英文:
Pointer receiver confusion
问题
我对以下代码的行为感到困惑。playground
var foo json.RawMessage
_ = json.Unmarshal([]byte(`{ "zoo": 123 }`), &foo)
enc := json.NewEncoder(os.Stdout)
// 正常工作
_ = enc.Encode(struct{ Foo *json.RawMessage }{&foo})
// MarshalJSON 是一个指针接收器,所以它在这里不会被调用
_ = enc.Encode(struct{ Foo json.RawMessage }{foo})
// 如果 .Foo 不是一个指针,为什么会调用 MarshalJSON?
_ = enc.Encode(&struct{ Foo json.RawMessage }{foo})
输出结果:
{"Foo":{"zoo":123}}
{"Foo":"eyAiem9vIjogMTIzIH0="}
{"Foo":{"zoo":123}}
我不明白为什么第三次调用 json.Encoder.Encode
能够访问 json.RawMessage.MarshalJSON
,即使它不是一个指针。
英文:
I'm confused about the behaviour of the following code. playground
var foo json.RawMessage
_ = json.Unmarshal([]byte(`{ "zoo": 123 }`), &foo)
enc := json.NewEncoder(os.Stdout)
// Works as expected
_ = enc.Encode(struct{ Foo *json.RawMessage }{&foo})
// MarshalJSON has a pointer reciever, so it doesn't get invoked here
_ = enc.Encode(struct{ Foo json.RawMessage }{foo})
// How is MarshalJSON being invoked if .Foo is not a pointer?
_ = enc.Encode(&struct{ Foo json.RawMessage }{foo})
Output:
{"Foo":{"zoo":123}}
{"Foo":"eyAiem9vIjogMTIzIH0="}
{"Foo":{"zoo":123}}
I don't understand why the third call to json.Encoder.Encode
is able to access json.RawMessage.MarshalJSON
even though it's not a pointer.
答案1
得分: 2
当在任何可寻址值上调用方法时,Go会自动引用该值以使用指针接收器调用方法。
type Foo struct{}
func (f *Foo) Call() {}
// f 不是指针,但是是可寻址的
f := Foo{}
f.Call()
此外,如果一个非指针值位于一个可寻址的结构体中,它也可以被引用以满足需要指针接收器的方法。
type Bar struct {
Foo Foo
}
// b 是可寻址的,因此 b.Foo 也是可寻址的
b := Bar{
Foo: f,
}
b.Foo.Call()
你最后的示例使用外部结构体的地址来获取 Foo 字段的地址,并调用 MarshalJSON
方法。
英文:
When calling a method on any addressable value, Go will automatically reference the value to call methods with a pointer receiver.
type Foo struct{}
func (f *Foo) Call() {}
// f isn't a pointer, but is addressable
f := Foo{}
f.Call()
Also, if a non-pointer value is in an addressable struct, it can also be reference for methods requiring a pointer receiver.
type Bar struct {
Foo Foo
}
// b is addressable, therefor so is b.Foo
b := Bar{
Foo: f,
}
b.Foo.Call()
Your last example uses the address of the outer struct to get the address of the Foo field, and call MarshalJSON
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论