golang如何实现反射?

时间:2016-01-05 06:23:39

标签: reflection go

使用反射,我们可以获得类型名称,存储大小和给定类型的函数(例如uint64,用户定义的结构等)。甚至,我们可以修改给定类型的某些字段。 golang如何实现反思?我想通过以下方式:

  1. golang中的每个类型(包括用户定义的类型)本身都有关于类型名称,字段名称和函数名称的信息。 Golang反射只是读取这些信息或调用函数。

  2. 通过某种机制,Golang可以获取类型名称,存储大小等。而且类型本身没有这些信息。

  3. 我粗略地阅读了golang反射代码。我猜测golang使用了第二种方式。 谁能描述反射的具体实现?或者推荐一些文件?阅读所有代码对我来说很难。

2 个答案:

答案 0 :(得分:5)

这只是一个概述,可能不是100%准确,但希望你会发现它有用。

在构建时,Go链接器会将有关应用程序使用的所有类型的信息嵌入到可执行文件中(https://github.com/golang/go/blob/master/src/runtime/symtab.go#L39

每个接口值都包含一个指向数据类型描述符(https://github.com/golang/go/blob/master/src/runtime/type.go#L14

的指针

在从编译时已知类型转换为接口值的过程中,Go编译器会将此接口值的类型描述符指向具体类型描述符(在编译时已知!)。

E.g。当你致电reflect.TypeOf(uint(87))时:

  • 接口值由引用uint类型描述符
  • 的编译器创建
  • 此接口值作为参数
  • 传递给reflect.TypeOf函数
  • reflect.TypeOf函数使用可执行文件中链接器存储的类型描述符来获取有关uint类型的对齐(和其他)信息。

答案 1 :(得分:1)

接口描述在这里有详细描述:The Laws of Reflection

  

接口类型的变量存储一对:具体值   分配给变量,以及该值的类型描述符。

基本上,类型是从代码中静态知道的。更灵活的接口类型保留了原始基础类型,以便返回原始数据类型。