GO程式設計模式08 PIPELINE

2021-10-13 10:16:30 字數 4147 閱讀 8449

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-0b2uy6di-1609292998770)(

本篇文章,我們著重介紹go程式設計中的pipeline模式。對於pipeline用過unix/linux命令列的人都不會陌生,他是一種把各種命令拼接起來完成乙個更強功能的技術方法。在今天,流式處理,函式式程式設計,以及應用閘道器對微服務進行簡單的api編排,其實都是受pipeline這種技術方式的影響,pipeline這種技術在可以很容易的把**按單一職責的原則拆分成多個高內聚低耦合的小模組,然後可以很方便地拼裝起來去完成比較複雜的功能。

這種pipeline的模式,我們在《go程式設計模式:修飾器》中有過乙個示例,我們在這裡再重溫一下。在那篇文章中,我們有一堆如withserverhead()withbasicauth()withdebuglog()這樣的小功能**,在我們需要實現某個http api 的時候,我們就可以很容易的組織起來。

原來的**是下面這個樣子:

)通過乙個**函式:

}我們就可以移除不斷的巢狀像下面這樣使用了:

)當然,如果你要寫出乙個泛型的pipeline框架並不容易,而使用go generation,但是,我們別忘了go語言最具特色的 go routine 和 channel 這兩個神器完全也可以被我們用來構造這種程式設計。

rob pike在 go concurrency patterns: pipelines and cancellation 這篇blog中介紹了如下的一種程式設計模式。

首先,我們需乙個echo()函式,其會把乙個整型陣列放到乙個channel中,並返回這個channel

func

echo

(nums [

]int

)<-

chan

intclose

(out)}(

)return out

}

然後,我們依照這個模式,我們可以寫下這個函式。

func

sq(in <-

chan

int)

<-

chan

intclose

(out)}(

)return out

}

func

odd(in <-

chan

int)

<-

chan

int}

close

(out)}(

)return out

}

func

sum(in <-

chan

int)

<-

chan

int out <- sum

close

(out)}(

)return out

}

然後,我們的使用者端的**如下所示:(注:你可能會覺得,sum()odd()sq()太過於相似。你其實可以通過我們之前的map/reduce程式設計模式或是go generation的方式來合併一下

var nums =

intfor n :=

range

sum(sq(

odd(

echo

(nums)))

)

上面的**類似於我們執行了unix/linux命令:echo $nums | sq | sum

同樣,如果你不想有那麼多的函式巢狀,你可以使用乙個**函式來完成。

type echofunc func([

]int)(

<-

chan

int)

type pipefunc func

(<-

chan

int)

(<-

chan

int)

func

pipeline

(nums [

]int

, echo echofunc, pipefns ... pipefunc)

<-

chan

intreturn ch

}

然後,就可以這樣做了:

var nums =

intfor n :=

range

pipeline

(nums, gen, odd, sq, sum)

動用go語言的 go routine和 channel還有乙個好處,就是可以寫出1對多,或多對1的pipeline,也就是fan in/ fan out。下面,我們來看乙個fan in的示例:

我們想通過併發的方式來對乙個很長的陣列中的質數進行求和運算,我們想先把陣列分段求和,然後再把其集中起來。

下面是我們的主函式:

func

makerange

(min, max int)[

]int

return a

}func

main()

for n :=

range

sum(

merge

(chans[:]

))}

再看我們的prime()函式的實現 :

func

is_prime

(value int

)bool

}return value >1}

func

prime

(in <-

chan

int)

<-

chan

int}

close

(out)}(

)return out

}

我們可以看到,

其中的merge**如下:

func

merge

(cs [

]<-

chan

int)

<-

chan

int wg.

done()

}(c)}go

func()

()return out

}

[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-db1px9fn-1609292998775)(

(全文完)

設計模式 0

設計模式包含了物件導向的精髓,懂了設計模式,你就懂了物件導向分析和設計的精要 對類來說的,即乙個類應該只負責一項職責。客戶端不應該依賴它不需要的介面,即乙個類對另乙個類的依賴應該建立在最小的介面上。高層模組不應該依賴低層模組,二者都應該依賴其抽象。低層模組盡量都要有抽象類或介面,或者兩者都有,程式穩...

go語言通道插入0 Go 語言通道

51reboot 運維開發 golang 課程 k8s 課程 python 自動化高階課程 python 基礎實戰課程 運維前端課程 課程試聽預約請掃碼 原子函式和互斥函式都能工作,但是依靠它們都不會讓編寫併發程式變得更簡單,更不容易出錯,或者更有趣。在 go 語言裡,你可以使用通道來傳送和接收需要...

Go 語言程式設計

課程名稱 go 語言程式設計 課程時間 2014年7月30日 週三 20 50 22 00 課程安排 20 50 21 00 通過郵件位址登入網路課堂 21 00 22 00 主題演講 徐立 與qa ps 課程諮詢 入qq群 csdn技術交流 群號是303806405 課程名稱 go 語言程式設計 ...