问题
json
包里使用的时候,会结构体里的字段边上加tag
,有没有什么办法可以获取到这个tag
的内容呢?
举例
tag
信息可以通过反射(reflect包)
内的方法获取,通过一个例子加深理解。
package main
import (
"fmt"
"reflect"
)
type J struct {
a string //小写无tag
b string `json:"B"` //小写+tag
C string //大写无tag
D string `json:"DD" otherTag:"good"` //大写+tag
}
func printTag(stru interface{}) {
t := reflect.TypeOf(stru).Elem()
for i := 0; i < t.NumField(); i++ {
fmt.Printf("结构体内第%v个字段 %v 对应的json tag是 %v , 还有otherTag? = %v \n", i+1, t.Field(i).Name, t.Field(i).Tag.Get("json"), t.Field(i).Tag.Get("otherTag"))
}
}
func main() {
j := J{
a: "1",
b: "2",
C: "3",
D: "4",
}
printTag(&j)
}
复制代码
输出
结构体内第1个字段 a 对应的json tag是 , 还有otherTag? =
结构体内第2个字段 b 对应的json tag是 B , 还有otherTag? =
结构体内第3个字段 C 对应的json tag是 , 还有otherTag? =
结构体内第4个字段 D 对应的json tag是 DD , 还有otherTag? = good
复制代码
解释
printTag
方法传入的是j的指针。reflect.TypeOf(stru).Elem()
获取指针指向的值对应的结构体内容。NumField()
可以获得该结构体含有几个字段。遍历结构体内的字段,通过 t.Field(i).Tag.Get("json")
可以获取到tag
为json
的字段。如果结构体的字段有 多个tag
,比如叫otherTag
,同样可以通过t.Field(i).Tag.Get("otherTag")
获得。
再补一句
上篇文章 提到json包
不能导出私有变量的tag
是因为取不到反射信息
的说法,但是直接取t.Field(i).Tag.Get("json")
却可以获取到私有变量的json字段
,是为什么呢?
其实准确的说法是,json
包里不能导出私有变量的tag
是因为json
包里认为私有变量为不可导出的Unexported
,所以跳过获取名为json
的tag
的内容。
具体可以看/src/encoding/json/encode.go:1070
的代码。
func typeFields(t reflect.Type) []field {
// 注释掉其他逻辑...
// 遍历结构体内的每个字段
for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i)
isUnexported := sf.PkgPath != ""
// 注释掉其他逻辑...
if isUnexported {
// 如果是不可导出的变量则跳过
continue
}
// 如果是可导出的变量(public),则获取其json字段
tag := sf.Tag.Get("json")
// 注释掉其他逻辑...
}
// 注释掉其他逻辑...
}
复制代码
文章推荐:
golang面试题:json包变量不加tag会怎么样? golang面试题:怎么避免内存逃逸? golang面试题:简单聊聊内存逃逸? golang面试题:字符串转成byte数组,会发生内存拷贝吗? golang面试题:翻转含有 中文、数字、英文字母
的字符串golang面试题:拷贝大切片一定比小切片代价大吗? golang面试题:能说说uintptr和unsafe.Pointer的区别吗?
如果你想每天学习一个知识点?
有疑问加站长微信联系(非本文作者)