Golang 流水線設計模式實踐

流水線設計模式對於順序處理業務數據非常有用,可以以一致的方式直觀的定義對數據的處理流程。原文: Using a Pipeline Pattern in Golang[1]

到目前爲止,我已經將 Golang 整合到項目中有一段時間了,Golang 是一種非常強大的語言,我渴望在其生態系統中進一步磨練技能。

基於項目的特定需求,我需要實現流水線模式 (Pipeline Pattern),數據需要通過多個過濾器,以順序的方式進行處理。讓我解釋一下:

假設我們有一個很長的字符串。第一步是根據特定標準對其進行解析。接下來,需要對解析後的數據進行一些調整。隨後,將解析後的數據保存到數據庫中。正如你所見,有多個任務需要處理,而每個任務都是相互關聯的。

基礎流水線

在軟件開發中,可以用流水線設計模式 (pipeline design pattern) 來管理這種場景,該模式是爲順序處理對象修改而設計的。想象有一條裝配流水線,每個工位都是一段 " 管道 (pipe)",當某個物體通過整個流水線後,就發生了變化。從本質上講,流水線負責將值通過一系列可調用的" 管道 (pipe)"(無論是中間件、過濾器還是處理器) 進行順序傳遞。在將該值傳遞給序列中的後續管道之前,每個管道段都有可能改變該值。該模式在諸如請求處理、數據處理或轉換等場景中特別有用,提供了一種乾淨、可維護和可測試的方法。

作爲解決方案,我準備了一個簡單的 Golang 包,可以在處理流程中使用流水線模式,它建立在責任鏈 (chain of responsibility, CoR) 設計模式之上,可以將其安裝到項目中並使用:

go get github.com/izniburak/pipeline-go

包安裝之後,可以做一個簡單演示。首先需要一些新的結構體,這些結構體具有從PipeInterface實現的Handle方法。因爲 pipeline 包需要多個流水線,所以我們用Handle方法來運行每個流水線:

package main

import (
 "strings"
 "github.com/izniburak/pipeline-go"
)

type UpperCasePipe struct{}

func (u *UpperCasePipe) Handle(value pipeline.PipeValue, next pipeline.PipeNext) pipeline.PipeValue {
  // get value
  text := value.(string)
  capitalized := strings.ToUpper(text)
  return next(capitalized)
}

type TrimSpacePipe struct{}

func (t *TrimSpacePipe) Handle(value pipeline.PipeValue, next pipeline.PipeNext) pipeline.PipeValue {
  // get value
  text := value.(string)
  trimmed := strings.Trim(text, " ")
  return next(trimmed)
}

然後可以開始使用流水線:

package main

import (
 "fmt"
 "strings"
 "github.com/izniburak/pipeline-go"
)

type UpperCasePipe struct{}

func (u *UpperCasePipe) Handle(value pipeline.PipeValue, next pipeline.PipeNext) pipeline.PipeValue {
  // get value
  text := value.(string)
  capitalized := strings.ToUpper(text)
  return next(capitalized)
}

type TrimSpacePipe struct{}

func (t *TrimSpacePipe) Handle(value pipeline.PipeValue, next pipeline.PipeNext) pipeline.PipeValue {
  // get value
  text := value.(string)
  trimmed := strings.Trim(text, " ")
  return next(trimmed)
}

func main() {
  text := "   buki.dev   "

  pipes := []pipeline.PipeInterface{
    new(UpperCasePipe),
    new(TrimSpacePipe),
  }
  result := pipeline.Send(text).Through(pipes).ThenReturn()

  fmt.Println(result) // BUKI.DEV
}

如你所見,我們使用了兩個不同的管道,分別是UpperCasePipeTrimSpacePipe。輸入是 buki.dev ,兩邊都有空格,輸出是BUKI.DEV

就是這樣。流水線非常有用,是吧?

可以在 GitHub 上查看 pipeline 包 [2]。


你好,我是俞凡,在 Motorola 做過研發,現在在 Mavenir 做技術工作,對通信、網絡、後端架構、雲原生、DevOps、CICD、區塊鏈、AI 等技術始終保持着濃厚的興趣,平時喜歡閱讀、思考,相信持續學習、終身成長,歡迎一起交流學習。爲了方便大家以後能第一時間看到文章,請朋友們關注公衆號 "DeepNoMind",並設個星標吧,如果能一鍵三連 (轉發、點贊、在看),則能給我帶來更多的支持和動力,激勵我持續寫下去,和大家共同成長進步!

參考資料

[1]

Using a Pipeline Pattern in Golang: https://tech.jotform.com/pipeline-go-pipeline-pattern-in-golang-5a51e5d811a

[2]

pipeline-go: https://github.com/izniburak/pipeline-go

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/ka4o9Mfq2gyHJ_Z_gkR-vg