Home > OS >  golang: How to check for exported fields in an interface
golang: How to check for exported fields in an interface

Time:02-12

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)
        }
    }
}

https://go.dev/play/p/0J3VXmFPe87

  • Related