如何在不使用字段名称作为字符串的情况下获取字段的标签?

时间:2019-06-19 14:38:21

标签: go reflection

是否可以使用仅接收结构和字段本身的函数来获取字段标签?

我知道我可以做这样的事情:

['firstName', 'lastName']

但是在这种情况下,我不想将字段的名称用作字符串,因为将来可以重命名它,因此最好使用字段本身。

reflect.TypeOf(x).FieldByName("FieldNameAsString").Tag

1 个答案:

答案 0 :(得分:4)

使用偏移量查找字段:

// getTag returns the tag for a field given a pointer to
// a struct and a pointer to the field in that struct.
func getTag(pv interface{}, pf interface{}) reflect.StructTag {
    v := reflect.ValueOf(pv)
    offset := reflect.ValueOf(pf).Pointer() - v.Pointer()

    t := v.Type().Elem()
    for i := 0; i < t.NumField(); i++ {
        f := t.Field(i)
        if f.Offset == offset {
            return f.Tag
        }
    }
    return ""
}

Run it on the playground

上面的代码假定垃圾收集器没有在Pointer的to调用之间移动结构。该假设在今天是正确的,但在将来可能不是正确的。使用unsafe包使代码安全,以防将来对垃圾收集器进行更改:

// getTag returns the tag for a field with the given offset
// in the struct pointed to by pv.
func getTag(pv interface{}, offset uintptr) reflect.StructTag {
    t := reflect.TypeOf(pv).Elem()
    for i := 0; i < t.NumField(); i++ {
        f := t.Field(i)
        if f.Offset == offset {
            return f.Tag
        }
    }
    return ""
}

这样称呼它:

x := MyStruct{}
fmt.Println(getTag(&x, unsafe.Offsetof(x.MyField)))

Run it on the Playground