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:
- Use
.Elem
afterreflect.ValueOf(a)
, because the variablea
is a pointer. Ifa
is an object, we can get the same result as below code
a := A{Foo: "afoo"}
val := reflect.ValueOf(a)
val.Field(i).Type().Name
is totally different fromval.Type().Field(i).Name
. The latter can help you get the field’s name.- To make the code safer, I usually will do the validation after
reflect
, such asval.IsValid()
,val.Kind()
orval.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:
- Use
val.Field(i).Kind()==reflect.Struct
to detect if the field’s type is anstruct
. If so, you need to reflect this field so as to get the child’s fields. - Here we use
reflect.ValueOf(val.Field(i).Interface())
to reflect the child object. The point is.Interface()
, because the type thatreflect.ValueOf
accepts isinterface{}
.
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!