[英]Go Syntax of calling a function with pointer receiver
在Go中,如果我用指针定义一个函数作为接收器,它不应该只允许从指针调用函数吗? 为什么可以从值本身调用此函数并具有相同的效果。
例如,在以下程序中:m1.reset()和m2.reset()具有相同的效果。 即使m1是值,m2也是指针。
我有点困惑,因为有两种方法可以做同样的事情 ,我不确定应该遵循哪一种方法。 虽然大多数代码遵循使用指针字段调用函数的约定 。 我错过了什么吗?
package main
import "fmt"
type MyStruct struct {
X int
}
func (m *MyStruct) reset() {
m.X = 0
}
func main() {
m1 := MyStruct{1}
m2 := &MyStruct{1}
fmt.Println(m1.X)
fmt.Println(m2.X)
m1.reset()
m2.reset()
fmt.Println(m1.X)
fmt.Println(m2.X)
}
@jnml提供了完美的doc规范说明,但我想添加一个基于你的代码示例。 我认为你应该更少关注“为什么有两种方法可以做同样的事情”,更多的是关于何时使用一种方法与另一种方式。 具有指针作为接收器的方法具有修改该接收器的值的方法,而具有作为接收器的值的方法不能。 这是因为方法接收接收器的副本 。 获得指针的副本后,仍可以修改其值。 当您收到值的副本时,您在该方法中所做的更改只会更改副本,而不会更改原始副本:
package main
import "fmt"
type MyStruct struct {
X int
}
func (m *MyStruct) resetPtr() {
m.X = 0
}
func (m MyStruct) resetValue() {
m.X = 0
}
func main() {
m1 := MyStruct{1}
m2 := &MyStruct{1}
fmt.Println("Original Values:", m1.X, m2.X)
m1.resetPtr()
m2.resetPtr()
fmt.Println("After resetPtr():", m1.X, m2.X)
m1 = MyStruct{1}
m2 = &MyStruct{1}
m1.resetValue()
m2.resetValue()
fmt.Println("After resetValue():", m1.X, m2.X)
}
产量
Original Values: 1 1
After resetPtr(): 0 0
After resetValue(): 1 1
您可以看到访问这些变量的方式并不是真正的问题。 它更多地是关于你可以在方法中使用它们做什么,以及它们如何作为参数传递给其他函数或方法(被复制)。
一个简短的解释是幕后的Go编译器会自动转换:
m1.reset()
m2.reset()
成:
(&m1).reset()
m2.reset()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.