来自json.Unmarshal文档的这个例子(为了简单Animal而略微修改而不是使用[]Animal)工作,没有错误:
// ...
var animals Animal
err := json.Unmarshal(jsonBlob, &animals)
// ...
Run Code Online (Sandbox Code Playgroud)
但是这个稍微修改过的例子不是:
// ...
var animals *Animal
err := json.Unmarshal(jsonBlob, animals)
// ...
Run Code Online (Sandbox Code Playgroud)
它显示这个模糊的错误,实际上没有用(看起来更像是函数调用而不是错误IMO):
json:Unmarshal(nil*main.Animal)
这似乎是因为animals是一个未初始化的指针.但文档说(强调我的):
Unmarshal将JSON解组为指针指向的值.如果指针为nil,则Unmarshal为其指定一个新值以指向它.
那么为什么在第二个例子中解编失败并显示出模糊的错误呢?
(另外,它是"解组"还是"解组"(一个L)?文档使用两者.)
Int*_*net 35
您遇到了InvalidUnmarshalError(请参阅decode.go中的第109行和第110行).
// InvalidUnmarshalError描述传递给Unmarshal的无效参数.
// (Unmarshal的参数必须是非零指针.)
看来文档可以做一些澄清,上述报价和下面的评论做到从Unmarshal源头似乎相互矛盾.
如果指针为nil,则Unmarshal为其指定一个新值以指向它.
Eve*_*man 28
因为你的指针是零.
如果你初始化它可以工作:http://play.golang.org/p/zprmV0O1fG
var animals *Animal = &Animal{}
Run Code Online (Sandbox Code Playgroud)
此外,它可以拼写为任何一种方式(虽然单个文档中的一致性会很好):http://en.wikipedia.org/wiki/Marshalling_ (computer_science)
我相信问题是,虽然你可以将指向nil的指针传递给Unmarshal(),但是你不能传递一个nil指针值.
指向nil的指针如下:
var v interface{}
json.Unmarshal(text, &v)
Run Code Online (Sandbox Code Playgroud)
值为vnil,但指针指向的v是非零指针地址.它是一个非零指针,指向一个nil接口{}(它本身就是一个指针类型).在这种情况下,Unmarshal不会返回错误.
一个零指针就像:
var v *interface{}
json.Unmarshal(text, v)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,v的类型是pointer to an interface{},但与golang中var的任何声明一样,初始值v是类型的零值.所以v是一个零值指针,这意味着它不指向内存中任何有效的地方.
如/sf/answers/1433524221/中所述,json.Unmarshal()需要一个指向某事物的有效指针,因此它可以更改某些内容(无论是零值结构还是指针) .