久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      golang的極簡流式編程

      傳統(tǒng)的過程編碼方式帶來的弊端是顯而易見,我們經(jīng)常有這樣的經(jīng)驗,一段時間不維護的代碼或者別人的代碼,突然拉回來看需要花費較長的時間,理解原來的思路,如果此時有個文檔或者注釋寫的很好的話,可能花的時間會短一點,但是即便如此,很多調(diào)用關(guān)系也要反復確認才敢動手改動。

      下面是一斷偽代碼,描述過程編碼方式:

      func A(){     B()     C() }  func B(){    do something     D() } func C(){    do something     } func D(){    do something } func main(){     A() }

      對照流式風格的寫法:

      NewStream(). Next(A). Next(B). Next(D). Next(C). Go()

      當過程風格的代碼調(diào)用關(guān)系復雜時,程序員需要謹慎仔細行事,相比較流式風格的代碼比較清爽,主干清晰,尤其是應(yīng)對需求變更的時候優(yōu)勢明顯。

      java8里借用lamda表達式實現(xiàn)了一套比較完美的流式編程風格,golang作為一個簡潔的語言還沒有官方的流式風格的包(可能早就有了,可能是我孤陋寡聞了)有點可惜了。

      我參考了gorequest的代碼,實現(xiàn)了一套相對比較通用的流式風格的包,實現(xiàn)原理是組成一個任務(wù)鏈表,每一個節(jié)點都保存了首節(jié)點和下一個節(jié)點以及該節(jié)點應(yīng)該執(zhí)行的回調(diào)函數(shù)指針,流式任務(wù)啟動后從第一個節(jié)點開始,逐個執(zhí)行,遇到異常則終止流式任務(wù),直到執(zhí)行到最后一個,結(jié)束任務(wù)鏈。先來看看代碼吧:

      package Stream  import (    "errors"     "fmt")/** 流式工作原理: 各個任務(wù)都過指針鏈表的方式組成一個任務(wù)鏈,這個任務(wù)鏈從第一個開始執(zhí)行,直到最后一個 每一個任務(wù)節(jié)點執(zhí)行完畢會將結(jié)果帶入到下一級任務(wù)節(jié)點中。 每一個任務(wù)是一個Stream節(jié)點,每個任務(wù)節(jié)點都包含首節(jié)點和下一個任務(wù)節(jié)點的指針, 除了首節(jié)點,每個節(jié)都會設(shè)置一個回調(diào)函數(shù)的指針,用本節(jié)點的任務(wù)執(zhí)行, 最后一個節(jié)點的nextStream為空,表示任務(wù)鏈結(jié)束。 **///定回調(diào)函數(shù)指針的類型type CB func(interface{}) (interface{}, error)//任務(wù)節(jié)點結(jié)構(gòu)定義type Stream struct {    //任務(wù)鏈表首節(jié)點,其他非首節(jié)點此指針永遠指向首節(jié)點     firstStream *Stream    //任務(wù)鏈表下一個節(jié)點,為空表示任務(wù)結(jié)束     nextStream *Stream    //當前任務(wù)對應(yīng)的執(zhí)行處理函數(shù),首節(jié)點沒有可執(zhí)行任務(wù),處理函數(shù)指針為空    cb CB }/** 創(chuàng)建新的流 **/func NewStream() *Stream {    //生成新的節(jié)點     stream := &Stream{}    //設(shè)置第一個首節(jié)點,為自己    //其他節(jié)點會調(diào)用run方法將從firs指針開始執(zhí)行,直到next為空     stream.firstStream = stream    //fmt.Println("new first", stream)     return stream }/** 流結(jié)束 arg為流初始參數(shù),初始參數(shù)放在End方法中是考慮到初始參數(shù)不需在任務(wù)鏈中傳遞 **/func (this *Stream) Go(arg interface{}) (interface{}, error) {    //設(shè)置為任務(wù)鏈結(jié)束     this.nextStream = nil    //fmt.Println("first=", this.firstStream, "second=", this.firstStream.nextStream)    //檢查是否有任務(wù)節(jié)點存在,存在則調(diào)用run方法    //run方法是首先執(zhí)行本任務(wù)回調(diào)函數(shù)指針,然后查找下一個任務(wù)節(jié)點,并調(diào)用run方法     if this.firstStream.nextStream != nil {        return this.firstStream.nextStream.run(arg)     } else {        //流式任務(wù)終止         return nil, errors.New("Not found execute node.")     } } func (this *Stream) run(arg interface{}) (interface{}, error) {    //fmt.Println("run,args=", args)    //執(zhí)行本節(jié)點函數(shù)指針     result, err := this.cb(arg)    //然后調(diào)用下一個節(jié)點的Run方法     if this.nextStream != nil && err == nil {        return this.nextStream.run(result)     } else {        //任務(wù)鏈終端,流式任務(wù)執(zhí)行完畢         return result, err     } } func (this *Stream) Next(cb CB) *Stream {    //創(chuàng)建新的Stream,將新的任務(wù)節(jié)點Stream連接在后面     this.nextStream = &Stream{}    //設(shè)置流式任務(wù)鏈的首節(jié)點     this.nextStream.firstStream = this.firstStream    //設(shè)置本任務(wù)的回調(diào)函數(shù)指針     this.nextStream.cb = cb    //fmt.Println("next=", this.nextStream)     return this.nextStream }

      下面是一個流式的例子,這里以早上起床到出門上班的流程為例:

      //起床func GetUP(arg interface{}) (interface{}, error) {     t, _ := arg.(string)     fmt.Println("鈴鈴.......", t, "###到時間啦,再不起又要遲到了!")    return "醒著的狀態(tài)", nil }//蹲坑func GetPit(arg interface{}) (interface{}, error) {     s, _ := arg.(string)     fmt.Println(s, "###每早必做的功課,蹲坑!")    return "舒服啦", nil }//洗臉func GetFace(arg interface{}) (interface{}, error) {     s, _ := arg.(string)     fmt.Println(s, "###洗臉很重要!")    return "臉已經(jīng)洗干凈了,可以去見人了", nil }//刷牙func GetTooth(arg interface{}) (interface{}, error) {     s, _ := arg.(string)     fmt.Println(s, "###刷牙也很重要!")    return "牙也刷干凈了,可以放心的大笑", nil }//吃早飯func GetEat(arg interface{}) (interface{}, error) {     s, _ := arg.(string)     fmt.Println(s, "###吃飯是必須的(需求變更了,原來的流程里沒有,這次加上)")    return "吃飽飽了", nil }//換衣服func GetCloth(arg interface{}) (interface{}, error) {     s, _ := arg.(string)     fmt.Println(s, "###還要增加一個換衣服的流程!")    return "找到心儀的衣服了", nil }//出門func GetOut(arg interface{}) (interface{}, error) {     s, _ := arg.(string)     fmt.Println(s, "###一切就緒,可以出門啦!")    return "", nil  } func main() {     NewStream().         Next(GetUP).         Next(GetPit).         Next(GetTooth).         Next(GetFace).         Next(GetEat).//需求變更了后加上的        Next(GetCloth).         Next(GetOut).         Go("2018年1月28日8點10分") }

      從上面的代碼看,流式編碼風格對于一個大的任務(wù)被分解成多個小任務(wù)后,在代碼層面是非常直觀的,不在費勁心思去查找到底那個調(diào)用了那個,另外對于需求的變更更容易了,上例中的吃早飯是第一個版本沒有實現(xiàn)的,客戶說了早上要吃飯,不然容易的膽結(jié)石,第二版要加上,我們需要完成吃飯的函數(shù),然后加到響應(yīng)的位置。相對過程編碼簡單了不少。

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號