golang 反射

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.Typeand reflect.Valueunderstanding type and value of literally

reflect.Type

reflect.TypeIt 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 receiveris 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

Please indicate the source article link: https://tech.hatlonely.com/article/59

Guess you like

Origin www.cnblogs.com/hatlonely/p/11945431.html