Golang reflect.Tag.Lookup()函数使用及示例
在Golang中,反射(reflect)是一个强大的特性,可以让我们在运行时获取类型的信息,甚至是修改它们。 reflect包下提供了一系列的函数和类型,用于完成反射的任务。在本文中,我们将重点解释 reflect.Tag.Lookup() 函数的用法。
什么是 reflect.Tag?
在Golang中,每一个struct都可以关联一个tag,通过tag,我们可以在代码中标记一个结构体字段(field)。 reflect.Tag 类型是将tag作为字符串解析的结果,它有一个Lookup函数可以用来查找结构体字段的tag。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
tag := reflect.TypeOf(Person{}).Field(0).Tag
fmt.Println(tag.Get("json")) // 输出: "name"
在上面的代码中,我们定义了一个 Person 结构体,它有两个字段 Name 和 Age,这两个字段都有一个 “json” tag,它们的值分别为 “name” 和 “age”。我们通过 reflect.TypeOf() 获取到相应的类型,再通过 Field() 获取到相应的字段,最后调用 Tag 属性获取到 tag。
reflect.Tag.Lookup()
reflect.Tag.Lookup() 函数可以用来查找结构体字段的tag值。它有一个字符串类型的参数,表示要查找的tag名称,返回一个 Pair 结构体,Pair 结构体包含一个 bool 类型的 ok 属性,表示是否找到了匹配的tag,如果找到了,还会返回该tag的值。
type Pair struct {
Key string
Val string
}
tag := reflect.TypeOf(Person{}).Field(0).Tag
jsonTag, ok := tag.Lookup("json")
if ok {
fmt.Println(jsonTag) // 输出: "name"
} else {
fmt.Println("tag not found")
}
上面的代码中,我们查找结构体 Person 的第一个字段 Name 的 “json” tag 值,如果存在,输出它的值;如果不存在,打印 “tag not found”。
示例代码
type Book struct {
Title string `json:"title"`
Author string `json:"author"`
PubDate string `json:"pub_date"`
}
func main() {
book := Book{Title: "Golang Tutorial", Author: "XYZ", PubDate: "2021-10-01"}
for i := 0; i < reflect.TypeOf(book).NumField(); i++ {
field := reflect.TypeOf(book).Field(i)
tag := field.Tag
jsonTag, ok := tag.Lookup("json")
if ok {
fmt.Printf("%s: %s\n", jsonTag, field.ValueOf(book))
}
}
}
接下来,我们来解释上面的代码。首先,我们定义了一个 Book 的结构体,有三个字段 Title、Author 和 PubDate,它们都有一个 “json” tag。我们创建了一个 Book 的实例,然后使用 reflect 遍历它的所有字段,查找是否有 “json” tag,如果有,就输出 tag 对应的值和字段的值。
结论
reflect.Tag.Lookup() 函数是一个非常实用的函数,可以用来获取结构体字段的tag值。利用反射和tag,我们可以实现很多自定义的功能,如json编解码、ORM等。
参考链接:
- https://golang.org/pkg/reflect#Tag
- https://blog.golang.org/laws-of-reflection