如何在Golang中获取结构体标签信息_使用reflect读取tag值

Go中可通过reflect包获取结构体字段标签值,调用Tag.Get("key")提取json等标签,返回空字符串表示无该标签;标签选项需手动解析,如用strings.Split拆分判断omitempty或"-"。

在 Go 中,可以通过 reflect 包读取结构体字段的标签(tag)信息,最常用的是获取 jsondbvalidate 等自定义标签值。

获取结构体字段的 tag 值

使用 reflect.TypeOf 获取结构体类型,再通过 Field 方法遍历字段,调用 Tag.Get("key") 提取指定键的标签值。

  • 必须传入结构体指针或值的反射对象,但 reflect.TypeOf 接收的是类型信息,reflect.ValueOf 才能获取值信息;实际中常先用 reflect.TypeOf 拿字段标签,再用 reflect.ValueOf 取值
  • Tag.Get("json") 返回空字符串表示该字段没有该 tag 或 tag 值为空;不会 panic
  • tag 字符串格式为 `key:"value,option"`Get 方法只返回引号内的内容(不含选项),如 json:"name,omitempty"Get("json") 返回 "name,omitempty"

解析 tag 中的选项(如 omitempty、-)

标准库 reflect.StructTag 提供了 GetLookup 方法,但要拆解选项需手动处理。常见做法是按逗号分割后判断:

  • strings.Split(tagValue, ",") 分割,首项是主值(如 "id"),后续为选项(如 "omitempty""-"
  • 若首项为 "-",表示忽略该字段(如 json:"-"
  • 可封装一个辅助函数,例如:func parseJSONTag(tag string) (name string, omit bool) { ... }

完整示例:打印所有字段的 json tag 名称和是否忽略空值

以下代码演示如何遍历结构体字段并解析 json 标签:

type User struct {
    ID     int    `json:"id"`
    Name   string `json:"name,omitempty"`
    Email  string `json:"email"`
    Secret string `json:"-"`
}

func printJSONTags(v interface{}) {
    t := reflect.TypeOf(v)
    if t.Kind() == reflect.Ptr {
        t = t.Elem()
    }
    if t.Kind() != reflect.Struct {
        return
    }

    for i := 0; i < t.NumField(); i++ {
        field := t.Field(i)
        jsonTag := field.Tag.Get("json")
        if jsonTag == "" || jsonTag == "-" {
            continue
        }
        parts := strings.Split(jsonTag, ",")
        name := parts[0]
        omit := false
        for _, opt := range parts[1:] {
            if opt == "omitempty" {
                omit = true
                break
            }
        }
        fmt.Printf("Field: %s → JSON name: %q, omit empty: %t\n", field.Name, name, omit)
    }
}

User{} 调用该函数,输出类似:

Field: ID → JSON name: "id", omit empty: false
Field: Name → JSON name: "name", omit empty: true
Field: Email → JSON name: "email", omit empty: false

注意事项与常见坑

  • 结构体字段必须是导出的(首字母大写),否则 reflect 无法访问其 tag
  • 不能对未导出字段调用 Field(i).Tag.Get(...),会返回空字符串且无错误提示
  • tag 值中的空格不自动去除,比如 json:" name "` 会被原样返回,解析时注意 strings.TrimSpace
  • 如果需要支持多个 tag(如同时读 jsondb),只需多次调用 Tag.Get("xxx")