Try   HackMD

Go - Goroutine,Channel

tags: Go,Goroutine,Channel

Goroutine、Channel 用途

Goroutine用於平行處理。也就是非同步執行
執行時如果是單線程(Single Thread)的,那麼執行時只會用到一個 CPU,如果你的電腦有兩個以上的 CPU,那可以想辦法讓他們分工合作。
分工合作需要溝通,Channel用途在於可以讓不同的Goroutine去溝通。

如何宣告Channel

搭配make()使用。

import "fmt" func main(){ s := make(chan string) //宣告一個 channel 變數 s <- "hello" //寫入 channel (sender) val <- s //讀取 channel (receiver) fmt.Println(val) }

分辨讀寫非常容易,請看 <- 符號放在哪邊,chan<- 指向自己就是寫,<-chan 離開自己就是讀,相當好分辨,如果 func 內讀寫都需要使用,則不需要使用任何箭頭符號,但是我會建議把讀寫的邏輯都拆開不同的 func 處理,對於閱讀上非常有幫助。

Write(chan<- int) Read(<-chan int) ReadWrite(chan int)

範例

  • 任務:加總數字
func Sum(numbers []int) int { total := 0 for _, n := range numbers { total += n } return total }
  • 任務:分兩個CPU加總數字
func SumTwoParallel(numbers []int) int { mid := len(numbers) / 2 ch := make(chan int) go func() { ch <- Sum(numbers[:mid]) }() go func() { ch <- Sum(numbers[mid:]) }() total := <-ch + <-ch return total } //結果 用兩個CPU運算比較快: // > go test -bench=^BenchmarkSumTwoParallel$ // goos: darwin // goarch: amd64 // BenchmarkSumTwoParallel-8 5000 300351 ns/op

確認有多少CPU

有多少CPU就全部教叫出來做事,可以使用 runtime.NumCPU() 取得 CPU 的數量,再把 slice 切割成 N 等份給不同的 goroutine 去加總,最後再統合到 total,這樣不管跑這段程式的電腦有幾個 CPU 都可以均勻分配。

func SumMaxParallel(numbers []int) int { nCPU := runtime.NumCPU() nNum := len(numbers) ch := make(chan int) for i := 0; i < nCPU; i++ { from := i * nNum / nCPU to := (i + 1) * nNum / nCPU go func() { ch <- Sum(numbers[from:to]) }() } total := 0 for i := 0; i < nCPU; i++ { total += <-ch } return total }

參考資料

https://larrylu.blog/golang-goroutine-parallel-processing-
https://blog.wu-boy.com/2020/01/when-to-use-go-channel-and-goroutine/