go中reflect反射的使用笔记
Published on:2022-11-02
一、介绍
reflect包实现了运行时反射,允许程序操作任意类型的对象。
典型用法是用静态类型interface{}保存一个值,
通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。
调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。
Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值。
二、理解
TypeOf 获取参数的类型相关信息,若是结构体,也可以获取结构体成员相关信息。
ValueOf 获取参数的值的相关信息,可以通过调用Type() 获取TypeOf的类型信息。
如果只是获取类型相关信息信息可以使用TypeOf
若需要操作值或值和类型 可以只是用ValueOf
如果参数是一个指针引用类型 Ptr 所有得操作需要加上 Elem()
三、TypeOf常用总结
Kind() Kind 返回参数类型 reflect包下的常量 Array Chan Func Interface Map Ptr Slice String Struct 等
Name() string 返回自定义类型的名称。例如自己定义的 type TestInfo struct 类型 会返回TestInfo, 否则返回""
Len() int 返回map、array、slice、chan类型的长度
结构体相关的操作
NumField() int 返回结构体struct类型的成员的数量
Field(i int) StructField 返回struct类型的第i个字段的类型
FieldByIndex(index []int) StructField 参数为StructField中的Index
FieldByName(name string) (StructField, bool) 通过名称获取某个成员
type StructField struct {
Name string // 字段的名字
Type Type // 字段的类型
Tag StructTag // 字段的标签 可以通过改成员获取标签信息
Index []int // 用于Type.FieldByIndex时的索引切片
PkgPath string
Offset uintptr
Anonymous bool // 是否匿名字段
}
四、ValueOf常用总结
Kind() Kind
Len() int 返回map、array、slice、chan类型的长度
IsValid() bool 返回是否持有一个值。如果v是Value零值会返回假
Interface() (i interface{}) 当前持有的值。注意返回的值,虽然是本身的类型,但在代码上下文中是不知道具体的类型,要使用需要进行类型转换
还有一些直接获取特定类型 Int() int64 , Float() float64 , Bool() bool , Bytes() []byte , String() string
Index(i int) Value 返回Array、Chan、Slice、String类型的第i个元素
Map集合相关操作
MapKeys() []Value 所有集合map的所有键的Value的切片
MapIndex(key Value) Value 返回key持有值为键对应的值的Value
结构体相关操作
NumField() int 返回结构体struct类型的成员的数量与TypeOf的方法一致
Field(i int) Value 返回结构体的第i个字段的值得Value
FieldByIndex(index []int) Value 返回索引序列指定的段的Value,参数为类型中的StructField.Index
FieldByName(name string) Value 返回类型名为name的字段的Value封装(会查找匿名字段及其子字段),如果未找到会返回Value零值。使用IsValid()进行判断是否找到
五、代码示例
将any(interface{})转为切片
func AnyToSlice(arr any) []any {
v := reflect.ValueOf(arr)
ptr := false
l := 0
if v.Kind() == reflect.Ptr {
if v.Elem().Kind() != reflect.Slice {
return nil
}
ptr = true
l = v.Elem().Len()
} else {
if v.Kind() != reflect.Slice {
return nil
}
l = v.Len()
}
ret := make([]interface{}, l)
for i := 0; i < l; i++ {
if ptr {
ret[i] = v.Elem().Index(i).Interface()
} else {
ret[i] = v.Index(i).Interface()
}
}
return ret
}
将struct转为map[string]any
func StructToMap(dest any, isJson bool) map[string]any {
t := reflect.TypeOf(dest)
if t.Kind() != reflect.Struct {
return nil
}
l := t.NumField()
var data = make(map[string]any)
v := reflect.ValueOf(dest)
for i := 0; i < l; i++ {
key := t.Field(i).Name
if isJson {
jsonKey := t.Field(i).Tag.Get("json")
if jsonKey != "" {
key = jsonKey
}
}
data[key] = v.Field(i).Interface()
}
return data
}
官方文档
type Type interface { // Kind返回该接口的具体分类 Kind() Kind // Name返回该类型在自身包内的类型名,如果是未命名类型会返回"" Name() string // PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64" // 如果类型为内建类型(string, error)或未命名类型(*T, struct{}, []int),会返回"" PkgPath() string // 返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64") // 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。 String() string // 返回要保存一个该类型的值需要多少字节;类似unsafe.Sizeof Size() uintptr // 返回当从内存中申请一个该类型值时,会对齐的字节数 Align() int // 返回当该类型作为结构体的字段时,会对齐的字节数 FieldAlign() int // 如果该类型实现了u代表的接口,会返回真 Implements(u Type) bool // 如果该类型的值可以直接赋值给u代表的类型,返回真 AssignableTo(u Type) bool // 如该类型的值可以转换为u代表的类型,返回真 ConvertibleTo(u Type) bool // 返回该类型的字位数。如果该类型的Kind不是Int、Uint、Float或Complex,会panic Bits() int // 返回array类型的长度,如非数组类型将panic Len() int // 返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map、Ptr或Slice,会panic Elem() Type // 返回map类型的键的类型。如非映射类型将panic Key() Type // 返回一个channel类型的方向,如非通道类型将会panic ChanDir() ChanDir // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic NumField() int // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic Field(i int) StructField // 返回索引序列指定的嵌套字段的类型, // 等价于用索引中每个值链式调用本方法,如非结构体将会panic FieldByIndex(index []int) StructField // 返回该类型名为name的字段(会查找匿名字段及其子字段), // 布尔值说明是否找到,如非结构体将panic FieldByName(name string) (StructField, bool) // 返回该类型第一个字段名满足函数match的字段,布尔值说明是否找到,如非结构体将会panic FieldByNameFunc(match func(string) bool) (StructField, bool) // 如果函数类型的最后一个输入参数是"..."形式的参数,IsVariadic返回真 // 如果这样,t.In(t.NumIn() - 1)返回参数的隐式的实际类型(声明类型的切片) // 如非函数类型将panic IsVariadic() bool // 返回func类型的参数个数,如果不是函数,将会panic NumIn() int // 返回func类型的第i个参数的类型,如非函数或者i不在[0, NumIn())内将会panic In(i int) Type // 返回func类型的返回值个数,如果不是函数,将会panic NumOut() int // 返回func类型的第i个返回值的类型,如非函数或者i不在[0, NumOut())内将会panic Out(i int) Type // 返回该类型的方法集中方法的数目 // 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法; // 匿名字段导致的歧义方法会滤除 NumMethod() int // 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态 // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil Method(int) Method // 根据方法名返回该类型方法集中的方法,使用一个布尔值说明是否发现该方法 // 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态 // 对接口类型,返回值的Type字段描述方法的签名,Func字段为nil MethodByName(string) (Method, bool) // 内含隐藏或非导出方法 }
type Value func ValueOf(i interface{}) Value func Zero(typ Type) Value func New(typ Type) Value func NewAt(typ Type, p unsafe.Pointer) Value func Indirect(v Value) Value func MakeSlice(typ Type, len, cap int) Value func MakeMap(typ Type) Value func MakeChan(typ Type, buffer int) Value func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value func Append(s Value, x ...Value) Value func AppendSlice(s, t Value) Value func (v Value) IsValid() bool func (v Value) IsNil() bool func (v Value) Kind() Kind func (v Value) Type() Type func (v Value) Convert(t Type) Value func (v Value) Elem() Value func (v Value) Bool() bool func (v Value) Int() int64 func (v Value) OverflowInt(x int64) bool func (v Value) Uint() uint64 func (v Value) OverflowUint(x uint64) bool func (v Value) Float() float64 func (v Value) OverflowFloat(x float64) bool func (v Value) Complex() complex128 func (v Value) OverflowComplex(x complex128) bool func (v Value) Bytes() []byte func (v Value) String() string func (v Value) Pointer() uintptr func (v Value) InterfaceData() [2]uintptr func (v Value) Slice(i, j int) Value func (v Value) Slice3(i, j, k int) Value func (v Value) Cap() int func (v Value) Len() int func (v Value) Index(i int) Value func (v Value) MapIndex(key Value) Value func (v Value) MapKeys() []Value func (v Value) NumField() int func (v Value) Field(i int) Value func (v Value) FieldByIndex(index []int) Value func (v Value) FieldByName(name string) Value func (v Value) FieldByNameFunc(match func(string) bool) Value func (v Value) Recv() (x Value, ok bool) func (v Value) TryRecv() (x Value, ok bool) func (v Value) Send(x Value) func (v Value) TrySend(x Value) bool func (v Value) Close() func (v Value) Call(in []Value) []Value func (v Value) CallSlice(in []Value) []Value func (v Value) NumMethod() int func (v Value) Method(i int) Value func (v Value) MethodByName(name string) Value func (v Value) CanAddr() bool func (v Value) Addr() Value func (v Value) UnsafeAddr() uintptr func (v Value) CanInterface() bool func (v Value) Interface() (i interface{}) func (v Value) CanSet() bool func (v Value) SetBool(x bool) func (v Value) SetInt(x int64) func (v Value) SetUint(x uint64) func (v Value) SetFloat(x float64) func (v Value) SetComplex(x complex128) func (v Value) SetBytes(x []byte) func (v Value) SetString(x string) func (v Value) SetPointer(x unsafe.Pointer) func (v Value) SetCap(n int) func (v Value) SetLen(n int) func (v Value) SetMapIndex(key, val Value) func (v Value) Set(x Value) func Copy(dst, src Value) int func DeepEqual(a1, a2 interface{}) bool
留言列表(0)
加载更多
留言
开源项目
- B5LaravelCMF:基于laravel9+bootstrap3实现的快速开发后台
- B5YiiCMF:基于Yii2+bootstrap3 实现的快速开发后台管理系统
- B5ThinkCmf:基于ThinkPHP6+bootstrap3 实现的快速开发后台管理系统
- B5GoCmf:gin + sqlx +bootstrap 实现后端管理系统
- See also:gitee.com@b5net
最新评论
wpstqe
:作者大大有没有建一个QQ群的计划?
流浪的PHPer
:感谢开源项目,快速开发非常的好用!
小白
:大佬您好 请问一下 http://b5laravelcmf.b5net.com/admin这个演示网址的全部代码有吗,gitee上不全呢,还能提供一下吗,感激不尽阿
tz
:大佬 B5YiiCMF 还开放吗
weifox
on GoLang常用的三方库
:还有 https://github.com/golang-module/carbon
php
:关于导出功能:1、B5thinkCMF部署后 参数的导出功能点击后就白屏了,不知道是哪里有问题?2、人员部门的导出功能没看懂怎么配置的? 只是启用exportshow=true吗
方便的话请答复下,谢谢!
初学者
:您好! 部署了您的B5ThinkCMF,请教下 使用新增功能如何实现二级联动呢 ?谢谢
11
:22
pcy
:前排围观
Louis
:冰舞的博客使用yii框架做的吧,B5ThinkCMF在本地部署后,登录系统的响应时间要比B5YiiCMF的登录时间长,还有一些Bug待修复
文章分类
标签