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