Reflection means for acquiring an object dynamically at run time properties which method function call object. golang support reflection, native json library is to use reflection to achieve.
There are two main reflection golang concepts: reflect.Type
and reflect.Value
understanding type and value of literally
reflect.Type
reflect.Type
It refers to a type, a basic type int, string, or may be a custom type of structure, by reflect.TypeOf()
the type of acquisition targets
TypeOf(i interface{}) Type // 获取任意一个对象的 Type 对象
(t *Type) NumField() int // 字段数量
(t *Type) NumMethod() int // 方法数量
(t *Type) Field(i int) StructField // 返回第 i 个字段
(t *Type) FieldByName(name string) (StructField, bool) // 根据字段名获取字段
(t *Type) Name() // 字段名
(t *Type) Kind() Kind // 字段类型
type StructField struct {
Name string // 字段名
PkgPath string // 包路径
Type Type // 字段类型
Tag StructTag // 字段的 tag
}
(tag StructTag) Get(key string) string // 获取字段的 tag 中的某个 key
reflect.Value
reflect.Value
Refers to a value, the main api
ValueOf(i interface{}) Type // 获取任意一个对象的 Value 对象
(v Value) NumField() int // 字段数量
(v Value) NumMethod() int // 方法数量
(v Value) Field(i int) Value // 返回第 i 个字段
(v Value) Method(int) Value // 返回第 i 个方法
(v Value) FieldByName(name string) Value // 根据字段名获取字段
(v Value) MethodByName(string) Value // 根据方法名获取字段
(v Value) Type() Type // 获取的类型
(v Value) Int() int // 返回 int
(v Value) String() string // 返回 string
(v Value) Interface() interface{} // 返回一个 interface,之后可以转成任意对象
(v Value) Call(in []Value) []Value // 方法调用,参数和返回值都是数组的形式
(v Value) CallSlice(in []Value) []Value // 可变长参数函数调用
For example
type A struct {
F1 int `json:"f1"`
F2 string `json:"f2"`
}
Gets the type
t := reflect.TypeOf(A{})
So(t.NumField(), ShouldEqual, 2)
So(t.Field(0).Name, ShouldEqual, "F1")
So(t.Field(0).Type.Kind(), ShouldEqual, reflect.Int)
So(t.Field(0).Tag, ShouldEqual, `json:"f1"`)
So(t.Field(1).Name, ShouldEqual, "F2")
So(t.Field(1).Type.Kind(), ShouldEqual, reflect.String)
So(t.Field(1).Tag, ShouldEqual, `json:"f2"`)
The tag
So(reflect.TypeOf(A{}).Field(0).Tag.Get("json"), ShouldEqual, "f1")
So(reflect.TypeOf(A{}).Field(1).Tag.Get("json"), ShouldEqual, "f2")
Get the value
a := A{
F1: 10,
F2: "hatlonely",
}
v := reflect.ValueOf(a)
So(v.NumField(), ShouldEqual, 2)
So(v.Field(0).Int(), ShouldEqual, 10)
So(v.Field(1).String(), ShouldEqual, "hatlonely")
So(v.Field(0).Type().Kind(), ShouldEqual, reflect.Int)
So(v.Field(1).Type().Kind(), ShouldEqual, reflect.String)
So(v.FieldByName("F1").Int(), ShouldEqual, 10)
So(v.FieldByName("F2").Interface().(string), ShouldEqual, "hatlonely")
Call methods, here to note that the method receiver
is a pointer or an object, value and type of receiver should be consistent
func (a *A) Add(b int) int {
a.F1 += b
return a.F1
}
func (a A) Mul(b int) int {
return a.F1 * b
}
func (a A) Sum(vi ...int) int {
sum := 0
for _, i := range vi {
sum += i
}
return sum + a.F1
}
a := A{
F1: 10,
}
So(reflect.ValueOf(a).MethodByName("Mul").Call([]reflect.Value{reflect.ValueOf(20)})[0].Int(), ShouldEqual, 200)
So(a.F1, ShouldEqual, 10)
So(reflect.ValueOf(&a).MethodByName("Add").Call([]reflect.Value{reflect.ValueOf(20)})[0].Int(), ShouldEqual, 30)
So(a.F1, ShouldEqual, 30)
So(reflect.ValueOf(a).MethodByName("Sum").Call([]reflect.Value{
reflect.ValueOf(30), reflect.ValueOf(40), reflect.ValueOf(50),
})[0].Int(), ShouldEqual, 150)
So(reflect.ValueOf(a).MethodByName("Sum").CallSlice([]reflect.Value{
reflect.ValueOf([]int{30, 40, 50}),
})[0].Int(), ShouldEqual, 150)
link
- Complete code: https://github.com/hatlonely/hellogolang/blob/master/internal/buildin/reflect_test.go
Please indicate the source article link: https://tech.hatlonely.com/article/59