%% @author Rolong<rolong@vip.qq.com> -module(bank_test1). -compile(export_all). %% 假设我开了3个银行账户: %% %% bank_server2:create_account(name1, 100). %% bank_server2:create_account(name2, 100). %% bank_server2:create_account(name3, 100). %% %% 练习1:如何获取name1对应的pid? %% %% 解答1:Pid1 = whereis(name1). %% %% %% 练习2:实现一个函数,计算以上3个账户余额的总和。 %% %% bank_sum(name1, name2, name3) -> Result. %% %% Result 为账号name1, name2, name3三个账户余额的总和。 %% 练习2解答思路: %% 1、先实现获取一个账户余额的API %% 1.1、用receive原语实现 bank_check(Name) -> Pid = whereis(Name), Pid ! {self(), check}, receive {Pid, Money} -> Money end. %% 1.2、用gen_server:call/2实现 bank_check2(Name) -> gen_server:call(Name, check). %% 2、实现bank_sum函数 %% 2.1、普通实现 bank_sum(N1, N2, N3) -> M1 = bank_check2(N1), M2 = bank_check2(N2), M3 = bank_check2(N3), M1 + M2 + M3. %% 2.2、递归实现 bank_sum2(Names) -> bank_sum2(Names, 0). bank_sum2([Name | T], Sum) -> Sum1 = Sum + bank_check2(Name), bank_sum2(T, Sum1); bank_sum2([], Sum) -> Sum.
-module(bank_server2). -behaviour(gen_server). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -export([create_account/2]). -define(I(F), io:format(F++"~n", [])). -define(I(F, A), io:format(F++"~n", A)). % -------------------------------------------------------------------- % API % -------------------------------------------------------------------- %%'银行开户,并存入初始金额 -spec create_account(Name, Money) -> any() when Name :: atom(), Money :: integer(). create_account(Name, Money)-> %% gen_server:start(Mod, Args, Options) {ok, Pid} = gen_server:start(?MODULE, [Money], []), %% 假设年费为10 Pid ! {yearly, 60}, erlang:register(Name, Pid). % -------------------------------------------------------------------- % Callback % -------------------------------------------------------------------- init([Money]) -> {ok, Money}. handle_call(check, _From, Money) -> {reply, Money, Money}; handle_call(_Request, _From, State) -> Reply = ok, {reply, Reply, State}. handle_cast(_Msg, State) -> {noreply, State}. %%'存钱 handle_info({deposit, AddMoney}, Money) -> NewMoney = Money + AddMoney, ?I("deposit money: ~w -> ~w", [Money, NewMoney]), {noreply, NewMoney}; %%. %%'取钱(可透支) handle_info({cash1, SubMoney}, Money) -> NewMoney = Money - SubMoney, ?I("deposit money: ~w -> ~w", [Money, NewMoney]), {noreply, NewMoney}; %%. %%'取钱(不可透支) handle_info({cash2, SubMoney}, Money) -> NewMoney = Money - SubMoney, case NewMoney > 0 of true -> %% 支取成功 ?I("deposit money: ~w -> ~w", [Money, NewMoney]), {noreply, NewMoney}; false -> %% 支取失败 提示余额不足 ?I("Insufficient balance, current money is ~w", [Money]), {noreply, Money} end; %%. %%'扣年费(这里假设10秒为一年) handle_info({yearly, Payment}, Money) -> Year = case get(year) of undefined -> put(year, 0), 0; Y -> YY = Y + 1, put(year, YY), YY end, erlang:send_after(60 * 1000, self(), {yearly, Payment}), Reply = if Money =< 0 -> %% 没有钱可以扣 Money; Year =:= 0 -> %% 还不到一年,不用扣 Money; true -> NewMoney = Money - Payment, case NewMoney > 0 of true -> %% 扣费成功 ?I("Yearly Payment: ~w -> ~w", [Money, NewMoney]), NewMoney; false -> %% 余额不足以扣年费,则扣到0为止 ?I("Yearly Payment: ~w -> ~w", [Money, 0]), 0 end end, {noreply, Reply}; %%. %%'查询 handle_info(check, Money) -> ?I("Current money is: ~w", [Money]), {noreply, Money}; handle_info({From, check}, Money) -> %% ?I("Send result to: ~w", [From]), From ! {self(), Money}, {noreply, Money}; %%. handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, _State) -> ok. code_change(_OldVsn, State, _Extra) -> {ok, State}.