2

我正在打这个电话:

add(Login, Pass, Role) ->
  gen_server:call(?SERVER, {add, Login, Pass, Role}).

我希望它与:

handle_call(State, {add, Login, Pass, Role}) ->
  io:format("add ~n"),
  Db = State#state.db,
  case lists:keyfind(Login, 1, Db) of
    false->
      io:format("add - reg new ~n"),
      {reply, registered, State#state{db=[{Login, erlang:md5(Pass), Role, ""}|Db]}};
     {Key, Result}-> 
      {reply, invalid_params, Db}  
  end.

但它总是去:

handle_call(_Request, _From, State) ->
  io:format("undef ~n"),
  Reply = ok,
  {reply, Reply, State}.

怎么了?

4

2 回答 2

3

在使用该gen_server行为的模块中,handle_call回调函数应采用三个参数。但是,您已经定义了两个不同的函数,handle_call/2并且handle_call/3. (在 Erlang 中,具有相同名称但采用不同数量参数的函数被视为不同的函数。)

由于gen_server模块只查找handle_call/3并忽略handle_call/2,因此始终调用您的“undef”函数。

要解决此问题,请将函数更改为采用(忽略的)第二个参数,并将请求放在首位,将状态放在最后:

handle_call({add, Login, Pass, Role}, _From, State) ->

并更改end.end;-.分隔不同的功能,同时;分隔同一功能的不同子句。

于 2015-01-20T11:35:34.223 回答
3

这种行为似乎是有效的,

handle_call有这样的规格:

-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
    State :: #state{}) ->
  {reply, Reply :: term(), NewState :: #state{}} |
  {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
  {stop, Reason :: term(), NewState :: #state{}}).

如果你可以看看这里 http://erlang.org/doc/man/gen_server.html#Module:handle_call-3

此外,对于 otp 默认行为,最好首先使用模板。对于 gen_server 例如https://gist.github.com/kevsmith/1211350

干杯!

于 2015-01-20T10:47:40.133 回答