Go 语言入门很简单:Go 反射
Go 语言也提供了 Java 类似的功能:反射。在编译不知道类型的情况下做到动态地操纵对象的值:
更新变量
运行时查看值
调用方法
什么是反射
Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。 -- 《Go 语言圣经》
反射是指在程序运行期对程序本身进行访问和修改的能力,程序在编译时变量被转换为内存地址,变量名不会被编译器写入到可执行部分,在运行程序时程序无法获取自身的信息。
反射可以在程序编译期将变量的反射信息,如字段名称、类型信息、结构体信息等整合到可执行文件中,并给程序提供接口访问反射信息,这样就可以在程序运行期获取类型的反射信息,并且有能力修改它们。
reflect 包
Go 语言中的反射是由 reflect 包提供支持的,reflect 包提供了 reflect.TypeOf 和 reflect.ValueOf 两个函数来获取任意对象的 Value 和 Type。
reflect 包实现了运行时的反射能力,能够让程序操作不同类型的对象。反射包中有两对非常重要的函数和类型,两个函数分别是:
reflect.TypeOf 能获取类型信息;
reflect.ValueOf 能获取数据的运行时表示;
获取类型
Go 使用 reflect.TypeOf()
函数可以获得任意值的类型对象(reflect.Type)
运行该代码:
代码解释:
第 5 行导入
reflect
包第 10 行定义了一个 “Hello,World!”的字符串变量 hello
第 12 行定义一个 typeOfHello 的变量接收 hello 的类型
第 14 行打印出 typeOfHello 变量的类型名为 string,类别(Kind)为 string。
(Type)和类别(Kind)的区别:Type 表示 Go 语言的一个类型,它是一个有很多方法的接口,可以用来识别一个结构的字段或者一个函数的各个参数。但在反射中,当需要区分一个大品种的类型时,就会用到种类(Kind)。例如需要统一判断类型中的指针时,使用类别(Kind)信息就较为方便。
reflect.Type 和 reflect.Value
reflect.TypeOf 函数接受任何的 interface{} 参数,并且把接口中的动态类型以 reflect.Type 形式返回,它返回的总是具体类型(而不会是接口类型)。
reflect.Value 可以包含一个任意类型的值。可以返回一个接口值。
reflect.ValueOf 函数接收任意的 interface{} 并将接口的动态值以 reflect.Value 的形式返回。同样也是返回具体值。
运行代码:
通过反射修改值
反射也可以用来修改变量的值,那么一定要传入变量的指针类型,这样才能修改原来的值。同时需要使用到reflect.ValueOf(v).Elem()
方法。
Elem 返回 v 持有的接口保管的值的 Value 封装,或者 v 持有的指针指向的值的 Value 封装。如果 v 的 Kind 不是 Interface 或 Ptr 会 panic ;如果 v 持有的值为 nil ,会返回 Value 零值。
运行代码:
在数组上使用
也可以在数组的整数上使用反射 Append 和 ValueOF 函数:
运行代码,结果为:
总结
在 Golang 反射中,反射允许我们在动态处更改或修改对象或任何变量。Go 作为静态类型语言,需要利用 Go 语言的 reflect 包反映来使用此功能。 可以通过 reflect.Type 获得任意变量类型,通过 reflect.value 获取或者设置实际变量的值。
参考资料:
版权声明: 本文为 InfoQ 作者【宇宙之一粟】的原创文章。
原文链接:【http://xie.infoq.cn/article/d968e55d50a2d276fd22cc763】。文章转载请联系作者。
评论