源自官方博客一篇文章《The Laws of Reflection》,主要是对于interface类型和反射的一些概念性定义,以下内容仅用于个人记录,如果没有读过原文可能阅读体验不好,请谅解。
类型与接口
- go是静态类型语言
- go是强类型语言
- 别名类型也必须强转才能赋值类原类型
- interface类型可以持有任意实现其方法的类型实例的值
- interface{}其实是含有0个方法的接口类型,可以这样理解,任意类型都实现了0个方法,所以它可以表示任意类型,这是个极端例子
- 尽管如此,interface{}并不是动态类型
interface类型的表达
强转发生在类型的方法不构成超集子集关系时,目标类型的方法是源类型方法子集时,无需转换。因此任意类型可以不用强转直接转换成interface{},因为它的方法集是空集,是任意方法集合的子集。
interface类型里包含了(值、类型)对儿,但是类型不能是interface类型,简单来说就是禁止套娃。
反射三原则
反射第一条:Reflection goes from interface value to reflection object.
- 这里有几种类型了:Value、Type、Kind,这一条law就是在讲,反射是把interface类型转换成这些reflect库类型,这个过程叫unpack。简单来说,反射就是对interface中的类型的检查和解构。
- 两个关键方法,reflect.ValueOf、reflect.TypeOf读取值和值类型
- TypeOf可以以字符串形式输出类型,与ValueOf().Type()作用一致
- ValueOf返回值信息,注意不是值本身,取值本身需要使用Float、Int等方法
- Kind方法返回常量,可用于类型对比,比如Kind() == reflect.Int32
- reflect.Int无法区分Int和用户自定义的Int别名类型(推测compile阶段会使用原生类型替换掉别名)
反射第二条:Reflection goes from reflection object to interface value
- reflect.Interface方法可以把reflect.Value类型重新打包成interface类型,这个过程叫pack,simple & easy
反射第三条:To modify a reflection object, the value must be settable
- Value有一系列setter函数,可以修改interface中的值部分,但是需要interface中的值是【可被寻追的addressable】
- 因为在reflect.ValueOf的过程中,实际是值拷贝,除非传入指针类型,否则reflect.ValueOf中存储的值,就不是addressable的,这会引发panic
- Value的Elem方法可以返回另外一个Value,对这个Value的修改,将会直接修改原Value指针指向的地址,当然也必须通过getter/setter方法进行
有关结构体
- 结构体反射需要通过Elem取得reflect.Value对象,然后通过NumField(获取字段值数目)、Field(获取字段值信息)、Type(获取结构体字段类型信息)等方法/字段,来完善结构体信息
- 对结构体中的元素修改,通过Field取得值对应Value,通过setter方法修改。需要注意最初传入的结构体对象,依然需要是settable/addressable的。