基礎篇簡單了介紹Channel&Goroutine的基本使用方法
接下來就是實際應用的問題了
實際例子上可能會有1-N個不等的chaneel
這時候就需要使用專門給channel使用的switch case,叫做Select
Select有幾個地方要注意
語法請看綜合範例2有演示
使用Goroutine最重要的
不要對routing的輸出順序以及時間做出假設
舉個簡單的例子,只要印出123
func main() {
go func() {
log.Println("123")
}()
//沒有暫停1秒鐘讓另一個routing準備好,有可能程式會直接結束而不會輸出任何東西
time.Sleep(1 * time.Second)
}
可以試試看把time.Sleep(1 * time.Second)給Remark,基本上是不會輸出任何東西,至少我是沒有成功過
因為Goroutine有極大的可能在main function執行完時而還沒有開始執行
所以Goroutine的closure就會什麼都沒有執行就結束了
這是最重要也是最難的部分
在使用Channel的時候最常要注意的事情就是deaklock
關於deaklock的情形可以參考:https://github.com/aceld/golang/blob/main/5%E3%80%81channel.md
基礎篇有提到UnBuffered Channel有著同步的特性
這種channel的兩端會等待著寫入與讀取,而且因為沒有Buffer,所以Channel的兩端會同步資料
func main() {
ch := make(chan bool)
go func() {
ch <- true
}()
// 雖然沒有time.Sleep等待goroutine執行
// 但最後有一個<-ch一直讀取channel
// 所以可以看到Print true
log.Println(<-ch)
}
可以使用for range方法讀取裡面的資料
func main() {
ch := make(chan int, 10)
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}()
for value := range ch {
log.Println(value)
}
}
從channel利用for loop讀取資料,可以搭配基礎篇服用
make channel的那一行可以加上cap玩看看,馬上就能知道UnBuffered & Buffered的差異
close(ch)那段最重要,可以試試看remark的結果,保證deadlock
func main() {
ch := make(chan int) // 可以加上cap,一樣可以正常跑程式,而且可以看出UnBuffered & Buffered的差異
go func() {
for i := 0; i < 10; i++ {
log.Println("Send value", i)
ch <- i
}
close(ch) // close channel很重要,沒有閉關的話,另一端一直在讀取,而沒有資料寫入,就會產生deadlock
}()
for {
val, ok := <-ch
if ok {
log.Println("Receive value", val)
} else {
break
}
}
}
執行這段程式碼有個重點
不要預期routing的執行時間,先後順序,一切的假設都不要有
for loop的部分是要一直讀取channel value
而當x==20時就會觸發事件s<-str
select接收到s channel的value時就會執行該case,跳出帶有LOOP tag的for loop
func main() {
str := "stop"
c := make(chan int)
s := make(chan string)
for i := 0; i < 50; i++ {
go func(x int) {
if x == 20 {
log.Println("goroutine will stop")
s <- str
} else {
log.Println("Send value", x)
c <- x
}
}(i)
}
LOOP:
for {
select {
case v, ok := <-c:
if ok {
log.Println("Select value", v)
}
case str := <-s:
log.Println(str)
break LOOP
default:
log.Println("wait")
}
}
}
在使用Goroutine&channel的時候要注意的地方大致可以歸類在以下幾點
然後要自己寫一遍,多deadlock幾次到差點想把筆電一分為二的時候你就會了(誤
其他還有Package sync & Package runtime,就等下一篇吧