原文鏈接:https://medium.com/@matryer/golang-advent-calendar-day-two-starting-and-stopping-things-with-a-signal-channel-f5048161018
使用channel在goroutines中傳遞信號
在go裏,使用channel
在goroutines
間交流數據是一個很好的方式,但是也可以使用它去傳遞信號。
傳遞信號時,使用空的struct
作爲channel
的類型,只表示信息傳遞。更有趣的是,它不會佔用內存空間,一個空的struct沒有任何的屬性。你可以到這裏查看
這是一個信號channel
:
var signal chan struct{}
可以使用go的內置make
函數初始化它:
signal := make(chan struct{})
代碼會被阻塞,直到某些值被髮送到channel
中:
<-signal
在這個例子下,我們不在意它的值,這也是爲什麼我們不傳遞任何值給它。
類似的,在一個select
語句,當收到goroutine
外的信號時,可以使用一個關閉的channel
去運行不同的代碼。
等待某些操作的結束
通過一個阻塞的信號channel
,可以等待另一個goroutine
中的任務結束:
done := make(chan struct{})
go func() {
doLongRunningThing()
close(done)
}()
// do some other bits
// wait for that long running thing to finish
<-done
// do more things
同一時間執行多個任務
假設有很多的goroutine
在排隊,可以通過關閉一個信號channel
去觸發它們在同一個時間開始執行:
start := make(chan struct{})
for i := 0; i < 10000; i++ {
go func() {
<-start // wait for the start channel to be closed
doWork(i) // do something
}()
}
// at this point, all goroutines are ready to go - we just need to
// tell them to start by closing the start channel
close(start)
暫停任務
類似的,也可以使用它去暫停goroutines
。當下面的goroutine
從一個email channel
中收到了數據會進行發送郵件的操作:
loop:
for {
select {
case m := <-email:
sendEmail(m)
case <-stop: // triggered when the stop channel is closed
break loop // exit
}
}
如果stop channel
被關閉了,for循環就會退出,就不會有更多的郵件被髮送。
- 更多的
channel
可以做的事件,到這裏查看:VIDEO: GopherCon 2014 A Channel Compendium by John Graham-Cumming.