初学者的Erlang / OTP行为
收藏

从《 Erlang和OTP的实际应用》一书中可以理解,行为一词指的是:

  • 行为接口,它是一组功能;
  • 行为实现,是应用程序专用代码(回调模块);
  • 行为容器,这是一个过程。

题:

Erlang / OTP初学者应该了解哪些行为?简而言之,有可能描述和理解OTP行为的概念吗?

在Elang / OTP上下文中,实际上什么是“回调函数”?

我们可以将行为实现中的回调视为Java中重写的方法吗?

该书说以下代码中与库函数“ gen_server:start_link / 4”相关的回调函数是“ Module:init / 1”。

这是否意味着使用init / 1我们调用gen_server:start_link / 4库函数?还是那意味着什么?

-module(tr_server).

-behaviour(gen_server).

-include_lib("eunit/include/eunit.hrl").

%% API
-export([
         start_link/1,
         start_link/0,
         get_count/0,
         stop/0
         ]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-define(SERVER, ?MODULE).
-define(DEFAULT_PORT, 1055).

-record(state, {port, lsock, request_count = 0}).


%%%===================================================================
%%% API
%%%===================================================================


%%--------------------------------------------------------------------
%% @doc Starts the server.
%%
%% @spec start_link(Port::integer()) -> {ok, Pid}
%% where
%%  Pid = pid()
%% @end
%%--------------------------------------------------------------------
start_link(Port) ->
    gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).

%% @spec start_link() -> {ok, Pid}
%% @doc Calls `start_link(Port)' using the default port.
s    tart_link() ->
    start_link(?DEFAULT_PORT).

%%--------------------------------------------------------------------
%% @doc Fetches the number of requests made to this server.
%% @spec get_count() -> {ok, Count}
%% where
%%  Count = integer()
%% @end
%%--------------------------------------------------------------------
get_count() ->
    gen_server:call(?SERVER, get_count).

%%--------------------------------------------------------------------
%% @doc Stops the server.
%% @spec stop() -> ok
%% @end
%%--------------------------------------------------------------------
stop() ->
    gen_server:cast(?SERVER, stop).


%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([Port]) ->
    {ok, LSock} = gen_tcp:listen(Port, [{active, true}]),
    {ok, #state{port = Port, lsock = LSock}, 0}.

handle_call(get_count, _From, State) ->
    {reply, {ok, State#state.request_count}, State}.

handle_cast(stop, State) ->
    {stop, normal, State}.

handle_info({tcp, Socket, RawData}, State) ->
    do_rpc(Socket, RawData),
    RequestCount = State#state.request_count,
    {noreply, State#state{request_count = RequestCount + 1}};
handle_info(timeout, #state{lsock = LSock} = State) ->
    {ok, _Sock} = gen_tcp:accept(LSock),
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

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

%%%===================================================================
%%% Internal functions
%%%===================================================================

do_rpc(Socket, RawData) ->
    try
        {M, F, A} = split_out_mfa(RawData),
        Result = apply(M, F, A),
        gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Result]))
    catch
        _Class:Err ->
            gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Err]))
    end.

split_out_mfa(RawData) ->
    MFA = re:replace(RawData, "\r\n$", "", [{return, list}]),
    {match, [M, F, A]} =
        re:run(MFA,
               "(.*):(.*)\s*\\((.*)\s*\\)\s*.\s*$",
                   [{capture, [1,2,3], list}, ungreedy]),
    {list_to_atom(M), list_to_atom(F), args_to_terms(A)}.

args_to_terms(RawArgs) ->
    {ok, Toks, _Line} = erl_scan:string("[" ++ RawArgs ++ "]. ", 1),
    {ok, Args} = erl_parse:parse_term(Toks),
    Args.


%% test

start_test() ->
    {ok, _} = tr_server:start_link(1055).

最佳答案

问:Erlang / OTP初学者应该了解哪些行为?是吗   可以描述和理解OTP行为的概念   简而言之?

行为通常在代码中使用,以便编译器可以根据其行为(即应用程序/主管/ gen_server / gen_event / gen_fsm)生成更直观的错误消息。

它使编译器能够给出特定于行为的错误消息,例如:gen_server

问:“回调函数”实际上是指   依兰/ OTP?

回调函数可以说是取自GUI编程(至少类似)。每当事件发生时。鼠标单击有一个单独的函数可以处理鼠标单击。

因此,每当例如。从另一个模块调用gen_server的导出函数,该函数可以具有具有不同模式的回调函数(handle_call / handle_cast)。

问:我们可以将行为实现中的回调视为方法吗?   在Java中被覆盖?

是的...也许...不:)

问:书中说该库的相关回调函数   以下代码中的函数“ gen_server:start_link / 4”是   '模块:init / 1'。

gen_server:start_link自己调用init函数,如w55回答...。(对不起,这个名字很大)。

希望我已经回答了您的所有问题:)

    公众号
    关注公众号订阅更多技术干货!