0%

Go 能否解码到一个 interface 类型的值

通过代码描述一下这里的具体操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type Parent interface {
Test()
}

type Child struct {
Name string `json:"name"`
}

func (c Child) Test() {
}

func createChild() Parent {
return Child{}
}

func test() Parent {
// c 是一个 Parent 类型
c := createChild()

s := `{"name":"123"}`
err := json.Unmarshal([]byte(s), &c)
if err != nil {
panic(err)
}

// 问题:这里能不能得到 name 的值 123?
fmt.Printf("name=%s\n", c.(Child).Name)

return c
}

答案:不行

问题描述

具体就是,我有一个结构体 Child 实现了接口 Parent,然后 Child 里面有 name 属性,然后在反序列化的时候,用指向 Parent,类型的值来接收。

结果就是,结构体里面字段都丢失了。

如果我们写成下面这样,就可能错过了发现错误的机会(我一开始就是这么写的):

1
_ = json.Unmarshal([]byte(s), &c)

如果打印错误的话,其实编译器已经给出了明确的报错信息:

1
2
panic: json: cannot unmarshal object into Go value of type body.Parent [recovered]
panic: json: cannot unmarshal object into Go value of type body.Parent

原因

在反序列化的时候,反射处理是拿不到那个值的具体类型的。

参考链接:https://stackoverflow.com/questions/32428797/unmarshal-to-a-interface-type

原答案:

You can marshal from an interface type variable, because the object exists locally, so the reflector knows the underlying type.

You cannot unmarshal to an interface type, because the reflector does not know which concrete type to give to a new instance to receive the marshaled data.