Channel 與Goroutine
channel 與 goroutine 是互相搭配的, main function 本身就是一個 goroutine,另外可以使用 go func 創造 goroutine,可以想像 goroutine 是一個異步的 function,然後搭配 channel 使用,來傳遞資料。
當 channel 有資料傳入或需要從某個 channel 變數讀出資料時,那個 channel 作用域上面的 func (該 goroutine func) 會被 block ,然後把執行環境交給另一個 goroutine,直到 channel 有進有出後才會回到該 goroutine 作用環境。
這邊有一個重點是 buffered channel (初始化時有給第二個參數),寫入但沒讀出且沒超過 channel size時也不會阻塞,但讀出時如果 channel 是空的就會阻塞。
Channel 用法
package main
import (
"fmt"
)
func main() {
var test = make(chan int)
go func() { test <- 123 }() // 如果傳遞值到 channel 時不在 go func 內程式會卡住
msg := <-test // channel 是一個地址,要賦予給一個變數後才能讀出
fmt.Println(test)
fmt.Println(msg)
}
// 0xc000062060
// 123因為 Goroutine 是異步 async 的,所以要利用 channel 來傳資料
goroutine 部分也可加上參數寫為
Goroutine
以上及為Goroutine一般的樣子,go code 執行時通常為同步的,所以加上 go 等於是 async,讓他變為非同步執行。
如果有多個Goroutine 做相同的事,放在越後面的會先執行完畢
Goroutine 匿名 function
類似:go func() {} ()
有關於是否要傳參數進去匿名函式的部分可參考:
差別在於是否在 go func 內可存取到正確的外部變數
https://stackoverflow.com/a/30183893/4622645
Channel
使用 make 創建 channel
然後用 <-傳訊息到channel
make 第二個參數可以放channel大小
使用 var test chan int 這樣宣告的 channel 因為初始為 nil 無法使用
等待 Goroutine 執行完才結束程式的三種方法
time.Sleep
sync.WaitGroup
使用 channel
以下利用 c channel 確保 go test1 執行後才會結束程式
Channel select
可以用select 來做channel 的流程控制,select只有 channel可以用,類似於switch
另外
有關 channel deadlock
如果 make channel 後 沒給值 則會產生 deadlock
解法為使用 select 或是 給 make 第二個參數
用 func 接收多個 channel
持續接受 channel
當我們這樣寫,程式接收一次channel 就會結束
可以用 for 搭配 select 持續監聽
或是使用 for range
https://gobyexample.com/range-over-channels
推薦閱讀:
https://peterhpchen.github.io/2020/03/08/goroutine-and-channel.html
Last updated