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