指针接收器混乱

时间:2015-08-28 18:07:47

标签: go

我对以下代码的行为感到困惑。 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})

输出:

{"Foo":{"zoo":123}}
{"Foo":"eyAiem9vIjogMTIzIH0="}
{"Foo":{"zoo":123}}

我不明白为什么第三次拨打json.Encoder.Encode的电话能够访问json.RawMessage.MarshalJSON,即使它不是指针。

1 个答案:

答案 0 :(得分:2)

在任何addressable value上调用方法时,Go会自动引用该值以使用指针接收器调用方法。

type Foo struct{}
func (f *Foo) Call() {}

// f isn't a pointer, but is addressable
f := Foo{}
f.Call()

另外,如果非指针值在可寻址结构中,它也可以作为需要指针接收器的方法的参考。

type Bar struct {
    Foo Foo
}

// b is addressable, therefor so is b.Foo
b := Bar{
    Foo: f,
}
b.Foo.Call()

您的上一个示例使用外部结构的地址来获取Foo字段的地址,并调用MarshalJSON