Go 将通道作为形式参数传递给闭包与使用父范围中定义的通道之间的区别?
以这两个片段为例Go 将通道作为形式参数传递给闭包与使用父范围中定义的通道之间的区别?,go,Go,以这两个片段为例 使用父范围中的out chan 将chan作为结束的正式论据传递出去 我知道向闭包传递参数会创建闭包的一个副本,并且使用父作用域中的某些内容会使用引用,所以我想知道在按副本传递的情况下,这在内部是如何工作的。是否有两个通道,一个在父作用域中,另一个副本传递给闭包,当闭包中的副本写入时,该值的副本也在父作用域中的通道中生成?因为我们正在将父作用域中的out chan返回给调用者,并且值将仅从该通道使用。chan是一种引用类型,就像切片或映射一样。go中的所有内容都是按值传
- 使用父范围中的out chan
- 将chan作为结束的正式论据传递出去
我知道向闭包传递参数会创建闭包的一个副本,并且使用父作用域中的某些内容会使用引用,所以我想知道在按副本传递的情况下,这在内部是如何工作的。是否有两个通道,一个在父作用域中,另一个副本传递给闭包,当闭包中的副本写入时,该值的副本也在父作用域中的通道中生成?因为我们正在将父作用域中的out chan返回给调用者,并且值将仅从该通道使用。
chan
是一种引用类型,就像切片或映射一样。go中的所有内容都是按值传递的。当您将chan作为参数传递时,它将创建引用相同值的引用副本。在这两种情况下,通道都将从父范围中消耗。但有两个不同之处。考虑下面的代码:
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
ch <- 1
ch = nil
wg.Done()
}()
<-ch // we can read from the channel
wg.Wait()
// ch is nil here because we override the reference with a null pointer
ch:=make(chan int)
var wg sync.WaitGroup
工作组.添加(1)
go func(){
哦,那么这两种情况本质上是相同的?@sumopal有一个区别。添加到一个答案中。事实上,完全相同代表一个切片、一个地图或一个指针。
func Worker() {
out := make(chan int)
func(out chan int) {
// write something to the channel
}(out)
return out
}
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
ch <- 1
ch = nil
wg.Done()
}()
<-ch // we can read from the channel
wg.Wait()
// ch is nil here because we override the reference with a null pointer
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func(ch chan int) {
ch <- 1
ch = nil
wg.Done()
}(ch)
<-ch // we still can read from the channel
wg.Wait()
// ch is not nil here because we override the copied reference not the original one
// the original reference remained the same