You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Erlang gen_server中{via,RegMod,ViaName}注册规范及示例求助

Erlang gen_server {via, RegMod, ViaName} 使用示例

1. 自定义注册表模块(RegMod)

先实现一个符合要求的注册表模块,这里用ETS表存储进程名与PID的映射:

-module(my_registry).
-export([register_name/2, unregister_name/1, whereis_name/1, send/2]).

% 初始化ETS表,首次注册时自动创建
init() ->
    ets:new(my_registry_table, [named_table, public, {read_concurrency, true}]).

% 注册进程名与PID
register_name(Name, Pid) when is_pid(Pid) ->
    case ets:insert_new(my_registry_table, {Name, Pid}) of
        true -> yes;
        false -> no
    end.

% 注销进程名
unregister_name(Name) ->
    ets:delete(my_registry_table, Name),
    ok.

% 根据进程名查找PID
whereis_name(Name) ->
    case ets:lookup(my_registry_table, Name) of
        [{Name, Pid}] -> Pid;
        [] -> undefined
    end.

% 向注册进程发送消息
send(Name, Msg) ->
    case whereis_name(Name) of
        undefined -> {badarg, {Name, Msg}};
        Pid -> Pid ! Msg, ok
    end.

2. gen_server 中使用 {via, RegMod, ViaName} 注册

编写一个简单的gen_server,启动时通过自定义注册表完成进程注册:

-module(my_server).
-behaviour(gen_server).
-export([start_link/0, get_pid/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

% 启动gen_server,使用{via, my_registry, my_server_1}作为注册标识
start_link() ->
    % 初始化注册表(未初始化时执行)
    case ets:info(my_registry_table) of
        undefined -> my_registry:init();
        _ -> ok
    end,
    gen_server:start_link({via, my_registry, my_server_1}, ?MODULE, [], []).

% 通过自定义注册表获取进程PID
get_pid() ->
    my_registry:whereis_name(my_server_1).

% gen_server回调实现
init([]) ->
    {ok, []}.

handle_call(_Request, _From, State) ->
    {reply, ok, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    % 进程终止时注销注册名
    my_registry:unregister_name(my_server_1),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

3. 测试验证

在Erlang Shell中执行以下命令验证:

% 编译模块
c(my_registry).
c(my_server).

% 启动gen_server
my_server:start_link().

% 通过注册表获取进程PID
my_server:get_pid(). % 返回对应的进程PID

% 通过注册表直接给进程发消息
my_registry:send(my_server_1, test_msg).

关键说明

  • RegMod必须实现的四个核心函数:register_name/2(绑定名称与PID)、unregister_name/1(注销名称)、whereis_name/1(查询PID)、send/2(向注册进程发送消息),函数行为需与global模块对应函数一致。
  • 示例用ETS实现了本地注册表,你也可以基于分布式存储、外部服务扩展出跨节点的进程注册逻辑。

内容的提问来源于stack exchange,提问作者孙海城

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:15:35