最近在看一些go语言标准库以及第三方库的源码时,发现go的reflect被大量使用,虽然反射的机制大多数语言都支持,但好像都没有go一样这么依赖反射的特性。个人觉得,reflect使用如此频繁的一个重要原因离不开go的另一个特性,空接口interface{},reflect配合空接口,让原本是静态类型的go具备了很多动态类型语言的特征。 另外,虽然反射大大增加了go语言的灵活性,但要完全掌握它的原理和使用也还是有一点难度的。
go的reflect库有两个重要的类型:


Type,Value分别对应对象的类型和值数据
还有两个重要的函数:
reflect.TypeOf(i interface{}) Type
reflect.TypeOf()返回值的类型就是reflect.Type。

reflect.ValueIOf()返回值的类型就是reflect.Value
reflect.Type
reflect.TypeOf(i interface{}) Type
因为reflect.Typeof的参数是空接口类型,因此可以接收任意类型的数据。 TypeOf()的返回值是这个接口类型对应的reflect.Type对象。通过Type提供的一些方法,就可以获得这个接口实际的静态类型。
1import (
2 "fmt"
3 "reflect"
4)
5
6type Foo struct {
7 X string
8 Y int
9}
10
11func main() {
12 var i int = 123
13 var f float32 = 1.23
14 var l []string = []string{"a", "b", "c"}
15
16 fmt.Println(reflect.TypeOf(i)) //int
17 fmt.Println(reflect.TypeOf(f)) //float32
18 fmt.Println(reflect.TypeOf(l)) //[]string
19
20 var foo Foo
21 fmt.Println(reflect.TypeOf(foo)) //main.Foo
22
23}
查看reflect包的源代码可以看到,reflect.Type的定义如下:
1type Type interface {
2 Align() int
3 FieldAlign() int
4 Method(int) Method
5 MethodByName(string) (Method, bool)
6 NumMethod() int
7 Name() string
8 String() string
9 Elem() Type
10 Field(i int) StructField
11 FieldByName(name string) (StructField, bool)
12 Len() int
13 .....
14}
15
可见reflect.Type是一个接口类型的对象,这个接口包含了很多方法,像Name()
,Field()
,Method()
等,下面再通过实例来了解几个比较重要的方法。