Go: Reflect 反射
Backlinks (1)
Backlinks (1)
1 · Reflect 反射#
反射,是程序检验自身结构的一种能力,尤其是检验类型。元编程的一种。
Go 反射本质:利用接口自带的类型信息,在运行时读取这些信息。没有”魔法”,一切都是编译期打好的”包”
提供运行时的反射能力,运行程序在运行时操作任意类型的对象。
围绕Type、Value:
// 返回 值,代表运行时的数据:解开interface
// 对应三大法则1
func ValueOf(i any) Value
// 逆操作:组装interface
// 对应三大法则2
func (v Value) Interface() (i any)
// 返回 类型,获取任意变量的类型。
// 对应三大法则1
func TypeOf(i any) Type
1.1 · 三大法则
1/2条:interface{}值 与反射对象的可以互相转换;interface是具体类型与反射类型的中间桥梁;
3条:修改反射对象的前提是必须可设置(比如常量不可设置, 值传递不是原有值);
NOTE: 核心在interface值,在运行时保存着类型信息、实际值;类型与值,即全部信息。
reflect包,是在运行时拆开interface值,获取其中的类型信息、实际值
interface 的内部结构
interface {
type *类型信息 // 指向方法集和类型描述
value *实际值 // 指向具体的数据
}
TypeOf 和 ValueOf 或其他reflect包下函数,参数都是any,也就是interface, Go 会在编译期间完成类型转换,将变量的类型和值转换成了 interface{} ,也就是把类型信息打包了, 等待运行期间使用 reflect 包获取接口中存储的信息。
- 第一个属性:Value 的 Getter/Setter API 使用”足够大”的类型
- 第二个属性:Kind 描述底层类型,不是静态类型(Type描述)
1.1.1 · settable value#
go 是值传递,传递的是副本;转换成为interface的时候,可能是副本了,那么修改不会作用到旧值
func (v Value) CanSet() bool
// 特定类型的setter, * 表示类型
func (v Value) Set*() bool
// 传递指针,然后获取其指向的元素,就可以修改了
func (v Value) Elem() Value
1.2 · 结构体
// type
//
// Field returns a struct type's i'th field.
Field(i int) StructField
FieldByName(name string) (StructField, bool)
// value
//
// Field returns the i'th field of the struct v.
func (v Value) Field(i int) Value
1.3 · 一些例子
获取接口类型 reflect.TypeOf((*<your_interface>)(nil)).Elem()
2 · 通过 reflect 学类型系统#
type system中的关系、操作,可以通过reflect中的Type和Value进行观察:
核心关系:可转换、可转换 核心操作:可比较
go doc reflect.Type.ConvertibleTo
go doc reflect.Type.Comparable
go doc reflect.Type.Implements
go doc reflect.Type.AssignableTo
go doc reflect.Value.CanConvert
go doc reflect.Value.Comparable
go doc reflect.Value.CanSet
go doc reflect.Value.CanAddr
go doc reflect.Value.Convert
go doc reflect.Value.Equal
go doc reflect.Value.Set
go doc reflect.Value.Addr