erlang gen server例子详解

实现简单的bank系统 创建用户 存钱 取钱

-module(my_bank).
-behaviour(gen_server).
-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).
-export([start/0,stop/0,new_account/1,deposit/2,withdraw/2]).
-define(SERVER,?MODULE).
% 启动一个名为{local my_bank}本地服务器, 回调模块为my_bank
start() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
% 对远程服务器的调用  关闭服务器 Msg是stop
stop() -> gen_server:call(?MODULE, stop).
% 对远程服务器的调用 给进程发送同步消息 Msg是{new,Who}
new_account(Who) -> gen_server:call(?MODULE,{new,Who}).
% 对远程服务器的调用 给进程发送同步消息 Msg是{add, Who, Amount}
deposit(Who,Amount) -> gen_server:call(?MODULE,{add, Who, Amount}).
% 对远程服务器的调用 给进程发送同步消息 Msg是{remove,Who,Amount}
withdraw(Who,Amount) -> gen_server:call(?MODULE,{remove,Who,Amount}).
%启动本地服务器后第一个调用的回调模块方法  返回{ok,State}说明成功启动服务器 State为handle_call/3的第三个参数
init([]) -> {ok,ets:new(?MODULE,[])}.
% handle_call 处理的格式
% spec handle_call(Request, From, Statu) ->
%                                   {reply, Reply, State} |
%                                   {reply, Reply, Statu, Timeout} |
%                                   {noreply, State} |
%                                   {noreply, State, TimeOut} |
%                                   {stop, Reason, Reply, State} |
%                                   {stop, Reason, State}
% 同步的回调函数 处理格式{reply, Reply, State}
handle_call({new, Who}, _From, Tab) ->
    Reply = case ets:lookup(Tab,Who) of
        [] -> ets:insert(Tab,{Who,0}),
            {welcome,Who};
        [_] -> {Who, you_already_are_a_customer}
    end,
    {reply, Reply, Tab};
% 同步的回调函数 处理格式{reply, Reply, State}
handle_call({add,Who,X}, _From, Tab) ->
    Reply = case ets:lookup(Tab, Who) of
        [] -> not_a_customer;
        [{Who,Balance}] ->
            NewBalance = Balance + X,
            ets:insert(Tab,{Who,NewBalance}),
            {thanks, Who, your_balance_is, NewBalance}
    end,
    {reply,Reply,Tab};
% 同步的回调函数 处理格式{reply, Reply, State}
handle_call({remove, Who, X}, _From, Tab) ->
    Reply = case ets:lookup(Tab,Who) of
        [] -> not_a_customer;
        [{Who,Balance}] when X =< Balance ->
            NewBalance = Balance - X,
            ets:insert(Tab,{Who,NewBalance}),
            {thanks, Who, your_balance_is, NewBalance};
        [{Who, Balance}] ->
            {sorry, Who, you_only_have, Balance, in_the_bank}
    end,
    {reply,Reply,Tab};
% 同步的回调函数 停止服务器  处理格式{stop, Reason, Reply, State} 第二个参数normal被用作terminate/2的第一个参数 第三个参数作为my_bank:stop/0的返回值
handle_call(stop, _From, Tab) -> {stop, normal, stopped, Tab}.
% handle_cast 处理的格式
% spec handle_cast(Msg, Statu) ->
%                       {noreply, State} |
%                       {noreply, State, TimeOut} |
%                       {stop, Reason, State}
% 异步的回调函数 处理格式{noreply, State}
handle_cast(_Msg, State) -> {noreply, State}.
% handle_info 处理的格式
% spec handle_info(Msg, Statu) ->
%                       {noreply, State} |
%                       {noreply, State, TimeOut} |
%                       {stop, Reason, State}
% 原生消息 不通过call或cast,直接发往服务器进程的消息 如:{'EXIT', Pid, Why} 或者知道此服务器pid的进程直接发过来的消息
handle_info(_Info, State) -> {noreply, State}.
% 以handle_开头的回调收到{stop, Reason, State} | {stop, Reason, Reply, State},或者服务器奔溃生成{'EXIT',reason},会调用此回调函数
terminate(_Reason, _State) -> ok.
% 再代码更改时转换进程状态
code_change(_OldVsn, State, _Extra) -> {ok, State}.

你可能感兴趣的:(erlang gen server例子详解)