Golang-反射,静态类型与动态类型

-目录-

反射,静态类型与动态类型

原理

https://segmentfault.com/a/1190000022931452

静态和动态是对于接口来说的

每个接口变量,实际上都是由一 pair 对(type 和 data)组合而成,pair 对中记录着实际变量的值和类型

根据接口是否包含方法,可以将接口分为 ifaceeface

iface结构

iface 结构

eface结构,itab指针里的静态类型为空

eface 结构组成

实践

https://i6448038.github.io/2020/02/15/golang-reflection/

应用规则

//接口数据 =====》 反射对象

  1. Reflection goes from interface value to reflection object.

//反射对象 ===> 接口数据

  1. Reflection goes from reflection object to interface value.

// 倘若数据可更改,可通过反射对象来修改它

  1. To modify a reflection object, the value must be settable.

可通过这两个反射函数看到接口i的类型和值(动态类型,数据指针指向内容)

实例1

//静态类型,i的静态类型是interface{},此时i没有动态类型
var i interface{}
//动态类型,此时i的动态类型是string,因为a实现了空interface
i="OK"

实例2

type User struct {
	Name string
}

type UserFun interface {
	GetName()
}

func (u User) GetName() {
}

func main() {
	var user UserFun
	user = User{"Tom"} //不加上这句话打印显示 <nil> <invalid reflect.Value>  加上后打印显示main.User {Tom}
	userReType := reflect.TypeOf(user)
	userReValue := reflect.ValueOf(user)

	// 打印动态类型和动态值
	fmt.Println(userReType, userReValue)

	// 比较反射类型和反射值的类型是否相同
	userReValueType := userReValue.Type()
	fmt.Println(userReType, userReValueType, userReType == userReValueType) //main.User main.User true

	// 比较反射值是否和真实值相同
	//userValue := user.(User)
	//fmt.Println(userReValue==userValue) //报错静态类型不匹配 Invalid operation: userReValue==userValue (mismatched types Value and User)


}

反射得到的type就是这个反射值(动态类型值)的type

而反射得到的值和真正的值不是一个type,反射ValueOf()返回的值是Value类型,而不是实际的User类型

img

实例3

通过反射值反向求原值,但是只能得到空接口与原值,因为不知道应该对应哪个实现的interface。

	// 由上可以知道,反射值是Value类型,不能直接使用,需要转换成实际值
	// 强转为interface{}再类型断言
	userValue := user.(User)
	userForceValue := userReValue.Interface().(User)
	fmt.Println(userValue, userForceValue, userValue == userForceValue) //{Tom} {Tom} true

img

实例4

通过反射更改原值

func main() {
	var user UserFun
	user = User{"Tom"}
	//注意这里需要传指针,否则后面无法修改
	userReValue := reflect.ValueOf(&user)
	//通过Set方法设置值,参数仍然是Value类型,但是因为函数传参是值拷贝,会报错 panic: reflect: reflect.Value.Set using unaddressable value
	//userReValue.Set(reflect.ValueOf(User{"Jerry"}))
	//需要先用Elem获取指针
	userReValue.Elem().Set(reflect.ValueOf(User{"Jerry"}))
	fmt.Println(user) //{Jerry}

}

总结

变量<===>interface()<===>reflect.Value

img

© 2019 - 2023 · YuYoung's Blog