一.什么是behavior?
使用erlang編程的人都知道OTP,而OTP里面創建進程的時候,常用的有四大behaviour, supervisor、gen_server、gen_fsm、gen_event.什么是behaviour?他是做什么用?
首先,寫這篇文章之前我上谷歌查過人家對behavior的定義,當然,非官方,我一直沒找著官方定義,如果有人有一個比較確切的定義,麻煩告訴我,大家共同學習嘛.
http://stackoverflow.com/questions/6488002/how-to-define-customized-behavior-in-erlang-and-what-can-it-do-for-you 在這篇文章中指明了,在erlang 的編譯器中,behavior的作用是用來定義一個規約.定義好這個規約之后,任何遵守這個規約的模塊,必須按照規約中的要求,使用-export([ ]). 導出對應的函數,導出完這些函數后,這些導出函數的調用由behaviour統一支配.為什么要這么做呢?參照一句話:
TheOTP Design Principles is a set of principles for how to structure Erlang code in terms of processes, modules and directories.
這句話來自官方文檔OTP設計原則的第一句話.那么,behaviour只不過是實現代碼組織的一種手段而已.那么,再應用一句:
The idea is to divide the code for a process in a generic part (a behaviour module) and a specific part (acallback module).
behaviour就是把代碼分成通用部分,以及每一個回調模塊需要去做的特殊部分.這樣就好理解了,于是使用-behaviour()定義的模塊都是這一個behaviour的回調模塊.
二.erlang可以自定義behavior嗎?
這是可以的,如果大家代碼讀得多了,就應該發現,很多優秀的開源項目中就自定義了behaviour,例如經典的rabbitmq中,就將erlang自帶的 gen_server 進行了改進,寫了一個 gen_server2 的 behaviour,因為gen_server中的消息隊列是一個普通消息隊列不能滿足需要,改進后的gen_server2使用了帶優先級的消息隊列.當然了,erlang本身的底層代碼里面,也有寫過很多behaviour,不細說了,總之,erlang可以自定義behaviour
三.是behavior還是behaviour
在寫代碼的時候發現有時候用的是behaviour,而又有的時候用的是behavior.這兩個詞應該是美式英語和英式英語的區別吧,說明一點:在定義behaviour的時候,erlang是親美一派的,必須用behaviour,使用behavior將報錯,而在使用已經定義好的behavior模塊的時候,對編譯器而言,兩個詞都可以用.....真是很詭異的
四.怎么定義一個behaviour?
要定義一個behaviour,首先你要創建一個模塊,它必須導出 behaviour_info/1 這個函數(注意必須帶u),函數的定義如下:
behaviour_info(callbacks) ->
[{foo, 0}, {bar, 1}, {baz, 2}];
behavior_info(_) ->
undefined.
當傳入callbacks參數,必須返回一個包含導出函數和參數個數的列表
這些導出函數,就是這些回調模塊所特有的部分,而通用部分,則寫在behaviour中.比如,gen_server 中,當一個進程收到一個消息,在behaviour行為模型中,它會處理大部分通用的邏輯,比如,如果是call消息,它會根據handle_call 函數的返回值對From進程發送返回消息,同時,處理完消息后,它會繼續循環進行消息處理,不多說,亮代碼:
handle_msg({‘$gen_call’, From, Msg}, GS2State = #gs2_state { mod = Mod,
state = State,
name = Name,
debug = Debug }) ->
case catch Mod:handle_call(Msg, From, State) of %%大家注意了,這里就是調用了模塊中的handle_call()函數,并且獲取它的返回值
{reply, Reply, NState} ->
Debug1 = common_reply(Name, From, Reply, NState, Debug),
loop(GS2State #gs2_state { state = NState,%%在這里,處理完一條消息之后,繼續轉入到循環中去
time = infinity,
debug = Debug1 });
{reply, Reply, NState, Time1} ->
Debug1 = common_reply(Name, From, Reply, NState, Debug),
loop(GS2State #gs2_state { state = NState,
time = Time1,
debug = Debug1});
{noreply, NState} ->
Debug1 = common_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loop(GS2State #gs2_state {state = NState,
time = infinity,
debug = Debug1});
{noreply, NState, Time1} ->
Debug1 = common_debug(Debug, fun print_event/3, Name,
{noreply, NState}),
loop(GS2State #gs2_state {state = NState,
time = Time1,
debug = Debug1});
{stop, Reason, Reply, NState} ->
{‘EXIT’, R} =
(catch terminate(Reason, Msg,
GS2State #gs2_state { state = NState })),
reply(Name, From, Reply, NState, Debug),
exit(R);
Other ->
handle_common_reply(Other, Msg, GS2State)
end;
源代碼是最好的老師!有時候我想,想要了解gen_server ,為什么放著gen_server.erl這個源代碼不去讀,卻寧愿相信百度上,或者谷歌上,或者別人說的話呢?還有什么比代碼中的事實更真實嗎?更可信的嗎?
五.怎么使用behaviour?
使用的時候,需要在模塊開頭 使用:
-behaviour(behaviour_name).
同時需要定義并且使用-export([ ])導出,這個behaviour所要求的導出函數.
注意了,一個模塊是可以有多個-behaviour(behaviour_name). 的,也就是說,這個模塊的一部分函數既是A behaviour的回調模塊,又是B behaviour 的回調模塊.
六.何時使用behaviour?
最后這個話題就比較廣了,這是一個沒有絕對意義正確的問題,在erlang OTP 中,那幾個主要進程的實現都是使用behaviour 封裝了基本的操作.
對于behaviour和進程的關系,我曾經有過這樣的疑惑,只有在創建進程的時候才能用behaviour嗎?最后得到的結論是:沒有關系! 因為在erlang的設計理念當中,模塊與進程,這是兩個概念,而behaviour與模塊的組織相關,因此它與進程沒有必然聯系.
ERLANG環境搭建
1.到erlang的官網下載erlang的源碼包,圖方便,直接在win8.1上安裝了。可以自己根據自己的需求自行下載。
2.我這里直接下載的第五個,64位的windows,下一步下一步安裝完畢后,把erlang的bin目錄添加到系統的環境變量PATH中。
3.進入cmd環境下測試erlang shell環境,確保erlang安裝成功。
看到上面的情況就說明安裝成功了,按CTRL+C退出,關閉cmd界面
4.安裝erlang的ide,以前學過vs的,還是很喜歡vs的強大的,所以本來想找有沒有vs的插件的, 結果找的沒有,說是只有一個代碼高亮顯示的插件,沒有智能提示的話,本人還是很煩惱的,然后就自然選擇了eclipse,插件選擇http://erlide.org/update,如何在eclipse安裝插件這里就不多做啰嗦,有問題的朋友可以百度一下,你就知道!
5.剛裝好插件,迫不及待的去創建erlang項目了,可惜選擇創建項目卡頓了一下,就提示錯誤,無奈各種搜索錯誤,心想難道是不兼容最新的eclipse? 百度了一會,突然說是還要配置Installed runtimes,立馬就去修改,具體修改方法 Menu -> [Window]->[preference] 找到 [Erlang]->[Installed runtimes],點擊add選擇erlang路徑。
6.嘗試File -> New ->Erlang Project,成功彈出創建對話框,欣喜ing,然后輸入HelloWorld,下一步下一步創建第一個說世界項目。
自此,erlang的開發環境算基本OK了,以后有空的話再寫下自己GOLANG的開發環境的搭建過程,希望能夠幫助到您!
評論
查看更多