[Golang] reflect all

This post is about how to use reflect feature to implement as much as you want to do with Golang.

Here are some cases:

1. How to get all the fields’ name of an object?

 1type A struct{
 2    Foo string
 3    Bar int64
 4}  
 5
 6func main() {
 7    a := &A{Foo: "afoo"}
 8    val := reflect.ValueOf(a).Elem()
 9    for i:=0; i<val.NumField();i++{
10        fmt.Println(val.Type().Field(i).Name)
11    }
12}

The output:

Foo
Bar

Tips:

  1. Use .Elem after reflect.ValueOf(a), because the variable a is a pointer. If a is an object, we can get the same result as below code
a := A{Foo: "afoo"}
val := reflect.ValueOf(a)
  1. val.Field(i).Type().Name is totally different from val.Type().Field(i).Name. The latter can help you get the field’s name.
  2. To make the code safer, I usually will do the validation after reflect, such as val.IsValid(), val.Kind() or val.IsNil(). You can choose the method based on your needs.

2. How to get the fields’ name of a child object?

type A struct{
    Foo string
    Bar int64
}  

type B struct{
    ID string
    A A
}

Before my solution, you can try your own version. Then, check mine.

 1func main() {
 2    b := B{}
 3    val := reflect.ValueOf(b)
 4    for i:=0; i<val.NumField(); i++{
 5      if val.Field(i).Kind() == reflect.Struct{
 6        childVal := reflect.ValueOf(val.Field(i).Interface())
 7        for j:=0;j<childVal.NumField(); j++{
 8          fmt.Println(childVal.Type().Field(j).Name)
 9        }
10      }else{
11        fmt.Println(val.Type().Field(i).Name)
12      }
13    } 
14}

The output:

ID
Foo
Bar

Tips:

  1. Use val.Field(i).Kind()==reflect.Struct to detect if the field’s type is an struct. If so, you need to reflect this field so as to get the child’s fields.
  2. Here we use reflect.ValueOf(val.Field(i).Interface()) to reflect the child object. The point is .Interface(), because the type that reflect.ValueOf accepts is interface{}.

In fact, the compiler won’t prompt the error even if you write reflect.ValueOf(val.Field(i)), since all types in Golang implement interface{}. Unfortunately, you can’t get what you want if you write like that. Try it to have a look at the consequence.

3. What if the child object’s type is a slice or array?

type A struct{
    Foo string
    Bar int64
}  

type C struct{
    Name string
    A []A
}

Ok, I want to leave this question to you guys. If you are interested in the answer of my version, please comment below this post.

From my own experience, if you really want to take full advantage of reflect feature, it is better to build your own lexical system combined with struct tag feature, like json:"something". Then, the magic will pop up.


If this post helped you to solve a problem or provided you with new insights, please upvote it and share your experience in the comments below. Your comments can help others who may be facing similar challenges. Thank you!
Buy Me A Coffee
DigitalOcean Referral Badge
Sign up to get $200, 60-day account credit !