反射的性能测试

Golang提供了一个testing包,使得单元测试、性能测试尤为简单。只要新建一个以_test结尾的文件,然后使用命令go test就可以自动执行文件中的相应测试函数了(单元测试函数以Test开头,性能测试函数以Benchmark开头)。我们可以使用golang testing来做一下reflect的最简单的性能测试。

Type:Type类型用来表示一个go类型。

不是所有go类型的Type值都能使用所有方法。请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,应先使用Kind方法获知类型的分类。调用该分类不支持的方法会导致运行时的panic。

reflect.Type中方法:

  1. // 通用方法
  2. func (t *rtype) String() string // 获取 t 类型的字符串描述,不要通过 String 来判断两种类型是否一致。
  3. func (t *rtype) Name() string // 获取 t 类型在其包中定义的名称,未命名类型则返回空字符串。
  4. func (t *rtype) PkgPath() string // 获取 t 类型所在包的名称,未命名类型则返回空字符串。
  5. func (t *rtype) Kind() reflect.Kind // 获取 t 类型的类别。
  6. func (t *rtype) Size() uintptr // 获取 t 类型的值在分配内存时的大小,功能和 unsafe.SizeOf 一样。
  7. func (t *rtype) Align() int // 获取 t 类型的值在分配内存时的字节对齐值。
  8. func (t *rtype) FieldAlign() int // 获取 t 类型的值作为结构体字段时的字节对齐值。
  9. func (t *rtype) NumMethod() int // 获取 t 类型的方法数量。
  10. func (t *rtype) Method() reflect.Method // 根据索引获取 t 类型的方法,如果方法不存在,则 panic。
  11. // 如果 t 是一个实际的类型,则返回值的 Type 和 Func 字段会列出接收者。 如果 t 只是一个接口,则返回值的 Type 不列出接收者,Func 为空值。
  12. func (t *rtype) MethodByName(string) (reflect.Method, bool) // 根据名称获取 t 类型的方法。
  13. func (t *rtype) Implements(u reflect.Type) bool // 判断 t 类型是否实现了 u 接口。
  14. func (t *rtype) ConvertibleTo(u reflect.Type) bool // 判断 t 类型的值可否转换为 u 类型。
  15. func (t *rtype) AssignableTo(u reflect.Type) bool // 判断 t 类型的值可否赋值给 u 类型。
  16. func (t *rtype) Comparable() bool // 判断 t 类型的值可否进行比较操作
  17. // 注意对于:数组、切片、映射、通道、指针、接口
  18. func (t *rtype) Elem() reflect.Type // 获取元素类型、获取指针所指对象类型,获取接口的动态类型
  19. // 数值
  20. func (t *rtype) Bits() int // 获取数值类型的位宽,t 必须是整型、浮点型、复数型
  21. // 数组
  22. func (t *rtype) Len() int // 获取数组的元素个数
  23. // 映射
  24. func (t *rtype) Key() reflect.Type // 获取映射的键类型
  25. // 通道
  26. func (t *rtype) ChanDir() reflect.ChanDir // 获取通道的方向
  27. // 结构体
  28. func (t *rtype) NumField() int // 获取字段数量
  29. func (t *rtype) Field(int) reflect.StructField // 根据索引获取字段
  30. func (t *rtype) FieldByName(string) (reflect.StructField, bool) // 根据名称获取字段
  31. func (t *rtype) FieldByNameFunc(match func(string) bool) (reflect.StructField, bool) // 根据指定的匹配函数 math 获取字段
  32. func (t *rtype) FieldByIndex(index []int) reflect.StructField // 根据索引链获取嵌套字段
  33. // 函数
  34. func (t *rtype) NumIn() int // 获取函数的参数数量
  35. func (t *rtype) In(int) reflect.Type // 根据索引获取函数的参数信息
  36. func (t *rtype) NumOut() int // 获取函数的返回值数量
  37. func (t *rtype) Out(int) reflect.Type // 根据索引获取函数的返回值信息
  38. func (t *rtype) IsVariadic() bool // 判断函数是否具有可变参数。
  39. // 如果有可变参数,则 t.In(t.NumIn()-1) 将返回一个切片。

reflect.Value方法:

reflect.Value.Kind():获取变量类别,返回常量.

用于获取值方法:

  1. func (v Value) Int() int64 // 获取int类型值,如果 v 值不是有符号整型,则 panic。
  2. func (v Value) Uint() uint64 // 获取unit类型的值,如果 v 值不是无符号整型(包括 uintptr),则 panic。
  3. func (v Value) Float() float64 // 获取float类型的值,如果 v 值不是浮点型,则 panic。
  4. func (v Value) Complex() complex128 // 获取复数类型的值,如果 v 值不是复数型,则 panic。
  5. func (v Value) Bool() bool // 获取布尔类型的值,如果 v 值不是布尔型,则 panic。
  6. func (v Value) Len() int // 获取 v 值的长度,v 值必须是字符串、数组、切片、映射、通道。
  7. func (v Value) Cap() int // 获取 v 值的容量,v 值必须是数值、切片、通道。
  8. func (v Value) Index(i int) reflect.Value // 获取 v 值的第 i 个元素,v 值必须是字符串、数组、切片,i 不能超出范围。
  9. func (v Value) Bytes() []byte // 获取字节类型的值,如果 v 值不是字节切片,则 panic。
  10. func (v Value) Slice(i, j int) reflect.Value // 获取 v 值的切片,切片长度 = j - i,切片容量 = v.Cap() - i。
  11. // v 必须是字符串、数值、切片,如果是数组则必须可寻址。i 不能超出范围。
  12. func (v Value) Slice3(i, j, k int) reflect.Value // 获取 v 值的切片,切片长度 = j - i,切片容量 = k - i。
  13. // i、j、k 不能超出 v 的容量。i <= j <= k。
  14. // v 必须是字符串、数值、切片,如果是数组则必须可寻址。i 不能超出范围。
  15. func (v Value) MapIndex(key Value) reflect.Value // 根据 key 键获取 v 值的内容,v 值必须是映射。
  16. // 如果指定的元素不存在,或 v 值是未初始化的映射,则返回零值(reflect.ValueOf(nil))
  17. func (v Value) MapKeys() []reflect.Value // 获取 v 值的所有键的无序列表,v 值必须是映射。
  18. // 如果 v 值是未初始化的映射,则返回空列表。
  19. func (v Value) OverflowInt(x int64) bool // 判断 x 是否超出 v 值的取值范围,v 值必须是有符号整型。
  20. func (v Value) OverflowUint(x uint64) bool // 判断 x 是否超出 v 值的取值范围,v 值必须是无符号整型。
  21. func (v Value) OverflowFloat(x float64) bool // 判断 x 是否超出 v 值的取值范围,v 值必须是浮点型。
  22. func (v Value) OverflowComplex(x complex128) bool // 判断 x 是否超出 v 值的取值范围,v 值必须是复数型。

设置值方法:

  1. func (v Value) SetInt(x int64) //设置int类型的值
  2. func (v Value) SetUint(x uint64) // 设置无符号整型的值
  3. func (v Value) SetFloat(x float64) // 设置浮点类型的值
  4. func (v Value) SetComplex(x complex128) //设置复数类型的值
  5. func (v Value) SetBool(x bool) //设置布尔类型的值
  6. func (v Value) SetString(x string) //设置字符串类型的值
  7. func (v Value) SetLen(n int) // 设置切片的长度,n 不能超出范围,不能为负数。
  8. func (v Value) SetCap(n int) //设置切片的容量
  9. func (v Value) SetBytes(x []byte) //设置字节类型的值
  10. func (v Value) SetMapIndex(key, val reflect.Value) //设置map的key和value,前提必须是初始化以后,存在覆盖、不存在添加

其他的方法:

  1. // 结构体相关:
  2. func (v Value) NumField() int // 获取结构体字段(成员)数量
  3. func (v Value) Field(i int) reflect.Value //根据索引获取结构体字段
  4. func (v Value) FieldByIndex(index []int) reflect.Value // 根据索引链获取结构体嵌套字段
  5. func (v Value) FieldByName(string) reflect.Value // 根据名称获取结构体的字段,不存在返回reflect.ValueOf(nil)
  6. func (v Value) FieldByNameFunc(match func(string) bool) Value // 根据匹配函数 match 获取字段,如果没有匹配的字段,则返回零值(reflect.ValueOf(nil))
  7. // 通道相关:
  8. func (v Value) Send(x reflect.Value)// 发送数据(会阻塞),v 值必须是可写通道。
  9. func (v Value) Recv() (x reflect.Value, ok bool) // 接收数据(会阻塞),v 值必须是可读通道。
  10. func (v Value) TrySend(x reflect.Value) bool // 尝试发送数据(不会阻塞),v 值必须是可写通道。
  11. func (v Value) TryRecv() (x reflect.Value, ok bool) // 尝试接收数据(不会阻塞),v 值必须是可读通道。
  12. func (v Value) Close() // 关闭通道
  13. // 函数相关
  14. func (v Value) Call(in []Value) (r []Value) // 通过参数列表 in 调用 v 值所代表的函数(或方法)。函数的返回值存入 r 中返回。
  15. // 要传入多少参数就在 in 中存入多少元素。
  16. // Call 即可以调用定参函数(参数数量固定),也可以调用变参函数(参数数量可变)。
  17. func (v Value) CallSlice(in []Value) []Value // 调用变参函数