在Golang的struct定义中,我们可以为字段添加tag来附加元数据,比如json序列化时的字段名、数据库映射的字段名等。通过reflect包可以在运行时获取这些tag值,满足动态处理的需求。

基础获取方法:通过Type和StructField获取
最基础的获取方式是先获取struct的反射类型reflect.Type,再通过Field方法获取对应字段的StructField,最后调用StructField的Tag属性获取tag内容。
示例代码如下:
package main
import (
"fmt"
"reflect"
)
// 定义一个带tag的结构体
type User struct {
Name string `json:"name" db:"user_name"`
Age int `json:"age" db:"user_age"`
}
func main() {
// 创建User实例
u := User{Name: "张三", Age: 20}
// 获取实例的反射类型
t := reflect.TypeOf(u)
// 遍历所有字段获取tag
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fmt.Printf("字段名:%s, tag值:%sn", field.Name, field.Tag)
}
}
上述代码中,field.Tag会返回完整的tag字符串,比如json:"name" db:"user_name"。
获取指定key的tag值
很多时候我们不需要完整的tag字符串,只需要获取某个key对应的value,比如只需要获取json对应的tag值,这时候可以使用Tag.Get方法。
代码示例:
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string `json:"name" db:"user_name"`
Age int `json:"age" db:"user_age"`
}
func main() {
u := User{Name: "张三", Age: 20}
t := reflect.TypeOf(u)
// 获取Name字段的json tag值
nameField, _ := t.FieldByName("Name")
jsonTag := nameField.Tag.Get("json")
dbTag := nameField.Tag.Get("db")
fmt.Printf("Name字段json tag:%s, db tag:%sn", jsonTag, dbTag)
// 获取Age字段的json tag值
ageField, _ := t.FieldByName("Age")
fmt.Printf("Age字段json tag:%sn", ageField.Tag.Get("json"))
}
Tag.Get方法会解析tag字符串,返回对应key的value,如果key不存在则返回空字符串。
处理带选项的tag值
有些tag的value会带有选项,比如json:"name,omitempty",这种时候如果需要拆分value和选项,可以使用Tag.Lookup方法,它会返回两个值,第一个是key对应的value,第二个是key是否存在的布尔值。
代码示例:
package main
import (
"fmt"
"reflect"
"strings"
)
type User struct {
Name string `json:"name,omitempty" db:"user_name"`
}
func main() {
u := User{Name: "张三"}
t := reflect.TypeOf(u)
nameField, _ := t.FieldByName("Name")
// 使用Lookup判断key是否存在
if tagValue, ok := nameField.Tag.Lookup("json"); ok {
// 拆分value和选项
parts := strings.Split(tagValue, ",")
fmt.Printf("json tag主值:%s, 选项:%vn", parts[0], parts[1:])
}
// 判断不存在的key
if _, ok := nameField.Tag.Lookup("xml"); !ok {
fmt.Println("Name字段不存在xml tag")
}
}
获取嵌入字段的tag值
如果struct包含嵌入字段,获取tag的时候需要注意嵌入字段的层级,通过FieldByIndex可以获取嵌套层级的字段信息。
代码示例:
package main
import (
"fmt"
"reflect"
)
type Base struct {
ID int `json:"id" db:"base_id"`
}
type User struct {
Base
Name string `json:"name" db:"user_name"`
}
func main() {
u := User{Base: Base{ID: 1}, Name: "张三"}
t := reflect.TypeOf(u)
// 获取嵌入字段Base的ID字段的tag
// 索引[0]是Base嵌入字段,[0]是Base的ID字段
idField := t.FieldByIndex([]int{0, 0})
fmt.Printf("嵌入字段ID的json tag:%sn", idField.Tag.Get("json"))
}
注意事项
- 获取tag前需要确保操作的是struct类型,否则调用
NumField等方法会触发panic,可以先通过Kind()判断类型是否为reflect.Struct。 - 如果传入的是struct的指针,需要先通过
Elem()方法获取指针指向的实际类型,再进行字段和tag的获取。 - tag的key和value需要符合Golang的tag语法规范,否则可能无法正确解析。
通过以上几种方法,就可以覆盖大部分Golang中通过reflect获取字段tag值的场景,开发者可以根据实际需求选择合适的实现方式。
Golangreflect字段tagstruct_tag修改时间:2026-07-04 13:45:26