在经历了9年的C++开发之后,我正在探索Go。在C++中,除了内置类型的变量外,按值传递函数的参数是一种不好的做法,因为会造成性能损失:参数的所有字段都将被复制,并且在大多数情况下,这将是一个非常昂贵的操作。
Go也是这样吗?仅通过值传递"this“以将"const”语义赋值给方法看起来代价很高。Go编译器是否足够聪明,可以防止变量在第一次修改之前被复制?为什么在Go中按值传递"this“不像在C/C++中那样是一种反模式?
发布于 2013-03-10 23:07:49
其他答案都很好,但在我看来,缺少一些信息。
Go中的接收器只是语法糖,如以下code所示
package main
import "fmt"
type Something struct {
Value int
}
func (s *Something) ChangeValue(n int) {
s.Value = n
}
func main() {
o := new(Something) // o is of type *Something
fmt.Println(o.Value) // Prints 0
o.ChangeValue(8) // Changes o.Value to 8
fmt.Println(o.Value) // Prints 8
(*Something).ChangeValue(o, 16) // Same as calling o.ChangeValue(16)
fmt.Println(o.Value) // Prints 16
}
在此基础上,考虑如果ChangeValue
的接收方是Something
类型的值而不是指向该类型的指针,会发生什么情况……
没错!你永远不可能通过这个方法来改变o
的Value
字段,大多数时候,你会使用指针接收器来进行封装。
发布于 2013-03-10 19:10:03
Go中的"this“被称为receiver。是的,使用非指针接收器来模拟"const“语义可能是非常昂贵的。但Go去掉了"const“修饰语是有充分理由的。因此,以不必要的复制为代价来接管特定的语言设计决策可能不是一个好主意-在任何比几个机器单词更大的情况下。
顺便说一句,"this“或"self”与"receiver“之间的术语差异意味着它也具有不同的语义。IIRC中,在其他语言中不能更改"this“或"self”的值,但在Go中,接收器只是另一个函数参数(实际上是从编译器的角度来看的第一个参数)。
也就是说,这就是我不鼓励编写接收器变量命名为this
或self
的方法的原因。对于习惯于其他语言的人来说,这是一种误导。
一个完全虚构的例子,希望能说明这个想法:
func (n *node) walk(f func(*node)) {
for n != nil {
f(n)
n = n.next
}
}
发布于 2013-03-10 19:21:38
我要说的是,你的C++知识可以很好地转化为函数参数的开销(通过值传递结构)和开销(内置类型,例如整型)。
主要的区别是引用类型,切片,map
和channel
。虽然它们看起来是通过值传递的(你不需要使用指针),但实际上是通过引用传递的,所以通常不要使用指向切片、映射或通道的指针。
string
也很特殊-它们是幕后的引用类型,但它们也是不可变的,所以直接传递它们。
至于this
或Go中调用的接收器的具体情况-同样的规则适用(请注意,与C++不同,您可以使用内置类型作为接收器),我认为编译器不够智能,无法避免复制,因此对大型结构使用指针。
https://stackoverflow.com/questions/15326185
复制相似问题