使用Go 和 channel时的一个常见错误是忘记了nil channel类型有时会有所帮助。那么什么是nil channel ?
让我们从创建一个nil channel和等待接收消息的goroutine开始。这段代码应该做什么?
var ch chan int
<-ch
ch是chan int类型的。channel的零值为nil,ch的值就是nil。goroutine不会panic,但它将永远阻塞。
如果我们向nil channel发送消息,原理是相同的。这个 goroutine 永远阻塞:
var ch chan int
ch <- 0
那么Go允许从nil channel接收或发送消息的目的是什么呢?我们将通过一个具体的例子来讨论这个问题。
我们将实现一个func merge(ch1,ch2 <-chan int) <- chan int函数,将两个channel合并为一个channel。通过合并他们,我们预期从ch1或ch2接收到的每条消息都将被发送到返回的channel。如下图所示:
如何在Go中做到这一点呢?我们首先编写一个简单的实现,它启动一个goroutine并从两个channel接收消息(生成的channel将是一个带有一个元素的缓冲channel):
func merge(ch1, ch2 <-chan int) <-chan int {
ch := make(chan int, 1)
go func() {
for v := range ch1 {
ch <- v
}
for v := range ch2 {
ch <- v
}
close(ch)
}()
return ch
}
在另一个goroutine中,我们从两个channel接收消息,并且每条消息最终都在ch中发布。