Last active
September 6, 2018 14:29
-
-
Save fiorix/5da590addb2486e0d83cf31c6a35d46a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package walkstruct | |
import ( | |
"fmt" | |
"reflect" | |
"unicode" | |
) | |
// WalkStruct walks the exported fields of a struct using reflection, | |
// and calls fn for each field. | |
func WalkStruct(s interface{}, fn func(reflect.StructField, reflect.Value)) { | |
t := reflect.TypeOf(s) | |
v := reflect.ValueOf(s) | |
if v.Kind() == reflect.Ptr { | |
v = v.Elem() | |
t = t.Elem() | |
} | |
if v.Kind() != reflect.Struct { | |
panic(fmt.Sprintf("WalkStruct: s is not struct: %T", s)) | |
} | |
for i := 0; i < v.NumField(); i++ { | |
ft := t.Field(i) | |
if !exportedField(ft) { | |
continue | |
} | |
fn(ft, v.Field(i)) | |
} | |
} | |
func exportedField(f reflect.StructField) bool { | |
return !f.Anonymous && unicode.IsUpper(rune(f.Name[0])) | |
} | |
// StructFields returns the names of all exported fields of struct s. | |
func StructFields(s interface{}, tag string) []string { | |
var f []string | |
WalkStruct(s, func(ft reflect.StructField, fv reflect.Value) { | |
n := ft.Tag.Get(tag) | |
if n == "" { | |
n = ft.Name | |
} | |
f = append(f, n) | |
}) | |
return f | |
} | |
// StructValues returns the values of all exported fields of struct s. | |
func StructValues(s interface{}) []interface{} { | |
var v []interface{} | |
WalkStruct(s, func(ft reflect.StructField, fv reflect.Value) { | |
v = append(v, fv.Interface()) | |
}) | |
return v | |
} | |
// StructValuesAddr returns pointer values of all exported fields of struct s. | |
func StructValuesAddr(s interface{}) []interface{} { | |
var v []interface{} | |
WalkStruct(s, func(ft reflect.StructField, fv reflect.Value) { | |
// this will panic if !fv.CanAddr(); and it should | |
v = append(v, fv.Addr().Interface()) | |
}) | |
return v | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment