Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parameters Go:引用类型作为参数_Parameters_Go_Reference - Fatal编程技术网

Parameters Go:引用类型作为参数

Parameters Go:引用类型作为参数,parameters,go,reference,Parameters,Go,Reference,Go中的某些类型是引用类型:贴图、切片、通道、函数和方法 有时您需要使用指向引用的指针。比如说, type Stack []interface{} func (stack *Stack) Push(x interface{}) { *stack = append(*stack, x) } 您需要它,因为所有参数都是通过复制值来传递的,append()可能需要在片容量不够大的情况下重新分配内存。我明白了 第一个问题。地图类型如何?如果我有一个基于映射的自定义类型,如果需要插入或删除一些

Go中的某些类型是引用类型:贴图、切片、通道、函数和方法

有时您需要使用指向引用的指针。比如说,

type Stack []interface{}
func (stack *Stack) Push(x interface{}) { 
    *stack = append(*stack, x)
}
您需要它,因为所有参数都是通过复制值来传递的,
append()
可能需要在片容量不够大的情况下重新分配内存。我明白了

第一个问题。地图类型如何?如果我有一个基于
映射的自定义类型
,如果需要插入或删除一些key:value,我是否应该始终传递一个指向它的指针

第二个问题。其他参考类型如何<例如,代码>频道。我可以想象这样一种情况:我基于通道构建一个自定义类型,以对传递给通道的值实现一些自定义预处理。这里也需要指针吗


很抱歉,如果这是最基本的,但我真的想很好地掌握这个主题。

当您将所有内容都视为一个值时,规则相当简单,其中一些值内部包含指针

  • 切片:当您可能需要修改长度或容量时,请使用指针,这会更改切片的值
  • 贴图:不要使用指针,因为贴图值不会随修改而更改
  • 函数和方法:不要使用指针,函数值也会产生同样的效果
  • chan:不要使用指针

当然也有例外,比如,如果您希望能够完全交换一个映射,您需要使用指针来完成交换,但这种情况很少见

在“值类型”和“引用类型”之间并没有真正的二分法。“引用类型”仅用于描述其“值”完全由单个指针组成的值类型

映射和通道类型也是如此,它们基本上是指向内部结构的指针类型。但这对于切片并不完全正确,因为切片是一种复合类型(基本上是一种结构),由两个整数值(长度和容量)和一个指针(指向元素)组成。因此,对于通过指针访问的元素,它是一种“引用类型”,但对于长度和容量,它是一种“值类型”

附加到切片会根据其长度和潜在容量进行操作,因此需要更改切片的“值”,而就地分配给元素只是使用指针,因此不需要更改切片的“值”。如果希望某个切片的“值”更改指针以指向与另一个切片相同的对象(可以通过指定给该切片来实现),则可能还需要更改该切片的“值”


这与“参考类型”、地图和频道类似。更改映射或通道的“内容”(位于指针指向的内容中)不需要更改映射或通道的“值”。但是,如果要将指针更改为指向不同的基础映射或通道,则需要更改映射或通道变量的“值”。

将切片描述符与基础数组混淆。Go中没有引用类型。你有价值,你有指针。指针是一个“引用”。我不知道您的代码示例在做什么,但这肯定不是必需的。值得一读@evanmdonnal:no,这需要一个指针,因为追加可能会分配一个新数组,从而更改内部数据指针以及len和cap值@吉米:是的,我在操场上摆弄它的时候注意到了。这种必要性是由愚蠢的设计造成的。只需使用接收方和返回类型
Stack
定义方法,并执行
myStack=myStack.Push(x)
。或者更好的是,不要定义这些,因为这只是对系统RAM的浪费。它这样做的唯一原因是因为append将切片描述符作为值处理,并在操作完成后返回一个新的值。然后,他做了一些不一致的事情,使他的类型只不过是一个切片链,这个方法使用了指针。@evanmcdonnal:有很好的理由使用这样的自定义类型。例如,查看stdlib中的
container/heap
,或
sort
包(其中显示了不需要指针的位置)。在整个stdlib中,还有很多这样的自定义类型的例子,包括map和func类型。Go中没有引用类型。例如,切片不是参考类型,香奈儿也不是参考类型。“去相似”引用类型中最接近的类型是“贴图”。停止使用“引用类型”真的很有帮助:没有。你不一定要同步修改指向chan的指针。如果修改仅由一个goroutine进行,则不需要同步(就像所有指针一样)。@rightfold:如果一个goroutine中只有访问权限,则无需同步任何内容,但即使该值仅在一个goroutine中修改,该值的非同步并发读取仍然是竞争条件。但是,该条件与同一范围内的共享值相同。我将删除这个短语,因为它可能比有用的更容易混淆。虽然这是一个很好的答案,但它不应该以“值类型”和“引用类型”之间没有真正的二分法”开头。值类型(例如,在作为函数参数传递时涉及复制内容的结构)与类型(例如,映射)之间存在差异,后者不涉及复制作为函数参数传递的映射的内容。“差异”是否比“二分法”弱得多,而“二分法”允许在明确“存在差异”的情况下陈述“不存在二分法”,这是有争议和令人困惑的。