什么是反射

反射是指程序在运行时能检查其变量和值并找到其类型的能力。
reflect实现了运行时的反射能力,能够让程序操作不同类型的对象,扩展了Go语言的语法元素。

为什么需要反射?

既然程序内部的变量已经有明确的类型和对应的值,那是不是说反射是多此一举呢?当然不是,举一个应用场景:
假设要实现一条SQL语句,根据传入的值,自动拼接成一条完整的SQL语句,例如想要实现一条普适的插入语句:

  1. insert into xxx values (xxx, xxx)

当然可以根据参数来定制不同的insertXXX()函数,但是这类函数本质上的原理是一致的,只不过根据参数的类型,数量等,最后拼接出来不同的insert语句
这种情况下,使用反射会比较方便:

  1. func creatInsertSQL(i interface{}) string {
  2. // 参数i可以是对应某张表抽象后的结构体
  3. // 使用反射,可以解析出对应的结构体名称以及结构体内各字段的名称及其类型
  4. // 从而使得最终输出形如 `insert into xxx values (xxx, xxx)`的字符串
  5. }

上述过程,就是ORM(Objet Relational Mapping, 对象关系映射)的基本原理。

反射在Go中的应用场景还有很多,诸如IDE 中的代码自动补全功能、对象序列化(encoding/json)、fmt 相关函数的实现等,后续再进行分析。

reflect package

明确了使用反射来实现上述功能,那么,先来看看使用结构体作为参数实现上述类似“自动填充”功能所需要的要素:

  • 结构体名称:对应需要插入的表名称
  • 结构体中各元素的名称、类型及对应的值

    reflect.Type和reflect.Value

    reflect.Kind

    NumField()和Field()

    Int()和String()

    何时使用反射