Chinaunix首页 | 论坛 | 博客
  • 博客访问: 389776
  • 博文数量: 273
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1430
  • 用 户 组: 普通用户
  • 注册时间: 2018-02-02 15:57
文章分类

全部博文(273)

文章存档

2018年(273)

我的朋友

分类: SQLite/嵌入式数据库

2018-06-27 15:57:23

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

go的reflect库有两个重要的类型:

d47e62d2b349aca45e42305ed6714efbe5ed61d9reflect.Type
d47e62d2b349aca45e42305ed6714efbe5ed61d9reflect.Value

Type,Value分别对应对象的类型和值数据

还有两个重要的函数:

d47e62d2b349aca45e42305ed6714efbe5ed61d9reflect.TypeOf(i interface{}) Type

reflect.TypeOf()返回值的类型就是reflect.Type。
d47e62d2b349aca45e42305ed6714efbe5ed61d9reflect.ValueOf(i interface{}) Value
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(int) StructField
11 FieldByName(name string) (StructField, bool)
12 Len() int
13 .....
14}
15

可见reflect.Type是一个接口类型的对象,这个接口包含了很多方法,像Name(),Field(),Method()等,下面再通过实例来了解几个比较重要的方法。

 
1type Foo struct {
2 X string
3 Y int
4}
5
6func (f Foo) do() {
7 fmt.Printf("X is: %s, Y is: %d", f.X, f.Y)
8
9}
10
11func main() {
12 var s string = "abc"
13 fmt.Println(reflect.TypeOf(s).String()) //string
14 fmt.Println(reflect.TypeOf(s).Name()) //string
15
16 var f Foo
17 typ := reflect.TypeOf(f)
18 fmt.Println(typ.String()) //main.Foo
19 fmt.Println(typ.Name()) //Foo ,返回结构体的名字
20
21}

上面的例子可见,通过Type.String(),Type.Name()方法就可以获得接口对应的静态类型。 下面几个方法,显示了Type的更多功能,特别是对于结构体对象而言。



阅读(1740) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~