Reading struct tags with reflection
I wanted one struct to describe both its JSON name and a tiny validation rule. The obvious declaration was:
type User struct {
Name string `json:"name" validate:"required"`
}
My first parser split the raw tag on spaces and colons. It worked until quoting became interesting, which took approximately seven minutes. reflect.StructTag already understands the convention:
t := reflect.TypeOf(User{})
f, _ := t.FieldByName("Name")
fmt.Println(f.Tag.Get("json"))
fmt.Println(f.Tag.Get("validate"))
Output:
name
required
Tags are metadata attached to fields in the type. Reflection exposes them; the compiler does not enforce what validate:"required" means. Misspelling the key gives an empty string, indistinguishable from an explicitly empty value when using Get.
Only exported fields are useful to packages such as encoding/json, because reflection cannot generally set unexported fields from another package. I also avoid turning tags into a miniature programming language. Once a rule needs conditions, database access, or cross-field state, ordinary Go is clearer.
One more trap: reflect.TypeOf on a pointer yields a pointer type. To inspect its fields I use t.Elem(). Reflection is precise, but it is not especially interested in guessing what I meant.