14、go的反射

基本数据类型反射

// 利用函数的参数定义为空接口
func testRefect(i interface{}) {
	// 调用TypeOf函数,返回reflect.Type类型的数据
	reType := reflect.TypeOf(i)
	fmt.Println(reType) // int
	// 调用ValueOf函数,返回reflect.Value类型数据
	reValue := reflect.ValueOf(i)
	fmt.Println(reValue) // 100
	// 虽然看着打印的是100这个数值,但它是value类型
	//num := 100 + reValue	// 这样编译就会直接报错了
	// 如果想要获取reValue的数值,用它的Int()方法
	num := 100 + reValue.Int()
	fmt.Println(num) // 200

	// reValue转成空接口
	a := reValue.Interface()
	// 类型断言
	i2 := a.(int)
	i3 := i2 + 30
	fmt.Println(i3) // 130
}
func main() {
	// 对基本数据类型进行反射
	var num int = 100
	testRefect(num)
}

image

反射对结构体反射

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

func testRefect2(i interface{}) {
	// 调用TypeOf函数,返回reflect.Type类型的数据
	reType := reflect.TypeOf(i)
	fmt.Println(reType) //main.Student
	// 调用ValueOf函数,返回reflect.Value类型数据
	reValue := reflect.ValueOf(i)
	fmt.Println(reValue) //{二狗 18}
	// reValue转成空接口
	a := reValue.Interface()
	student, flag := a.(Student)
	if flag { // 断言成功的话
		fmt.Printf("姓名:%v, 年龄:%v", student.Name, student.Age) //姓名:二狗, 年龄:18
	}
}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	testRefect2(student)
}

反射获取变量类别

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

func testRefect3(i interface{}) {
	// 调用TypeOf函数,返回reflect.Type类型的数据
	reType := reflect.TypeOf(i)
	// 调用ValueOf函数,返回reflect.Value类型数据
	reValue := reflect.ValueOf(i)
	// 通过reType获取变量的类别
	kind := reType.Kind()
	fmt.Println(kind) // struct
	// 通过reValue获取,类别是否一样
	kind2 := reValue.Kind()
	fmt.Println(kind2) //struct

	// 获取变量的类型
	// reValue转成空接口
	a := reValue.Interface()
	student, flag := a.(Student)
	if flag { // 断言成功的话
		fmt.Printf("结构体类型:%T", student) //结构体类型:main.Student
	}

}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	testRefect3(student)
}

反射修改变量的值

func testRefect4(i interface{}) {
	reValue := reflect.ValueOf(i)
	// 通过SetInt()改变值
	reValue.Elem().SetInt(40)
}
func main() {
	var num int = 100
	testRefect4(&num) // 传指针地址h
	fmt.Println(num)	// 40
}

反射操作结构体

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

func (s Student) CPrint() {
	fmt.Println("调用了Print()方法")
	fmt.Println("名字是:", s.Name)
}
func (s Student) AGetSum(n1, n2 int) int {
	fmt.Println("调用了AGetSum()方法")
	return n1 + n2
}
func (s Student) BSet(name string, age int) {
	s.Name = name
	s.Age = age
}

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

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

	// 通过reflect.Value类型操作结构体方法
	method := val.NumMethod()
	fmt.Println(method) // 3

	//调用CPrint()方法
	// 方法顺序安装ASCII顺序排列的,注意方法名首字母大写
	val.Method(2).Call(nil)

	//调用AGetSum()方法
	// 定义value的切片
	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(20))
	call := val.Method(0).Call(params)
	fmt.Println(call[0].Int())	// 30
}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	TestStudentStruct(student)
}

打印:
image

反射修改变量值

// 定义学生结构体
type Student struct {
	Name string
	Age  int
}

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

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

	// 修改字段的值
	val.Elem().Field(0).SetString("张三")
}
func main() {
	student := Student{
		Name: "二狗",
		Age:  18,
	}
	TestStudentStruct(&student)
	fmt.Println(student)
}
posted @ 2022-11-25 16:00  aBiu--  阅读(26)  评论(0编辑  收藏  举报