为什么json.Unmarshal使用引用而不是指针?
从json.Unmarshal文档(稍加修改,使用简单的Animal
代替[]Animal
)这个例子的作品,没有任何错误:为什么json.Unmarshal使用引用而不是指针?
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:解组(无* main.Animal)
这似乎是因为animals
是未初始化的指针。但文档说(重点是我的):
Unmarshal将JSON解组到指针指向的值。 如果指针为零,Unmarshal会为它指定一个新值。
那么为什么在第二个例子中unmarshaling失败并显示不明确的错误?
(此外,有 “解组” 或 “拆封”(一个L)?该文档同时使用。)
你遇到了一个InvalidUnmarshalError(见lines 109 and 110 in decode.go)。
// InvalidUnmarshalError描述传递给Unmarshal的无效参数。
// (以解组的参数必须是一个非空指针。)
看来文档可以做一些澄清,上述报价和低于from the Unmarshal
source的意见做似乎相互矛盾。
如果指针为零,Unmarshal会为它指定一个新值。
因为你的指针是零。
如果你初始化它的工作原理:http://play.golang.org/p/zprmV0O1fG
var animals *Animal = &Animal{}
而且,它可以被拼写为任何一种方式(一致性在一个单一的文档将是很好,虽然):http://en.wikipedia.org/wiki/Marshalling_(computer_science)
我有一个类似的情况之前,但在不同的情况下。 它与Go中的界面概念有关。 如果一个函数声明了一个接口作为参数或返回值,调用者必须传递或返回参考
在你的情况,json.Unmarshal
接受接口作为第二个参数
我认为问题是,虽然您可以将指针传递给无 Unmarshal(),您无法传递零指针值。
的指针为nil将是这样的:
var v interface{}
json.Unmarshal(text, &v)
的v
的值是零,但指针v
是一个非零指针地址。它是一个非零指针,它指向一个nil接口(它本身就是一个指针类型)。在这种情况下,Unmarshal不会返回错误。
甲零指针将是这样的:
var v *interface{}
json.Unmarshal(text, v)
在这种情况下,V的类型是pointer to an interface{}
,但与在golang一个变种的任何声明,的v
初始值是类型的零值。因此v
是一个零值指针,这意味着它不指向内存中的任何有效位置。
如https://stackoverflow.com/a/20478917/387176提到的,json.Unmarshal()需要一个有效的指针东西,因此它可以改变一些(可能是一个零值结构或指针)在适当位置。
好的,但是这对于Unmarshal文档意味着什么:“如果指针为零,Unmarshal会为它指定一个新值。”为什么我们必须初始化它,如果Unmarshal应该为我们做呢? – Matt
哈哈,是的,我刚刚在你的问题中看到了。那么,如果你传入指针的引用,它也分配它。 http://play.golang.org/p/3KP7pPKmBp –
有趣。那么,我对“指针”意味着什么不正确或文档错误的理解是什么?因为我在这里看到的所有工作都是引用,而不是指针。 – Matt