原文链接: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
// 阻塞,直到goroutine中关闭channel
<-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.