laitimes

Chapter 13: Reflections

Introduction of reflections

【1】What can reflection do?

1) Reflection can dynamically obtain various information of variables at runtime, such as variable type, category and other information

2) If it is a structure variable, you can also obtain the information of the structure itself (including the fields and methods of the structure)

3) Through reflection, the value of the variable can be modified, and the associated method can be called.

4) To use reflection, import ("reflect") is required

[2] Reflection-related functions

1) reflect. TypeOf (variable name), gets the type of the variable, . Type Type

2) reflect. ValueOf (variable name), get the value of the variable, return reflect. Value type (reflect. Value is a struct type), via reflect. Value, you can get a lot of information about the variable.

Reflection on basic data types

【1】Reflection-related functions

1) reflect. TypeOf (variable name), gets the type of the variable, returns reflect. Type Type

2) reflect. ValueOf (variable name), get the value of the variable, return reflect. Value type (reflect. Value is a struct type), via reflect. Value, you can get a lot of information about the variable.

【2】Code:

package main

import (
	"fmt"
	"reflect"
)

//利用一个函数,函数的参数定义为空接口:
//空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋给空接口。
func testReflect(i interface{})  {

	//1.调用TypeOf函数,返回reflect.Type类型数据:
	reType := reflect.TypeOf(i)
	fmt.Println("reType:",reType)
	fmt.Printf("reType的具体类型是:%T \n",reType)
	//2.调用ValueOf函数,返回reflect.Value类型数据:
	reValue := reflect.ValueOf(i)
	fmt.Println("reValue",reValue)
	fmt.Printf("reValue的具体类型是:%T \n",reValue)

	// num1 := 100
	//如果真想获取reValue的数值,要调用Int()方法:返回v持有的有符号整数
	num2 := 80 + reValue.Int()
	fmt.Println(num2)

	//reValue转成空接口:
	i2 := reValue.Interface()
	n := i2.(int)
	n2 := n + 30
	fmt.Println(n2)
}

func main()  {
	var num int = 100;
	testReflect(num)
}           
Chapter 13: Reflections

Reflection on struct type

【1】Reflection-related functions

1) reflect. TypeOf (variable name), gets the type of the variable, returns reflect. Type Type

2) reflect. ValueOf (variable name), get the value of the variable, return reflect. Value type (reflect. Value is a struct type), via reflect. Value, you can get a lot of information about the variable.

【2】Code:

package main

import (
	"fmt"
	"reflect"
)

//利用一个函数,函数的参数定义为空接口:
//空接口没有任何方法,所以可以理解为所有类型都实现了空接口,也可以理解为我们可以把任何一个变量赋给空接口。
func testReflect(i interface{})  {

	//1.调用TypeOf函数,返回reflect.Type类型数据:
	reType := reflect.TypeOf(i)
	fmt.Println("reType:",reType)
	fmt.Printf("reType的具体类型是:%T \n",reType)
	//2.调用ValueOf函数,返回reflect.Value类型数据:
	reValue := reflect.ValueOf(i)
	fmt.Println("reValue",reValue)
	fmt.Printf("reValue的具体类型是:%T \n",reValue)
	// num1 := 100
	//如果真想获取reValue的数值,要调用Int()方法:返回v持有的有符号整数
	num2 := 80 + reValue.Int()
	fmt.Println(num2)

	//reValue转成空接口:
	i2 := reValue.Interface()
	n := i2.(int)
	n2 := n + 30
	fmt.Println(n2)
}

func main()  {
	var num int = 100;
	testReflect(num)
}           

Gets the category of the variable

【1】Get the category of the variable: two ways:

(1)reflect. Type.Kind()

(2)reflect. Value.Kind()

【2】The value of Kind is a constant value:

Chapter 13: Reflections

【3】Code:

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name string
	Age int
}

func testReflect(i interface{})  {
	reType := reflect.TypeOf(i)
	reValue := reflect.ValueOf(i)

	//获取变量的类别:
	//(1)reType.Kind()
	k1 := reType.Kind()
	fmt.Println(k1)

	//(2)reValue.Kind()
	k2 := reValue.Kind()
	fmt.Println(k2)

	//获取变量的类型:
	i2 := reValue.Interface()
	n,flag := i2.(Student)
	if flag == true {
		fmt.Printf("结构体的类型是:%T",n)
	}
}

func main()  {
	stu := Student{
		Name: "菜园子",
		Age: 18,
	}
	testReflect(stu)
}           

[4] The difference between Type and Kind

Type is the type, Kind is the category, Type and Kind may or may not be the same.

For example, var num int = 10 num Type is int, and Kind is int

For example, var stu Studentstu's Type is pkg1. Student , Kind is struct

Modify variables through reflection

To modify the value of a basic data type:

package main

import (
	"fmt"
	"reflect"
)

func testReflect(i interface{})  {
	reValue := reflect.ValueOf(i)
	//通过SetInt()来改变值:
	reValue.Elem().SetInt(50)
}

func main()  {
	var num int = 100
	//传入指针地址
	testReflect(&num)
	fmt.Println(num)
}           
Chapter 13: Reflections

Properties and methods that manipulate structs through reflection

[1] Code: (familiar with API)

package main

import (
	"fmt"
	"reflect"
)

type Student struct {
	Name string
	Age int
}

//给结构体绑定方法:
func (s Student) Print()  {
	fmt.Println("调用了Print()方法")
	fmt.Println("学生的名字是:",s.Name)
}

func (s Student) GetSum(n1,n2 int) int{
	fmt.Println("调用了GetSum()方法")
	return n1 + n2
}

func (s Student) Set(name string,age int)  {
	s.Name = name
	s.Age = age
}

//定义函数操作结构体进行反射操作:
func TestStudentStruct(a interface{})  {
	//a转成reflect.Value类型:
	val := reflect.ValueOf(a)
	fmt.Println(val)

	//通过reflect.Value类型操作结构体内部的字段:
	n1 := val.NumField()
	fmt.Println(n1)
	//遍历-获取具体的字段:
	for i := 0; i < n1; i++ {
		fmt.Printf("第%d个字段的值是:%v \n",i+1,val.Field(i))
	}

	//通过reflect.Value类型操作结构体内部的方法:
	n2 := val.NumMethod()
	fmt.Println(n2)

	//调用Print()方法:
	//调用方法,方法的首字母必须大写才能有对应的反射的访问权限
    //方法的顺序按照ASCII的顺序排列的,a,b,c,,,,,,索引:0,1,2,,,
	val.Method(1).Call(nil)

	//调用GetSum方法:
	//定义Value的切片:
	var params []reflect.Value
	params = append(params,reflect.ValueOf(10))
	params = append(params,reflect.ValueOf(20))
	result := val.Method(0).Call(params)
	fmt.Println("GetSum方法的返回值是:",result[0].Int())
}

func main()  {
	stu := Student{
		Name: "菜园子",
		Age: 19,
	}
	TestStudentStruct(stu)
}           

Modify variables through reflection

【1】Code:

package main

import (
	"fmt"
	"reflect"
)

type Student struct{
	Name string
	Age int
}

func (s Student) Print() {
	fmt.Println("调用了Print()方法")
	fmt.Println("学生的姓名是:",s.Name)
}

func (s Student) GetSum(n1,n2 int) int {
	fmt.Println("调用了GetSum()方法")
	return n1 + n2
}

func (s Student) Set(name string,age int)  {
	s.Name = name
	s.Age = age
}

func TestReflectStuct(a interface{})  {
	//a转成reflect.Value类型:
	val := reflect.ValueOf(a)
	fmt.Println(val)

	n := val.Elem().NumField()
	fmt.Println(n)

	//修改字段的值:
	val.Elem().Field(0).SetString("Idea")
}

func main()  {
	stu := Student {
		Name: "菜园子",
		Age: 19,
	}

	TestReflectStuct(&stu)

	fmt.Println(stu)
}           

Reference source: golang-demo: golang learning

Reference blog: CYZ