條目處理管道的介面擁有額外的 ItemProcessors、Send、FailFast 和 SetFailFast 方法,因此其實現型別 myPipeline 的基本結構是這樣的:
//條目處理管道的實現型別
type myPipeline struct {
//元件基礎範例
stub.ModuleInternal
//條目處理器的列表
itemProcessors []module.ProcessItem
//處理是否需要快速失敗
failFast bool
}
程式碼包 gopcp.v2/chapter6/webcrawler/module/local/pipeline 是存放該型別的位置,其中 New 函數與 analyzer 包中的 New 函數在引數宣告列表和引數檢查方式方面都很類似,這裡就省略不講了。相關程式碼包的程式碼大家可以在網路硬碟(連結:https://pan.baidu.com/s/1yzWHnK1t2jLDIcTPFMLPCA 提取碼:slm5)中下載。
除此之外,分析器中有 HTTP 響應解析函數的列表,而條目處理管道中有條目處理常式(以下簡稱處理常式)的列表。因此,後者的 Send 方法與前者的 Analyze 方法在實現流程方面也大體一致。只不過由於條目處理管道存在對快速失敗的設定,所以在流程細節上它們仍有不同。
另外,還要注意,條目處理管道需要讓條目依次經過那幾個處理常式的加工。也就是說,第一個處理常式的處理結果要作為第二個處理常式的引數,第二個處理常式的處理結果要作為第三個處理常式的引數,以此類推。這是由條目處理管道的設計決定的,也是“管道” 一詞要表達的含義。
相比之下,分析器中的解析函數對 HTTP 響應的解析是相互獨立的。下面是 Send 方法的程式碼片段,體現了上述不同:
func (pipeline *myPipeline) Send(item.module.Item) []error {
//省略部分程式碼
var errs []error
//省略部分程式碼
var currentItem = item
for _, processor := range pipeline.itemProcessors {
processedItem, err := processor(currentItem)
if err != nil {
errs = append(errs, err)
if pipeline.failFast {
break
}
}
if processedItem != nil {
currentltem = processedItem
}
}
//省略部分程式碼
return errs
}
ItemProcessors、FailFast和SetFailFast方法的實現都非常簡單,在此略過。
至此,我已經講解了元件相關介面的絕大部分實現,同時闡述了一些我在 Go語言程式編寫和軟體設計方面的經驗,也展示了一些編碼技巧。