Concurrency 通道是否通过引用隐式传递
go tour的频道示例如下:Concurrency 通道是否通过引用隐式传递,concurrency,go,channels,pass-by-reference,Concurrency,Go,Channels,Pass By Reference,go tour的频道示例如下: 主程序包 输入“fmt” 函数和(a[]整数,c chan整数){ 总和:=0 对于u,v:=范围a{ 总和+=v } c你可以说是的,但是说“信道c在求和函数中被修改”并不是真正正确的术语。信道发送和接收并不是真正的修改 请注意,切片和贴图的行为方式类似,有关详细信息,请参见 另外,“通过引用传递”意味着可以在sum中对c赋值,这将在sum之外改变它的值(相对于它的基础数据),情况并非如此。通道变量是引用,但这取决于您对“引用”的定义。永远不要提及引用类型 su
主程序包
输入“fmt”
函数和(a[]整数,c chan整数){
总和:=0
对于u,v:=范围a{
总和+=v
}
c你可以说是的,但是说“信道c在求和函数中被修改”并不是真正正确的术语。信道发送和接收并不是真正的修改
请注意,切片和贴图的行为方式类似,有关详细信息,请参见
另外,“通过引用传递”意味着可以在sum
中对c
赋值,这将在sum之外改变它的值(相对于它的基础数据),情况并非如此。通道变量是引用,但这取决于您对“引用”的定义。永远不要提及引用类型
sum
函数中未“修改”任何通道(变量)。发送到通道会更改其状态
换句话说,是的,通道被实现为指向某个运行时结构的指针
编辑:上面这句话的意思是:“注意,对于引用语义来说,这并不是绝对必要的。”,即“not”一词消失了。很抱歉,任何最终造成的混乱。从技术上讲,它们是被复制的,因为当您使用make
时,您在堆上分配了一些东西,因此从技术上讲,它在幕后是一个指针。但是指针类型没有公开,因此可以将其视为引用类型
编辑:从规范:
内置函数make采用类型T,该类型必须是片、映射或通道类型,后面可选地跟有特定于类型的表达式列表。它返回类型T(而不是*T)的值。内存初始化如初始值部分所述
通道必须先初始化,然后才能使用。Make执行此操作,以便将其用作引用类型
这基本上意味着,您可以将其传递到函数中,并对其进行写入或读取。一般的经验法则是,如果使用make
、new
或&
,您可以将其传递到另一个函数,而无需复制底层数据
因此,以下是“参考”类型:
- 切片
- 地图
- 渠道
- 指针
- 功能
传递到函数中时,仅复制数据类型(数字、布尔值和结构等)。字符串是特殊的,因为它们是不可变的,但不是按值传递的。这意味着以下内容无法按预期工作:
type A struct {
b int
}
func f(a A) {
a.b = 3
}
func main() {
s := A{}
f(s)
println(s.b) // prints 0
}
Go中的所有内容都是通过值传递和分配的。某些内置类型,包括通道类型和映射类型,表现为指向某些隐藏内部结构的不透明指针。可以通过对通道或映射的操作来修改该内部结构。它们开始时为nil
,类似于nil
poiINTER.是的,Go中的引用类型是slice
、map
和channel
。传递这些类型时,您正在复制引用。(字符串也作为引用类型实现,尽管它们是不可变的。)@tjameson:make并不意味着堆分配,而slice实际上是作为一个结构实现的,并在传递时被复制。@斜视-对。array
,我的意思是make([]int,5)
,但我刚刚意识到这在技术上更像是一个切片。我的不好。@jml-回顾规范,我想在技术上不是这样的。我会编辑。指针不是真正的引用类型,它们是碰巧用作引用的值类型。slice
的行为不像map
和chan
d中的“不透明指针”o、 如果使用参数a[]string
调用的函数将其更改为a=append(a,x)
,则调用者将看不到长度的更改。对预先存在的索引的更改是可见的(除非在同一个func中它前面的append
导致重新分配)。
type A struct {
b int
}
func f(a A) {
a.b = 3
}
func main() {
s := A{}
f(s)
println(s.b) // prints 0
}