Golang反射机制

反射概念:

  反射是一种让程序检查自身结构的能力

特殊的静态类型interface

  interface类型是一种特殊的类型,它代表方法集合,可以存放实现了其方法的值。

反射三定律

  反射可以将interface类型变量转换成反射对象

import (
	"fmt"
	"reflect"
)

func main() {
	var x float64
	x = 7.66
	t := reflect.TypeOf(x)
	fmt.Println("Type:", t)
	v := reflect.ValueOf(x)
	fmt.Println("Value:", v)
}

  反射是针对interface变量的,其中TypeOf()和ValueOf()接收的参数都是interface类型的,即上述代码中的x的值是被转换了interface传入的。

  反射可以将反射对象还原成interface对象

import (
	"fmt"
	"reflect"
)

func main() {
	var e int
	e = 10
	v := reflect.ValueOf(e)
	var y int = v.Interface().(int)
	fmt.Println("value:", y)
	fmt.Println("the type of y :", reflect.TypeOf(y))
}

  对象e转换成反射对象v,v又通过Interface()接口转换成interface对象,interface对象又通过int断言获取int类型的值  

  反射对象可修改,value值必须是可设置的

  通过反射可以将interface类型变量转换成反射对象,可以使用该反射对象设置其持有的值。

   首先,尝试修改反射对象的value

import (
	"fmt"
	"reflect"
)

func main() {
	var new_x float64
	new_x = 2.5
	v := reflect.ValueOf(new_x)
	v.SetFloat(25.23)
	fmt.Println(v)
}

运行结果:
goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x14000066ed8?)
        /usr/local/go/src/reflect/value.go:260 +0x74
reflect.flag.mustBeAssignable(...)
        /usr/local/go/src/reflect/value.go:247
reflect.Value.SetFloat({0x10028aee0?, 0x1400011c008?, 0x14000066f28?}, 0x40393ae147ae147b)
        /usr/local/go/src/reflect/value.go:2219 +0x40
main.main()
        /Users/kol/go/src/GoSJ/ch10-reflect/reflect_3.go:12 +0xec

  上例中,传入reflect.ValueOf()函数的其实是x的值,而非x本身。即通过v修改其值是无法影响x的,也即是无效 的修改,所以golang会报错。

  想到此处,即可明白,如果构建v时使用x的地址就可实现修改了,但此时v代表的是指针地址,我们要设置的是指针所 指向的内容,也即我们想要修改的是 *v 。 那怎么通过v修改x的值呢?

  reflect.Value 提供了 Elem() 方法,可以获得指针向指向的 value 。

  修改如下:

  

import (
	"fmt"
	"reflect"
)

func main() {
	var new_x float64
	new_x = 2.5
	v := reflect.ValueOf(&new_x)
	v.Elem().SetFloat(25.25)
	fmt.Println("new_x:", v.Elem().Interface())
}

输出如下:
new_x: 25.25

 

posted @ 2023-05-11 16:25  99号的格调  阅读(34)  评论(0)    收藏  举报