为什么在接口中添加 func 会导致 json.Unmarshal 失败?

rex*_*das 3 json go

为什么这会失败并出现错误:

json:无法将对象解组为 main.Spouse 类型的 Go 结构字段 Person.spouse

type Spouse interface {
    Name() // Adding this causes an error
}

type Address interface {
}

type Person struct {
    Name string   `json:"name"`
    A    *Address `json:"address"`
    S    *Spouse  `json:"spouse"`
}

func main() {
    b := []byte(`{
     "name":"sarah", 
     "address":{
         "street":"101 main" 
         }, 
     "spouse":{
         "name":"joe"
         }
     }
    `)

    p := &Person{}
    if err := json.Unmarshal(b, p); err != nil {
        fmt.Printf("%s", err)
    }
}
Run Code Online (Sandbox Code Playgroud)

查看文档,我不明白为什么在接口中添加函数会导致错误。我期待 json.Unmarshal 简单地忽略Name()函数,因为它不是json.Unmarshal 处理的列表的一部分。

这是go playground 中的代码。

转到版本 go1.10 达尔文/amd64

mu *_*ort 6

来自精美手册

func Unmarshal
[...]
要将 JSON 解组为接口值,Unmarshal 将其中之一存储在接口值中:

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
Run Code Online (Sandbox Code Playgroud)

您正在尝试将 JSON 对象解组到接口中,因此该接口背后的值将是 amap[string]interface{}来表示键/值对。但是map[string]interface{}没有Name()方法所以它没有实现你的Spouse接口。

如果我们稍微简化一下您的示例并摆脱该Name()方法,我们可以看到发生了什么:

type Spouse interface {
}

type Person struct {
    S *Spouse `json:"spouse"`
}

func main() {
    b := []byte(`{"spouse":{ "name":"joe" } }`)

    p := &Person{}
    if err := json.Unmarshal(b, p); err != nil {
        fmt.Printf("%s", err)
    }
    spouse := (*p.S).(map[string]interface{})
    fmt.Printf("%+v\n", spouse)
}
Run Code Online (Sandbox Code Playgroud)

spousemap[string]interface{}记录的。