1. 介绍

文档地址:https://pkg.go.dev/reflect

Go 标准库 reflect 用于运行时的映射,使程序运行时可以检查和操纵任意类型的对象。例如,在运行时获取一个任意类型 interface{} 的对象,并获取它的动态类型。

获取对象的类型并使用不同的取值方法:

for _, v := range []any{"hi", 42, func() {}} {
	switch v := reflect.ValueOf(v); v.Kind() {
	case reflect.String:
		fmt.Println(v.String())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		fmt.Println(v.Int())
	default:
		fmt.Printf("unhandled kind %s", v.Kind())
	}
}

获取变量的类型:

var x int
typ := reflect.TypeOf(x)
fmt.Println(typ)

根据函数名调用对应函数:

func add(a int, b int) int {
	return a + b
}
var FuncMap = map[string]interface{}{
	"add":   add,
}

funcName := "add"
f := reflect.ValueOf(FuncMap[funcName])
args := []reflect.Value{
	reflect.ValueOf(1),
	reflect.ValueOf(2),
}
ret := f.Call(args)
i := ret[0].Int()

根据方法名调用对应方法,需要注意方法需要是可导出方法才能被反射调用:

type People struct {
	name string
}
func (p *People) SetName(s string) {
	p.name = s
}
func (p *People) GetName() string {
	return p.name
}

p := People{}
setFunc := reflect.ValueOf(&p).MethodByName("SetName")
args := []reflect.Value{reflect.ValueOf("moondo")}
setFunc.Call(args)
getFunc := reflect.ValueOf(&p).MethodByName("GetName")
name := getFunc.Call([]reflect.Value{})[0].String()

获取结构体成员的标签:

type S struct {
	F string `species:"gopher" color:"blue"`
}

s := S{}
st := reflect.TypeOf(s)
field := st.Field(0)
fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))

2. 常量

const Ptr = Pointer

3. 类型

3.1 Kind

类型定义:

// Kind 类型
type Kind uint
const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Pointer
	Slice
	String
	Struct
	UnsafePointer
)

方法:

// String 返回类型名称
func (k Kind) String() string

3.2 Type

类型定义:

// Type 类型的接口
type Type interface {

	// Align returns the alignment in bytes of a value of
	// this type when allocated in memory.
	Align() int

	// FieldAlign returns the alignment in bytes of a value of
	// this type when used as a field in a struct.
	FieldAlign() int

	// Method returns the i'th method in the type's method set.
	// Methods are sorted in lexicographic order.
	Method(int) Method

	// MethodByName returns the method with that name in the type's
	// method set and a boolean indicating if the method was found.
	MethodByName(string) (Method, bool)

	// NumMethod returns the number of methods accessible using Method.
	NumMethod() int

	// Name returns the type's name within its package for a defined type.
	Name() string

	// PkgPath returns a defined type's package path.
	PkgPath() string

	// Size returns the number of bytes needed to store a value of the given type.
	Size() uintptr

	// String returns a string representation of the type.
	String() string

	// Kind returns the specific kind of this type.
	Kind() Kind

	// Implements reports whether the type implements the interface type u.
	Implements(u Type) bool

	// AssignableTo reports whether a value of the type is assignable to type u.
	AssignableTo(u Type) bool

	// ConvertibleTo reports whether a value of the type is convertible to type u.
	ConvertibleTo(u Type) bool

	// Comparable reports whether values of this type are comparable.
	Comparable() bool

	// Bits returns the size of the type in bits.
	Bits() int

	// ChanDir returns a channel type's direction.
	ChanDir() ChanDir

	// IsVariadic reports whether a function type's final input parameter
	// is a "..." parameter. If so, t.In(t.NumIn() - 1) returns the parameter's
	// implicit actual type []T.
	IsVariadic() bool

	// Elem returns a type's element type.
	Elem() Type

	// Field returns a struct type's i'th field.
	Field(i int) StructField

	// FieldByIndex returns the nested field corresponding to the index sequence.
	FieldByIndex(index []int) StructField

	// FieldByName returns the struct field with the given name
	// and a boolean indicating if the field was found.
	FieldByName(name string) (StructField, bool)

	// FieldByNameFunc returns the struct field with a name
	// that satisfies the match function and a boolean indicating if
	// the field was found.
	FieldByNameFunc(match func(string) bool) (StructField, bool)

	// In returns the type of a function type's i'th input parameter.
	In(i int) Type

	// Key returns a map type's key type.
	Key() Type

	// Len returns an array type's length.
	Len() int

	// NumField returns a struct type's field count.
	NumField() int

	// NumIn returns a function type's input parameter count.
	NumIn() int

	// NumOut returns a function type's output parameter count.
	NumOut() int

	// Out returns the type of a function type's i'th output parameter.
	Out(i int) Type
}

方法:

// TypeOf 获取变量的类型
func TypeOf(i any) Type

// ArrayOf 给定长度和元素类型的数组的类型
func ArrayOf(length int, elem Type) Type

// ChanOf 给定方向和元素类型的通道的类型
func ChanOf(dir ChanDir, t Type) Type

// FuncOf 给定参数和返回类型的函数的类型
func FuncOf(in, out []Type, variadic bool) Type

// MapOf 给定key和元素类型的map的类型
func MapOf(key, elem Type) Type

// PointerTo 给定类型的指针的类型
func PointerTo(t Type) Type

// PtrTo 给定类型的指针的类型,等同PointerTo
func PtrTo(t Type) Type

// SliceOf 给定类型元素的slice的类型
func SliceOf(t Type) Type

// StructOf 给定成员类型的结构体的类型
func StructOf(fields []StructField) Type

3.3 Value

类型定义:

// Value 变量
type Value struct {
	// contains filtered or unexported fields
}

方法:

// Append 将多个变量x追加到slice s
func Append(s Value, x ...Value) Value

// AppendSlice 将slice t追加到slice s
func AppendSlice(s, t Value) Value

// Indirect 返回指针v指向的变量
func Indirect(v Value) Value

// MakeChan 创建不同的类型
func MakeChan(typ Type, buffer int) Value
func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value
func MakeMap(typ Type) Value
func MakeMapWithSize(typ Type, n int) Value
func MakeSlice(typ Type, len, cap int) Value

// New 创建指定类型的空指针
func New(typ Type) Value

// NewAt 创建指针并指向p
func NewAt(typ Type, p unsafe.Pointer) Value

// ValueOf 创建变量并用i初始化
func ValueOf(i any) Value

// Zero 创建指定类型变量并赋空值
func Zero(typ Type) Value

// Call 本身是一个函数,调用自己,传入in作为参数列表
func (v Value) Call(in []Value) []Value

// 还包括类型Value的许多方法,如判断能否转化为各种类型、设置各种类型的值、转为各种类型的值等

3.4 Method

类型定义:

// Method 方法
type Method struct {
	Name string    // method name
	PkgPath string // 对非导出的方法是包路径,对可导出的方法为空
	Type  Type     // method type
	Func  Value    // func with receiver as first argument
	Index int      // index for Type.Method
}

方法:

// IsExported 是否可导出(首字母大写)
func (m Method) IsExported() bool

3.5 StructField

类型定义:

// StructField 结构体的某个成员
type StructField struct {
	Name string         // field name
	PkgPath string      // 对非导出的成员是包路径,对可导出的成员为空
	Type      Type      // field type
	Tag       StructTag // field tag string
	Offset    uintptr   // offset within struct, in bytes
	Index     []int     // index sequence for Type.FieldByIndex
	Anonymous bool      // is an embedded field
}

方法:

// VisibleFields 返回可见的成员列表
func VisibleFields(t Type) []StructField

// IsExported 是否可导出(首字母大写)
func (f StructField) IsExported() bool

3.6 StructTag

类型定义:

// StructTag 结构体成员的标签
type StructTag string

方法:

// Get 获取标签对应key的值,key不存在返回空字符串
func (tag StructTag) Get(key string) string

// Lookup 获取标签对应key的值以及key是否存在
func (tag StructTag) Lookup(key string) (value string, ok bool)

3.7 MapIter

类型定义:

// MapIter map遍历的迭代器
type MapIter struct {
	// contains filtered or unexported fields
}

方法:

// Key 返回迭代器当前位置的key
func (iter *MapIter) Key() Value

// Value 返回迭代器当前位置的value
func (iter *MapIter) Value() Value

// Next 迭代器指向下一个元素,返回false表示遍历到尽头了
func (iter *MapIter) Next() bool

// Reset 将迭代器指向另一个map
func (iter *MapIter) Reset(v Value)

3.8 其他类型

类型定义:

// ChanDir 通道类型的方向
type ChanDir int
const (
	RecvDir ChanDir             = 1 << iota // <-chan
	SendDir                                 // chan<-
	BothDir = RecvDir | SendDir             // chan
)

// SelectCase select语句中的某个case
type SelectCase struct {
	Dir  SelectDir // direction of case
	Chan Value     // channel to use (for send or receive)
	Send Value     // value to send (for send)
}

// SelectDir 一个SelectCase的通信方向
type SelectDir int
const (
	SelectSend    SelectDir // case Chan <- Send
	SelectRecv              // case <-Chan:
	SelectDefault           // default
)

// SliceHeader 运行时的slice
type SliceHeader struct {
	Data uintptr
	Len  int
	Cap  int
}

// StringHeader 运行时的string
type StringHeader struct {
	Data uintptr
	Len  int
}

4. 函数

// Copy 变量复制,两个参数必须是同样元素类型的slice或数组,返回复制的元素个数
func Copy(dst, src Value) int

// DeepEqual 比较参数是否深度相等,对于函数同样是nil才是深度相等
func DeepEqual(x, y any) bool

// Swapper 返回一个函数,执行这个函数将调换现在的参数slice中的对应索引的元素
func Swapper(slice any) func(i, j int)