文章始发于公众号【迈莫coding】
地址:https://mp.weixin.qq.com/s/F8yZyqC5UwoewsX0THqy1w
即将用Go语言从零到一编写ORM框架,目前先把所用技术讲一遍,大家可以尽情期待,可以关注【迈莫coding】,了解最新状况。
目录
- 反射概念
- reflect包
- 反射类型(Type)和种类(Kind)
- 反射类型(Type)使用
- 反射类型对象(TypeOf)使用
- 结构体对象
- 变量
- 常量
- 指针
- 反射获取结构体的成员类型
- 介绍structField结构
- 演示
- 反射获取结构体标签(Struct Tag)
- 标签概念
- 标签格式
- 标签方法
- 标签演示
- 闲聊
- 欢迎加入我的公众号【迈莫coding】 一起pk大厂
反射基本概念
反射让我们能在运行期间探知对象的类型信息和内存结构,这从一定程度弥补了静态语言在动态行为上的不足。同时,反射还是实现元编程的重要手段。
和C数据结构一样,Go对象头部并没有类型指针,通过其自身是无法在运行期间获知任何类型相关信息的。反射操作所需的全部信息都源自接口变量。接口变量除存储自身类型外,还会保存实际对象的类型数据。
Go语言提供了一种机制在运行时更新和检查变量的值,调用变量的方法和变量支持的内在操作,但是在编译时并不知道这些变量的具体类型,这种机制被称为反射。反射也可以让我们将类型自身作为第一类的值类型处理。
Go语言程序的反射系统无法获取到一个可执行文件空间中或者是一个包中的所有类型信息,需要配合使用标准库中对应的词法,语法解析器和抽象语法树(AST)对源码进行扫描后获得这些信息。
Go语言提供了 reflect
包来访问程序的反射信息。
reflect包
Go语言中的反射是由 reflect 包提供的,它定义了两个重要类型 Type
和 Value
,分别由 reflect.TypeOf
和 reflect.ValueOf
两个函数获取。
func TypeOf(i interface{
}) Type
func ValueOf(i interface{
}) Value
这两个反射入口函数,会将任何传入的对象转换为接口类型。
在面对类型时,需要区分 Type
和 Kind
。前者表示真实类型(静态类型),后者表示其基础结构(底层结构)类别,接下来,揭开 Type
和 Kind
真面目。
反射类型(Type)和种类(Kind)
在使用反射时,首先需要理解类型(Type
)和种类(Kind
)的含义。在反射中,如果想要区别大品种的类型时,优先使用种类(Kind
),他相比类型(Type
)来说,粒度更细,比如, Map
, Slice
, Chan
都属于引用类型,但如果想区分他们的话,可以使用种类(Kind),因为他们的种类不同,分别为 Map
, Slice
, Chan
。
种类(Kind) 指的是对象归属的品种,在reflect包中有如下定义:
type Kind uint
const (
Invalid Kind = iota // 非法类型
Bool // 布尔型
Int // 有符号整型
Int8 // 有符号8位整型
Int16 // 有符号16位整型
Int32 // 有符号32位整型
Int64 // 有符号64位整型
Uint // 无符号整型
Uint8 // 无符号8位整型
Uint16 // 无符号16位整型
Uint32 // 无符号32位整型
Uint64 // 无符号64位整型
Uintptr // 指针
Float32 // 单精度浮点数
Float64 // 双精度浮点数
Complex64 // 64位复数类型
Complex128 // 128位复数类型
Array // 数组
Chan // 通道
Func // 函数
Interface // 接口
Map // 映射
Ptr // 指针
Slice // 切片
String // 字符串
Struct // 结构体
UnsafePointer // 底层指针
)
反射类型(Type)使用
结构体对象
示例:
package main
import (
"fmt"
"reflect"
)
type Turbo struct {
}
func main() {
// 初始化 struct对象
var a = Turbo{
}
// 获取a结构体的类型对象
types := reflect.TypeOf(a)
// 获取反射类型对象的名称和种类
fmt.Println