Go语言是静态类型语言.比如int float32 []byte32等等.每个变量都有一个静态类
型.并且在编译的时候就已经确定了.
type Myint int
var i int
var j Myint
变量i和j不是相同类型.因为二者拥有不同的静态类型.尽管二者底层的类型都是int.但
在没有类型转换的情况下是不可以相互赋值的.Go提供了布尔 数值和字符串类型的基
础类型.还有一些使用这些类型组成的复合类型.比如数组 结构体 指针 切片 map和
channel等.interface 也可以称为一种复合类型
1.interface类型:
每个interface类型代表一个特定的方法集.方法集中的方法称为接口.示例:
type Animal interface {
Speak() string
}
interface变量:
就像任何其他类型一样.也可以声明interface类型的变量.示例:
var animal Animal
type Animal interface {
Speak() string
}
上面的animal变量的值为nil.
实现接口:
任何类型只要实现了interface类型的所有方法.就可以声称该类型实现了这个接口.
该类型的变量就可以存储到interface变量中.示例:
type Animal interface {
Speak() string
}
type Dog struct {}
func (dog *Dog) Speak() string {
return "Woof!"
}
func testAnimal() {
var animal Animal
var dog Dog
animal = &dog
}
结构体Dog实现了Speak()方法.就可以存储到animal变量中.
注:interface变量可以存储任意实现了该接口类型的变量.
复合类型:
为什么interface可以存储任意实现了该接口类型的变量呢.
因为interface类型的变量在存储某个变量时会同时保存变量类型和遍历值.
源码位置:src/runtime/runtime2.go:iface
type iface struct {
tab *itab
data unsafe.Pointer
}
tab:保存变量类型(以及方法集).
data:变量值位于堆栈的指针.
Go的反射就是在运行时操作interface中的值和类型的特性.这是反射的前提.
空interface:
空interface是一种非常特殊的interface类型.它没有指定任何方法集.如此一来.任
意类型都可以声称实现了空接口.那么接口变量也就可以存储任意值.
2.反射定律:
2.1reflect包:
reflect包中提供了reflect.Type和reflect.Value两个类型.分别代表interface中的
value和类型.
// TypeOf returns the reflection [Type] that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i any) Type {
return toType(abi.TypeOf(i))
}
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i any) Value {
if i == nil {
return Value{}
}
return unpackEface(i)
}
1).第一定律:反射可以将interface类型变量转换为反射对象.
示例:
func main() {
var x float64 = 3.4
//t is reflect.Type
t := reflect.TypeOf(x)
fmt.Println(t)
value := reflect.ValueOf(x)
fmt.Println(value)
}
执行结果:
上面的例子中好像没有出现interface变量.实则不然.变量x在传入reflect.TypeOf()
函数的时候实际上做了一次类型转换,作为一个空接口传入.reflect.ValueOf()也是
如此.这个例子展示了反射可以获取interface变量的类型和值.这是反射进一步操作
interface变量的基础.
2),第二定律:反射可以将反射对象还原成interface对象.
之所以叫反射.是因为反射对象与interface对象是可以相互转换的.示例:
func main() {
var A interface{}
A = 100
v := reflect.ValueOf(A)
B := v.Interface()
if A == B {
fmt.Println("they ara same")
}
}
执行结果:
在上面的函数中.通过reflect.ValueOf()获取接口变量A的反射对象.然后又通过反射
对象的Interface()获取B.结果A和B相同.
3).第三定律:反射对象可以修改.value值必须是可设置的.
通过反射可以将interface类型的变量转换成反射对象.可以使用该反射对象设置in
terface变量持有的值.可以通过reflect.Value的一系列SetXXX()方法来设置反射对
象的值.先看一个失败的例子.示例如下:
func main() {
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1)
}
执行结果:
错误原因是v值是不可修改的.为什么会这样?
上面reflect.ValueOf()函数传入的值其实是x的值.不是x本身.通过值修改值是无法
影响到x的.是无效的修改.所以会报错.
reflect.Value提供了Elem()方法.可以获得指向value的指针.修改示例如下:
func main() {
var x float64 = 3.4
v := reflect.ValueOf(&x)
v.Elem().SetFloat(7.1)
fmt.Println(v.Elem().Interface())
}
执行结果: