'Extract tags from Go struct as a reflect.Value

I'm trying to extract tags from a certain Value which is a struct. I am able to get the fields of the struct but unable to extract the tags. What am I doing wrong here? I've tried many different ways (using reflect.Type, interface{} etc) but all failed.


type House struct {
    Room string
    Humans Human
}

type Human struct {
    Name         string `anonymize:"true"` // Unable to get this tag
    Body         string
    Tail         string `anonymize:"true"` // Unable to get this tag
}

func printStructTags(f reflect.Value) { // f is of struct type `human`
    for i := 0; i < f.NumField(); i++ {
        fmt.Printf("Tags are %s\n", reflect.TypeOf(f).Field(i).Tag) // TAGS AREN'T PRINTED
    }
}

The reason I use reflect.Value as the parameter is because this function is called from another function in the following manner

    var payload interface{}
    payload = &House{}
    // Setup complete
    v := reflect.ValueOf(payload).Elem()
    for j := 0; j < v.NumField(); j++ { // Go through all fields of payload
        f := v.Field(j)
        if f.Kind().String() == "struct" { 
            printStructTags(f)
        }
    }

Any insights would be extremely valuable



Solution 1:[1]

When you call reflect.TypeOf(f) you get the type of f, which is already a reflect.Value.

Use the Type() func of this f to get the type and do the Field check on it:

func printStructTags(f reflect.Value) { // f is of struct type `human`
    for i := 0; i < f.NumField(); i++ {
        fmt.Printf("Tags are %s\n", f.Type().Field(i).Tag) 
    }
}

However, it's easier to check for a tag and get its value with f.Type().Field(i).Tag.Get("anonymize"). This way you directly get the assigned value, for example true in your case and an empty string if the tag doesn't exist.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jawspeak