go-源码研读-reflect
背景介绍
Go中的反射使用的就是官方提供的reflect这个包
使用方法
类型reflect.Type
主要是使用reflect.Typeof()获取到变量的类型信息(reflect.Type),再通过里面一些方法拿到想要的属性
1 | //a/a.go |
reflect.Type的方法很多,但是可不可以使用取决于变量本身的类型,比如Len()方法string是使用不了的,这里整理了一个表格供大家参考
示例代码位于:
| 类型 | 可用方法列表 | 用途 | |
|---|---|---|---|
| 通用 | String | 全名称:[包名.]类型名 | |
| Kind | 类型 | ||
| Name | 类型名 可能为空 | ||
| PkgPath | 包名 包名可能为空 | ||
| Comparable | 是否可以比较 | ||
| Size | 占用字节 | ||
| Align | 对齐字节 | ||
| Struct | FieldAlign | 字段内存对齐字节 | |
| NumField | 字段数 | ||
| Field | 根据索引获取字段 | ||
| FieldByName | 根据名称获取字段 | ||
| NumMethod | 导出的方法数 | ||
| Method | 根据索引获取方法,只能访问导出的方法(大写的) | ||
| MethodByName | 根据名称获取方法,只能访问导出的方法(大写的) | ||
| FieldByIndex | 当struct是嵌套的,这个方法可以找到内嵌的字段,第0个字段的第0个字段 | ||
| FieldByNameFunc | 根据所给的方法查找,如果多个匹配返回第一个匹配的 | ||
| Func | NumIn | 入参个数 | |
| NumOut | 返回值个数 | ||
| In | 获取入参索引位置的类型 | ||
| Out | 获取返回值索引位置的类型 | ||
| IsVariadic | 是否有可变参数 比如… float64 | ||
| Channel | ChanDir | channel方向 | |
| Array | Len | 长度 | |
| Slice | 无 | ||
| Map | Key | key的类型 | |
| Array,Slice,Channel,Map,Pinter | Elem | 内部元素的类型 | |
| 数字类型 | Bits | 占用bit数 |
还有几个特殊方法
AssignableTo(v interface{})
判断能不能把v赋值给自己
ConvertibleTo(v interface{})
判断能不能和v进行比较
Implements(v interface{})
v只能传接口,判断有没有实现这个接口,使用起来会比较复杂,下面给出示例
1 | package main |
值reflect.Value
上文所有的操作都是和类型相关的,那么如何对实际的值进行操作呢?
首先得明确一点,那就是Go的参数传递都是值传递的,所以想要修改本身,得传递自身的指针.
1 | func main() { |
这里可以看到,v本身是不能修改的,而v.Elem()v的元素是可以修改的,这是什么意思呢?其实就是 指针的指向是不能修改的,但是指针指向的值可以修改的。
同样,下面整理了一份表格以供查阅
示例代码位于:
原理剖析
进阶理解
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SHIELD!
评论