反射:
在编译时不知道这些变量的具体类型,在运行时检查和更新变量的值、调用变量的方法和变量支持的内在操作。
反射的类型对象(reflect.Type)
使用 reflect.TypeOf() 函数可以获得任意值的类型对象(reflect.Type),程序通过类型对象可以访问任意值的类型信息
package main
import (
"fmt"
"reflect"
)
// 定义一个Enum类型
type Enum int
const (
Zero Enum = 0
)
func main() {
// 声明一个空结构体
type cat struct {
}
// 获取结构体实例的反射类型对象
typeOfCat := reflect.TypeOf(cat{})
// 显示反射类型对象的名称和种类
fmt.Println(typeOfCat.Name(), typeOfCat.Kind())
// 获取Zero常量的反射类型对象
typeOfA := reflect.TypeOf(Zero)
// 显示反射类型对象的名称和种类
fmt.Println(typeOfA.Name(), typeOfA.Kind())
}
输出
cat struct
Enum int
反射种类(Kind)
种类(Kind)指的是对象归属的品种, Kind 方法不会像 Type 方法一样区分 自定义的MyInt 和 int。
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 // 底层指针
)
指针
reflect.Elem() 方法获取这个指针指向的元素类型
结构体
通过反射值对象 reflect.Type 的 NumField() 和 Field() 方法获得结构体成员的详细信息。
方法 | 说明 |
---|---|
Field(i int) StructField | 根据索引返回索引对应的结构体字段的信息,当值不是结构体或索引超界时发生宕机 |
NumField() int | 返回结构体成员字段数量,当类型不是结构体或索引超界时发生宕机 |
FieldByName(name string) (StructField, bool) | 根据给定字符串返回字符串对应的结构体字段的信息,没有找到时 bool 返回 false,当类型不是结构体或索引超界时发生宕机 |
FieldByIndex(index []int) StructField | 多层成员访问时,根据 []int 提供的每个结构体的字段索引,返回字段的信息,没有找到时返回零值。当类型不是结构体或索引超界时发生宕机 |
FieldByNameFunc(match func(string) bool) (StructField,bool) | 根据匹配函数匹配需要的字段,当值不是结构体或索引超界时发生宕机 |
结构体标签
- func (tag StructTag) Get(key string) string:根据 Tag 中的键获取对应的值,例如
key1:"value1" key2:"value2"
的 Tag 中,可以传入“key1”获得“value1”。 - func (tag StructTag) Lookup(key string) (value string, ok bool):根据 Tag 中的键,查询值是否存在。
注意:在 json: 和 “type” 之间增加了一个空格,这种写法没有遵守结构体标签的规则,因此无法通过 Tag.Get 获取到正确的 json 对应的值。这个错误在开发中非常容易被疏忽,造成难以察觉的错误。所以将第 12 行代码修改为下面的样子,则可以正常打印。