Краткий отрывок из Tour of Go гласит, что:
Методы с указателями-получателями могут изменять значение, на которое указывает получатель [...].Поскольку методы часто нуждаются в модификации своего приемника, приемники указателей встречаются чаще, чем приемники значений.
Почему r.b
отображается правильно, а r.a
вообще не изменяется?
Как уже говорилось в моем ответе ниже, ваш метод add()
является получателем значения.Следовательно, он возьмет вашу инициализированную структуру (то есть r
), скопирует ее и затем соответствующим образом модифицирует.Поскольку вы инициализировали новую карту в r.b
в своей функции main()
, здесь копируется только ссылка на эту карту, но не вся карта.Поэтому манипуляции на карте работают, а не на срезе r.a
.Но почему r.a
не меняется вообще?Это связано с тем, что append()
, который находится в методе add()
, сохраняет новый заголовок слайса в свойстве a
и указывает на другой раздел базового массива.В конце ваш метод получения значения add()
сделал копию r
, установил новый заголовок среза под свойством a
и никогда не изменял исходную структуру r
, которая была определена в main()
функция, как это было скопировано с помощью метода получателя значения add()
.
В вашем случае метод add()
- это так называемый метод получателя значения, который не может выполнять никаких манипуляций с вашей определенной структурой r
, расположенной вmain()
функционирует напрямую, но копирует его и выполняет манипуляции впоследствии.Следовательно, вам нужно превратить ваш add()
метод в метод приемника указателя, например, так:
func (r *R) add() {
r.a = append(r.a, 2)
r.b[2] = 2
}
Теперь метод принимает фактическую ссылку на вашу структуру r
, которая инициируется в main()
, и изменяет ее соответствующим образом.
Как это могло бы работать, не меняя ваш метод add()
на приемник указателя?
Вы просто должны были бы вернутьскопировать структуру в ваш add()
метод следующим образом:
package main
import (
"fmt"
)
func main() {
var r R
r.b = make(map[int]int)
fmt.Println(r.add()) // outputs {[2] map[2:2]}
}
type R struct {
a []int
b map[int]int
}
func (r R) add() R {
r.a = append(r.a, 2)
r.b[2] = 2
return r
}