来自json.Unmarshal文档的这个示例(为了简单起见,使用Animal
而不是[]Animal
略有修改)有效,没有错误:
Playground link of working example
// ...
var animals Animal
err := json.Unmarshal(jsonBlob, &animals)
// ...
但是这个略有修改的例子没有:
Playground link of non-working example
// ...
var animals *Animal
err := json.Unmarshal(jsonBlob, animals)
// ...
它显示这个模糊的错误,实际上没有帮助(看起来更像是函数调用而不是错误IMO):
json:Unmarshal(nil * main.Animal)
这似乎是因为animals
是未初始化的指针。但是文档说(强调我的):
Unmarshal将JSON解组为指针指向的值。 如果指针为nil,则Unmarshal会为其指定一个新值以指向它。
那么为什么在第二个例子中解组失败并显示出模糊的错误?
(另外,它是“解组”还是“解组”(一个L)?文档同时使用它们。)
答案 0 :(得分:31)
您遇到了InvalidUnmarshalError(请参阅lines 109 and 110 in decode.go)。
// InvalidUnmarshalError描述传递给Unmarshal的无效参数 // (Unmarshal的参数必须是非零指针。)
似乎文档可以做一些澄清,因为上面的引用和from the Unmarshal
source下面的评论似乎相互矛盾。
如果指针为nil,则Unmarshal为其指定一个新值以指向。
答案 1 :(得分:26)
因为你的指针是零。
如果您初始化它,则有效:http://play.golang.org/p/zprmV0O1fG
var animals *Animal = &Animal{}
此外,它可以拼写为任何一种方式(单个文档中的一致性会很好):http://en.wikipedia.org/wiki/Marshalling_(computer_science)
答案 2 :(得分:7)
我认为问题在于,虽然你可以将指针传递给nil 到Unmarshal(),但你不能传递 nil指针值。
指向nil的指针就像:
var v interface{}
json.Unmarshal(text, &v)
v
的值为nil,但指向v
的指针是非零指针地址。它是一个非零指针,指向一个nil接口{}(它本身就是一个指针类型)。在这种情况下,Unmarshal不会返回错误。
nil指针就像:
var v *interface{}
json.Unmarshal(text, v)
在这种情况下,v的类型是pointer to an interface{}
,但与golang中var的任何声明一样,v
的初始值是类型的零值。所以v
是一个零值指针,这意味着它没有指向内存中的任何有效位置。
如https://stackoverflow.com/a/20478917/387176中所述,json.Unmarshal()需要一个指向某事的有效指针,因此它可以改变某些东西(无论是零值结构还是指针)到位。
答案 3 :(得分:0)
我之前有一个类似的情况,但在另一种情况下。 它与Go中的界面概念有关。 如果函数将接口声明为参数或返回值,则调用者必须传递或返回引用
在您的情况下,json.Unmarshal
接受接口作为第二个参数