现在需要用 go 对接一个接口,接口的响应数据如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| { "success": true, "data": { "name": "hugo" }, "identifi": { "key": "xxx", "secret": "secret" }, "errors": [ { "code": "not_found", "message": "something" } ] }
|
我们可能会写如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| type Resp struct { Success bool Identifi RespIdentifi Data interface{} Errors []RespErr }
type RespIdentifi struct { Key string Secret string } type RespError struct { Code string Message string }
resp := new(Resp) json.Unmarshal(respBody, resp)
|
可读性太差了,不能一眼看出来我们要解析的数据结构是怎样的,如果再稍微复杂一点的结构我们要一行一行的定义很多 type,而且很多时候我们只是需要读到响应的内容,不需要给这些嵌套的结构定义方法来操作它们。
好在 golang 是支持这样写的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| type Resp struct { Success bool Identifi struct { Key string Secret string } Data interface{} Errors []struct { Code string Message string } }
resp := new(Resp) json.Unmarshal(respBody, resp)
|
我在 Stackoverflow 上找到对这种写法的称呼叫 Unnamed struct,不过如果你要显示的去给这个类型的对象赋值就很头疼了,你需要将前面的未命名类型再声名一次:
1 2 3 4 5 6 7 8 9 10 11
| resp := Resp{ Success: true, Identify: struct { Key string Secret string }{ Key: "xxx", Secret: "xxx", }, }
|
不过也并不影响它在前面的 Unmarshal 场景中很实用,另外这里有一篇看着就很头大的扩展阅读:https://gocn.vip/article/501 讲了 Unamed type 的各种奇葩表现。