给出以下代码:
package main import ( "encoding/json" "log" ) type Somefin string func (s *Somefin) UnmarshalJSON(b []byte) error { log.Println("Unmarshaling",string(b)) *s = Somefin("~"+string(b)+"~") return nil } type Wat struct { A, B string *Somefin } func main() { b := []byte(`{"A":"foo","B":"bar","Somefin":"baz"}`) w := &Wat{Somefin: new(Somefin)} err := json.Unmarshal(b,w) log.Println(w, err) }
我得到以下输出:
# go run wat.go 2013/12/14 13:59:17 Unmarshaling {"A":"foo","B":"bar","Somefin":"baz"} 2013/12/14 13:59:17 &{ <nil>} <nil>
因此,Somefin出于某种原因,密钥是试图取消对整个结构的编组,而不是仅仅应该解组。我做错了吗,或者这是json编码器中的错误?顺便说一句,正在进行1.2。
Somefin
这不是解码器中的错误,而是代码中的错误。你只是将另一个地址为本地指针s在UnmarshalJSON。更正的代码:
s
UnmarshalJSON
func (s *Somefin) UnmarshalJSON(b []byte) error { log.Println("Unmarshaling",string(b)) sn := Somefin("~"+string(b)+"~") *s = sn return nil }
语义s = &sn:将地址分配&sn给s。这类似于s = 42。
s = &sn
&sn
s = 42
的语义*s = sn:将所有内容复制sn到指向的地方s。
*s = sn
sn
这项工作的一项要求是s指向有效的内存位置,并且不能为nil。您的代码用法示例(播放):
nil
w := &Wat{Somefin: new(Somefin)} err := json.Unmarshal(b,w) log.Printf("%#v (%s)\n", w, err)
Crucial是Wat使用new进行的初始化,Somefin因此sin 的指针UnmarshalJSON有效(指向使用创建的对象new(Somefin))。
Wat
new(Somefin)
嵌入不是多态。虽然嵌入对象(在你的情况的方法集 Somefin)提升到外面,但这 并不 意味着该方法现在工作的嵌入结构,而不是嵌入的一个。
小例子(播放):
type Inner struct { a int } func (i *Inner) A() int { return i.a } type Outer struct { *Inner a int } i := &Inner{} o := Outer{Inner: i} fmt.Println("Inner.A():", i.A()) fmt.Println("Outer.A():", o.A()) o.a = 2 fmt.Println("Outer.A():", o.A())
有了多态,您将希望Outer.A()返回,2因为方法A()将在范围内运行,Outer并且Inner不再运行。嵌入后,作用域A()将永远不会改变,并且 将始终在上运行Inner。
Outer.A()
2
A()
Outer
Inner
相同的效果会阻止您UnmarshalJSON看到这两个成员A,B因为它们根本不在以下范围内Somefin:
A
B