@ jnml предлагает идеальное объяснение спецификации документа, но я хотел добавить пример кода на основе вашего. Я думаю, что вы должны сосредоточиться не столько на том, «Почему есть два способа сделать одно и то же», а на том, когда использовать один против другого. Метод, имеющий указатель в качестве получателя, имеет возможность изменять значения этого получателя, в то время как метод, который имеет значение в качестве получателя, не может. Это происходит потому, что методы получают копию получателя. Когда вы получаете копию указателя, вы все равно можете изменить его значение. Когда вы получаете копию значения, изменения, которые вы вносите в этом методе, изменяют только копию, а не оригинал:
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
Вы видите, что способ доступа к этим переменным на самом деле не является проблемой. Больше о том, что вы можете делать с ними внутри метода, и как они передаются в качестве аргументов другим функциям или методам (копируются).