A simple introduction to golang reflect reflection

Table of contents

get field name

Get field type and value

set field value

static assignment

Interface slices are mapped to structures (dynamic assignment)

Advanced - map is mapped into a structure

Summarize


First, there is a definition of the following structure

type User struct {
	UserName string
	UserId   int `name:"uid"`
}

Initialize an instance of a struct

u := User{"octoboy", 101}

get field name

 First get the Type variable of the variable

t := reflect.TypeOf(u)

It should be noted that if the incoming u is a pointer, such as &User{"octoboy", 101}

if t.Kind() == reflect.Ptr {
	t = t.Elem()
}

Here, the type of the variable is obtained through the Kind() function, and if the type is a pointer, it is necessary to use Elem() to obtain the content pointed to by the pointer.

Then traverse the fields of the structure to get its field name

	for i := 0; i < t.NumField(); i++ {
		fmt.Println(t.Field(i).Name)
	}

Output result:

UserName
UserId

Get field type and value

v := reflect.ValueOf(u)
if v.Kind() == reflect.Ptr { //类型为指针 需要取elem
	v = v.Elem()
}

 To get the value or assignment of a field, you need to use the ValueOf method

for i := 0; i < v.NumField(); i++ {
	//v.Field(i).Int() v.Field(i).String() 都可以把值返回出来,相当于断言 类型不匹配会直接panic
	//直接断成interface 任意类型
	fmt.Println(v.Field(i).Interface())
}

Output result:

sick

101

Continue to output the type of member variables

for i := 0; i < v.NumField(); i++ {
	fmt.Println(v.Field(i).Kind())
}

Output result:

string

int 

set field value

static assignment

	//设置字段值
	va := reflect.ValueOf(&u) //这里必须使用指针 否则后面调用Set无法使用无地址的值
	if va.Kind() == reflect.Ptr { //类型为指针 需要取elem 意为取它指向的内容值
		va = va.Elem()
	}
	for i := 0; i < va.NumField(); i++ {
		//两种方法取设置字段的值,第二种更为统一
		if va.Field(i).Kind() == reflect.String {
			//重要 如果需要使用set取修改u中的值,需要在ValueOf中传入u的地址。否则会因为SetString使用了一个不能被寻址的值而造成panic
			va.Field(i).SetString("octoboy")
		}
		if va.Field(i).Kind() == reflect.Int {
			va.Field(i).Set(reflect.ValueOf(123))
		}
	}

Interface slices are mapped to structures (dynamic assignment)

	//练手
	values := []interface{}{"octoboy", 123}
	for i := 0; i < va.NumField(); i++ {
		if reflect.ValueOf(values[i]).Kind() == va.Field(i).Kind() {
			va.Field(i).Set(reflect.ValueOf(values[i]))
		}
	}

 Print the variables of the above two structural questions

Output result:

&{octoboy 123}

Advanced - map is mapped into a structure

There is the following code

	//练习 把map映射成struct
	set := map[string]interface{}{
		"UserName": "zyg",
		"UserId":   101,
		"Age":      19,
		"Sex":      1,
	}
	user := &User{}
	MapToStruct(set, user)
	fmt.Println(user)

It is required to map the map to the user structure question, that is, if the field name of User exists in the key of the map, then assign the corresponding value to the member variable of the user structure question

have the following implementation

//str类型为interface{} 代表可以传入任意的结构体
func MapToStruct(m map[string]interface{}, str interface{}) {
	val := reflect.ValueOf(str)
	if val.Kind() != reflect.Ptr {//必须是指针 否则无法用Set赋值
		panic(any("must be ptr!"))
	}
	val = val.Elem()
	if val.Kind() != reflect.Struct { //指针指向的必须是结构体
		panic(any("must be struct"))
	}
	for i := 0; i < val.NumField(); i++ {
		name := val.Type().Field(i).Name //value转type后取字段名称
		if v, ok := m[name]; ok {        //如果根据tag做映射,就使用val.Type().Field(i).Tag.Get("name")作为key
			if reflect.ValueOf(v).Kind() == val.Field(i).Kind() {
				val.Field(i).Set(reflect.ValueOf(v))
			}
		}
	}
}

Summarize

1.TypeOf uses Name to obtain the field name, and can also use Kind to obtain the field type; ValueOf can only use Kind to obtain the field type.

2. Use reflect.ValueOf(u).Type() to convert to type, which can achieve the same effect as reflect.TypeOf(u).

3. If you want to use Set, SetString and other methods to assign values ​​to it, the u in reflect.ValueOf(u) must pass in a pointer, otherwise it cannot be addressed and a panic will occur

4.reflect.ValueOf(u).Interface() can get the value. In actual use, the returned result is often asserted as an interface type to call the interface function

Guess you like

Origin blog.csdn.net/kingu_crimson/article/details/127665684