Golang-反射,静态类型与动态类型
-目录-
反射,静态类型与动态类型
原理
https://segmentfault.com/a/1190000022931452
静态和动态是对于接口来说的
每个接口变量,实际上都是由一 pair 对(type 和 data)组合而成,pair 对中记录着实际变量的值和类型
根据接口是否包含方法,可以将接口分为 iface 和 eface
iface结构

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

实践
https://i6448038.github.io/2020/02/15/golang-reflection/
应用规则
//接口数据 =====》 反射对象
- Reflection goes from interface value to reflection object.
//反射对象 ===> 接口数据
- Reflection goes from reflection object to interface value.
// 倘若数据可更改,可通过反射对象来修改它
- To modify a reflection object, the value must be settable.
可通过这两个反射函数看到接口i的类型和值(动态类型,数据指针指向内容)
- reflect.TypeOf(x)
- reflect.ValueOf(x)
实例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类型

实例3
通过反射值反向求原值,但是只能得到空接口与原值,因为不知道应该对应哪个实现的interface。
// 由上可以知道,反射值是Value类型,不能直接使用,需要转换成实际值
// 强转为interface{}再类型断言
userValue := user.(User)
userForceValue := userReValue.Interface().(User)
fmt.Println(userValue, userForceValue, userValue == userForceValue) //{Tom} {Tom} true

实例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
