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
.Elemafterreflect.ValueOf(a), because the variableais a pointer. Ifais an object, we can get the same result as below code
a := A{Foo: "afoo"}
val := reflect.ValueOf(a)
val.Field(i).Type().Nameis 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.Structto 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.ValueOfaccepts 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.
Enjoyed this article? Support my work with a coffee ☕ on Ko-fi.