为什么json.Unmarshal使用引用而不是指针?

Mat*_*att 35 json go

来自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)

  • 如果没有对指针的引用,它将无法更改指针的值(它指向的位置). (6认同)
  • 哈哈,是的,我刚刚在你的问题中看到了这一点。好吧,如果您传入对指针的引用,它也会分配它。http://play.golang.org/p/3KP7pPKmBp (2认同)

Rus*_*gan 8

我相信问题是,虽然你可以将指向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()需要一个指向某事物的有效指针,因此它可以更改某些内容(无论是零值结构还是指针) .