TL; DR: Приемник указателя должен быть разыменовываются, прежде чем это значение могут быть установлены. Это относится как к структурным, так и к неструктурным типам. В случае типов структур разыменование автоматически выполняется выражением селектора.
После того, как я немного углубился, я думаю, что это поведение вызвано тем, что приемник указателя не является тем же самым указателем, вызывающим метод.
Выполнение этого фрагмента кода показывает, что указатель u
в функции main()
отличается от функции defaultIP()
. По сути, я заканчиваю только, изменяя указатель u
в методе defaultIP()
. Исполняемый пример можно найти here.
func main() {
var u *userIP
u.defaultIP()
fmt.Printf("main(): address of pointer is %v\n", &u)
fmt.Printf("main(): user IP address is %v\n", u)
}
type userIP net.IP
func (u *userIP) defaultIP() {
defaultIP := userIP("127.0.0.1")
u = &defaultIP
fmt.Printf("defaultIP(): address of pointer is %v\n", &u)
fmt.Printf("defaultIP(): user IP address is %s\n", *u)
}
правильный способ сделать это как указано в ответе Тома есть разыменовать u
в методе defaultIP()
.
Что меня озадачило раньше, почему этот пример будет работать, если я завернул IP в качестве поля в структуре? Выполнение фрагмента кода показывает, что два указателя u
действительно отличаются, но поле ip
изменено. Исполняемый пример можно найти here.
func main() {
u := &userInfo{}
u.defaultIP()
fmt.Printf("main(): address of pointer is %v\n", &u)
fmt.Printf("main(): user IP address is %s\n", u.ip)
}
type userInfo struct{
ip net.IP
}
func (u *userInfo) defaultIP() {
u.ip = net.ParseIP("127.0.0.1")
fmt.Printf("defaultIP(): address of pointer is %v\n", &u)
fmt.Printf("defaultIP(): user IP address is %s\n", u.ip)
}
Оказывается, что это вызвано selector expression (x.y
). Для цитирования документа,
Селекторы автоматически разыменовывают указатели на структуры. Если x является указателем на структуру, x.y является сокращением для (x) .y; если поле y также является указателем на структуру, x.y.z является сокращением для ( (* x) .y) .z и т. д. Если x содержит анонимное поле типа * A, где A также является типом структуры, x.f является ярлыком для (* x.A) .f.
Так что в моем случае, выражение u.ip
разыменовывает u
перед изменением ip
поля, которое по существу переводит к (*u).ip
.
dereference * (я пробовал редактировать это, но это не позволяло мне, так как изменение было менее 6 символов) – Kul
Читателю нужно нажать на ссылку, чтобы понять этот ответ. (если вы уже не знаете, что означает разыменование, но даже так, как вы это делаете в golang-клике по ссылке, чтобы узнать: D – Jacob