为什么将通道输入参数设置为 nil?



我需要一些帮助来理解 Go 泛型提案示例。

特别是到目前为止,我在理解题为">通道"的提案的示例部分中的两段代码时遇到了麻烦:

我没有得到的第一点是在func Merge[T any](c1,c2 <-chan T) <-chan T的定义中找到的:该函数实例化一个将保存结果的chan T变量,然后它启动一个将处理精算合并的goroutine。

特别是,只要至少一个输入通道(要合并)不nil,就会运行一个无限循环。

法典:

// Merge merges two channels of some element type into a single channel.
func Merge[T any](c1, c2 <-chan T) <-chan T {
r := make(chan T)
go func(c1, c2 <-chan T, r chan<- T) {
defer close(r)
for c1 != nil || c2 != nil {
select {
case v1, ok := <-c1:
if ok {
r <- v1
} else {
c1 = nil
}
case v2, ok := <-c2:
if ok {
r <- v2
} else {
c2 = nil
}
}
}
}(c1, c2, r)
return r
}

在循环中,select语句梳理输入通道以查找有效接收的值(vn,ok:=<-cn表达式),然后是奇怪的部分:

如果通道发送有效值,合并并完成它(r<-vn),但如果通道报告它只是为其元素类型(ok==false)提供了零值,那么两个分支caseelse分支中的代码做了一些难以理解的事情(对我来说):它将通道变量设置为nil

那么,为什么允许合并的goroutine将其输入通道设置为nil。这难道不应该是负责输入通道cn的goroutine的义务吗?我显然错过了一些东西,请启发我。

将通道设置为nil将防止从那里开始执行该case。注意:只有函数参数设置为nil,这是函数的局部变量,通道对象保持不变。

该函数应循环,直到两个输入通道关闭,这可能不会同时发生。一旦通道关闭,从该通道接收可以立即继续。因此,如果一个通道是关闭的,从它接收的case可以始终从那里立即执行,不必要地使用高 CPU,并且还可以阻止从另一个非封闭通道接收(如果多个case通道准备就绪,则伪随机选择一个,请参阅当涉及多个通道时选择如何工作?

另一方面,如果一个(封闭的)通道设置为nil,它基本上将从select中取出,因为从nil通道接收会永远阻塞(所以只有另一个通道会从那里开始被监控)。有关通道公理,请参阅未初始化的通道的行为方式?

最新更新