使用go来实现类似erlang otp里面的gen_server功能
生活随笔
收集整理的這篇文章主要介紹了
使用go来实现类似erlang otp里面的gen_server功能
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
erlang比go要成熟,其中一大原因就是擁有otp工程,進程的管理可以通過專門的行為
模式去處理,例如gen_server,里面包含的6個回調函數init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3
來實現進程的一系列行為,例如啟動進程,異步調用,同步調用,響應,關閉進程等
先來看一段gen_server的內部實現代碼:
-module(server_templat -export([start/1]). -export([call/2, cast/2]). -export([init/1]).%%通用進程模式(可以認為是c/s模型的阻塞和非阻塞)start(Mod) ->spawn(server_template, init, [Mod]). init(Mod) ->register(Mod, self()),State = Mod:init(),loop(Mod, State).loop(Mod, State) ->receive{call, From, Req} ->{Res, State2} = Mod:handle_call(Req, State),From ! {Mod, Res},loop(Mod, State2);{cast, Req} ->State2 = Mod:handle_cast(Req, State),loop(Mod, State2);stop -> stop end.%% 接口部分 call(Name, Req) ->Name ! {call, self(), Req},receive %% 這里就是阻塞在等待返回,精辟!!!{Name, Res} ->Resend. cast(Name, Req) ->Name ! {cast, Req},ok.
能看懂erlang代碼的,應該明白上面是什么意思。
下面是我用go來實現的
package globalimport ("time" )type PidObj struct {Callback GenServerreqCh chan GenReqreplyCh chan Replystop bool }type GenReq struct {Method stringMsgData interface{}t inttime int32 }type Reply interface{}const (call = iotacasttimershutdown )// Start server func RegisterPid(pidName interface{}, callback GenServer) *PidObj {pidObj := &PidObj{Callback:callback}pidObj.reqCh = make(chan GenReq, 1024)pidObj.replyCh = make(chan Reply, 1024)callback.Start()go pidObj.loop()return pidObj }func (p *PidObj) loop() {for {req := <-p.reqChswitch req.t {case call:reply := p.Callback.HandleCall(req)p.replyCh <- replycase cast:p.Callback.HandleCast(req)case timer:p.Callback.HandleInfo(req)//time.AfterFunc(time.Duration(req.time) * time.Second, func() {// p.Callback.HandleInfo(req)//})case shutdown:p.stop = trueclose(p.reqCh)close(p.replyCh)p.Callback.Stop()return}} }func (p *PidObj) Call(method string, msg interface{}) (reply Reply) {p.reqCh <- GenReq{Method: method, MsgData: msg, t: call}reply = <-p.replyChreturn }func (p *PidObj) Cast(method string, msg interface{}) {p.reqCh <- GenReq{Method: method, MsgData: msg, t: cast} }func (p *PidObj) SendAfter(method string, seconds int32, msg interface{}) {time.AfterFunc(time.Duration(seconds) * time.Second, func() {if !p.stop {p.reqCh <- GenReq{Method: method, MsgData: msg, t: timer, time:seconds}}}) }func (p *PidObj) Stop() {p.reqCh <- GenReq{t: shutdown} }
?
定義接口:
package global// GenServer behavior needs to implement this interface type GenServer interface {Start()HandleCall(GenReq) ReplyHandleCast(GenReq)HandleInfo(GenReq)Stop() }
上面是用go實現了類似erlang的gen_server功能,使用的時候只需要實現Start, HandleCall,HandleCast,HandleInfo和Stop
這五個接口就可以了。
ok,that's all !
轉載于:https://www.cnblogs.com/huangliang-hb/p/9640408.html
總結
以上是生活随笔為你收集整理的使用go来实现类似erlang otp里面的gen_server功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (4opencv)OpenCV PR 成
- 下一篇: Spread表格组件For JAVA功能