反射:
在编译时不知道这些变量的具体类型,在运行时检查和更新变量的值、调用变量的方法和变量支持的内在操作。
反射的类型对象(reflect.Type)
使用 reflect.TypeOf() 函数可以获得任意值的类型对象(reflect.Type),程序通过类型对象可以访问任意值的类型信息
package mainimport ("fmt""reflect")// 定义一个Enum类型type Enum intconst (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 structEnum int
反射种类(Kind)
种类(Kind)指的是对象归属的品种, Kind 方法不会像 Type 方法一样区分 自定义的MyInt 和 int。
type Kind uintconst (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 行代码修改为下面的样子,则可以正常打印。
