short version:
import (
"fmt"
"reflect"
)
type StatusVal int
type Foo struct {
Name string
Age int
art string
}
func ListFields(a interface{}) {
v := reflect.ValueOf(a).Elem()
fmt.Printf(" Kind: % v \n", v.Type())
for _, f := range reflect.VisibleFields(v.Type()) {
if f.IsExported() {
fmt.Printf(" Kind: % v \n", f)
} else {
fmt.Printf(" Kind: %s \n", f.Name)
}
}
}
func main() {
var x Foo
ListFields(&x)
}
This code works, but what I really need is var x []Foo
, and I cannot find a way to get that to work and check for IsExported in the fields of the slice of structs.
Long version:
I was looking to generate a generic sqlToStruct function, and I bumped into this awesome answer: Generalizing *sql.Rows Scan in Go
I don't have the reputation to reply there.
The only problem with that is that if my struct has any unexported fields, it panics, and I would like to check for that and return an error to be handled, rather than let it panic.
Also: I have been coding in go for a very short amount of time, please understand where I am coming from and sorry if I am missing something absolutely obvious.
CodePudding user response:
func ListFields(a interface{}) {
rt := reflect.TypeOf(a) // take type of a
if rt.Kind() == reflect.Ptr {
rt = rt.Elem() // use Elem to get the pointed-to-type
}
if rt.Kind() == reflect.Slice {
rt = rt.Elem() // use Elem to get type of slice's element
}
if rt.Kind() == reflect.Ptr { // handle input of type like []*StructType
rt = rt.Elem() // use Elem to get the pointed-to-type
}
if rt.Kind() != reflect.Struct {
return
}
fmt.Printf(" Kind: % v \n", rt)
for _, f := range reflect.VisibleFields(rt) {
if f.IsExported() {
fmt.Printf(" Kind: % v \n", f)
} else {
fmt.Printf(" Kind: %s \n", f.Name)
}
}
}