在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 提供了完美的文档规范解释,但我想添加一个基于您的代码示例。我认为你的重点应该少在于“为什么有两种方法可以做同一件事”,而应该更多地关注何时使用一种方法而不是另一种方法。以指针作为接收者的方法能够修改该接收者的值,而以值作为接收者的方法则不能。这是因为这些方法接收到copy接收器的。当您获得指针的副本时,您仍然可以修改它的值。当您收到该值的副本时,您在该方法中所做的更改只会更改副本,而不会更改原始值:
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)
}
Output
Original Values: 1 1
After resetPtr(): 0 0
After resetValue(): 1 1
您可以看到访问这些变量的方式并不是真正的问题。更多的是关于您可以在方法内部使用它们做什么,以及如何将它们作为参数传递给其他函数或方法(被复制)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)