Dynamic Field Lookup in Go
work in progressWriting Go code for the first time in ages, I’ve recently had to recalibrate my brain a bit – though I was surprised at how little resistance I encountered there.
One thing I struggled with, however, was dynamic field lookup: Extracting data from a record based on a field name, with the latter determined at runtime – think customizing table columns.
One approach is to use reflection:
func GetFieldValue(obj interface{}, fieldName string) string {
value := reflect.ValueOf(obj)
return reflect.Indirect(value).FieldByName(fieldName).String()
}
That’s fairly slow and somewhat unwieldy though. Turns out there’s a ridiculous alternative: JSON!
package main
import (
"encoding/json"
"html/template"
"os"
)
func main() {
person := Person{
Name: "JD",
Age: 99,
Location: Location{
Lat: 123,
Lon: 456,
},
}
tmp, _ := json.Marshal(&person)
data := map[string]interface{}{}
json.Unmarshal(tmp, &data)
template.Must(template.New("main").Parse(`
{{- $data := .Data -}}
{{- range $i, $col := .Columns -}}
{{ $col }}: {{ index $data $col }}
{{ end }}
`)).Execute(os.Stdout, View{
Columns: []string{"Name", "Age"},
Data: data,
})
}
type View struct {
Columns []string
Data interface{}
}
type Person struct {
Name string
Age int
Location Location
}
type Location struct {
Lat int
Lon int
}