这个坑隐藏得很深,绝大多数情况下都不会碰到。在转换JSON的过程中,Unmarshal会按字段名来转换,碰到同名但大小写不一样的字段会当做同一字段处理。在官方文档中亦有说明(加粗部分):
To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match. By default, object keys which don’t have a corresponding struct field are ignored (see Decoder.DisallowUnknownFields for an alternative).
精确匹配最好,但是也接受大小写不敏感的匹配。只能说“包容性”太好了,但我认为这并不是一个好的设计。
一段典型代码如下:
package main
import (
"encoding/json"
"fmt"
)
type UserInfo struct {
UserID string `json:"UserID"`
}
func main() {
var u1 UserInfo
json.Unmarshal([]byte(`{"UserID":"aaa"}`), &u1)
fmt.Println(u1.UserID) // 打印 aaa
var u2 UserInfo
json.Unmarshal([]byte(`{"UserID":"aaa", "UserId":"bbb"}`), &u2)
fmt.Println(u2.UserID) // 打印 bbb
var u3 UserInfo
json.Unmarshal([]byte(`{"UserID":"aaa", "UserId":"bbb", "userId":"ccc"}`), &u3)
fmt.Println(u3.UserID) // 打印 ccc
}
刚碰到一个“这也能正常运行?!”的问题,一查就是这个坑…