go 反射
go 是静态类型语言。注意,interface 也是静态类型,如果一个接口变量被赋值了其他变量,那么其他变量必须实现该接口包含的方法。
type MyInt int
var a MyInt
// a 的静态类型是 MyInt,底层类型是 int。
// 获取静态类型:reflect.TypeOf(a)
// 获取底层类型:relect.TypeOf(a).Kind() 或 relect.ValueOf(a).Kind()
- reflect.TypeOf(i) :获得接口值的类型
- reflect.ValueOf(i):获得接口值的值
这两个方法返回的对象,我们称之为反射对象:Type object 和 Value object。
反射第一定律:反射可以将接口类型变量转换为反射类型变量。
func main() {
var age interface{} = 25
fmt.Printf("原始接口变量的类型为 %T,值为 %v \n", age, age)
t := reflect.TypeOf(age)
v := reflect.ValueOf(age)
// 从接口变量到反射对象
fmt.Printf("从接口变量到反射对象:Type对象的类型为 %T \n", t)
fmt.Printf("从接口变量到反射对象:Value对象的类型为 %T \n", v)
}
//原始接口变量的类型为 int,值为 25
//从接口变量到反射对象:Type对象的类型为 *reflect.rtype
//从接口变量到反射对象:Value对象的类型为 reflect.Value
反射第二定律:反射可以将反射类型变量转换成接口类型变量。
func main() {
var age interface{} = 25
fmt.Printf("原始接口变量的类型为 %T,值为 %v \n", age, age)
t := reflect.TypeOf(age)
v := reflect.ValueOf(age)
// 从接口变量到反射对象
fmt.Printf("从接口变量到反射对象:Type对象的类型为 %T \n", t)
fmt.Printf("从接口变量到反射对象:Value对象的类型为 %T \n", v)
// 从反射对象到接口变量
i := v.Interface()
fmt.Printf("从反射对象到接口变量:新对象的类型为 %T 值为 %v \n", i, i)
}
//原始接口变量的类型为 int,值为 25
//从接口变量到反射对象:Type对象的类型为 *reflect.rtype
//从接口变量到反射对象:Value对象的类型为 reflect.Value
//从反射对象到接口变量:新对象的类型为 int 值为 25
反射第三定律:如果要修改”反射类型变量“,其值必须是”可写的“(setable)。
package main
import (
"fmt"
"reflect"
)
func main() {
var x float32 = 1.1
v := reflect.ValueOf(x)
//v.SetFloat(1.2) // panic
fmt.Println(v.CanSet()) // false
v = reflect.ValueOf(&x)
fmt.Println(v.CanSet()) // false 因为我们要改的是 *v
target := v.Elem()
fmt.Println(target.CanSet())
target.SetFloat(2.3)
fmt.Println(x) // 2.3
}