go语言的Reflect包

反射

反射是指程序运行时能够"观察"并"操作"自身结构的能力。

可以获取任意变量的 类型信息Type

获取或设置任意变量的值Value

调用方法、遍历结构体字段等

核心概念 reflect.Type 和 reflect.Value

reflect.Type

是一个接口,表示了任意类型的完整类型信息

基本信息

方法 返回值 说明
.Name() string 类型在代码中的名字(如 Person),匿名类型返回空字符串
.PkgPath() string 类型所在包的路径(仅对具名类型有效)
.String() string 类型的完整字符串表示(如 main.Person[]int
.Kind() reflect.Kind 底层基本种类(如 Struct, Int, Slice 等)

type MyInt int -> Name()="MyInt",Kind()=Int,PkgPath()="main"

方法 返回值 说明
.AssignableTo(u Type) bool 当前类型是否可赋值给类型 u
.ConvertibleTo(u Type) bool 是否可通过类型转换转为 u
.Implements(u Type) bool 是否实现了接口 uu 必须是接口类型)
.Comparable() bool 类型是否支持 ==!= 比较
.Size() uintptr 类型在内存中占用的字节数(类似 unsafe.Sizeof
.Align() int 该类型在结构体中的对齐字节数
.FieldAlign() int 作为结构体字段时的对齐字节数

Kind == Ptr()指针:.Elem()指针指向的类型

Array/Slice:.Elem()元素类型,.Len()数组长度

Map:.Key()键类型,.Elem值类型

Chan通道:.ChanDir()通道方向.Elem()通道元素类型

Func函数:.NumIn()/.NumOut()入参出参个数。.In(i)/.Out(i)第i个输入输出参数类型。.IsVariadic()是否变参。

Struct结构体:.NumField()字段数量,.Field(i)第i个字段,.FieldByName(name),.FieldByIndex(index)按嵌套索引访问字段。

reflect.Value

是一个结构体,封装了任意变量的值。

通过reflecy.ValueOf(x)获取,通过.Interface()方法还原。

方法 说明
.Kind() 返回底层种类(如 Int, String, Struct
.Type() 返回对应的 reflect.Type
.IsValid() 判断值是否有效(零值 Value{} 无效)
.IsZero() 判断是否为类型的零值(Go 1.13+)

▶ 结构体(Struct)

  • .NumField() / .Field(i) → 字段数量和字段值(Value

  • .FieldByName(name) → 按名称获取字段

  • .FieldByIndex([]int) → 支持嵌套字段访问

▶ 切片/数组(Slice/Array)

  • .Len() / .Cap() → 长度和容量

  • .Index(i) → 获取第 i 个元素(返回 Value

  • .SetIndex(i, value) → 设置元素(需可寻址)

▶ 映射(Map)

  • .MapKeys() → 所有 key 的 []Value

  • .MapIndex(key) → 获取值

  • .SetMapIndex(key, val) → 设置或删除(val 为零值则删除)

▶ 指针(Ptr)

  • .Elem() → 解引用,获取指向的值

▶ 函数/方法(Func)

  • .Call(args []Value) → 调用函数

  • .CallSlice(args []Value) → 调用带 ... 参数的函数

例子

获取值

Go 复制代码
v := reflect.ValueOf(100)
fmt.Println(v.Int())  // 输出: 100

设置值(必须为指针,Value可寻址)

Go 复制代码
x := 10
v := reflect.ValueOf(&x).Elem()
if v.CanSet() {
    v.SetInt(200)
}
fmt.Println(x) // 输出: 200

结构体字段和方法操作

Go 复制代码
type User struct {
    Name string
    Age  int
}

u := User{"Alice", 30}
v := reflect.ValueOf(u)
t := reflect.TypeOf(u)

for i := 0; i < v.NumField(); i++ {
    fmt.Printf("Field %s = %v\n", t.Field(i).Name, v.Field(i))
}

动态设置结构体字段

Go 复制代码
u := User{"Bob", 25}
v := reflect.ValueOf(&u).Elem()
v.FieldByName("Name").SetString("Charlie")

fmt.Println(u.Name) // 输出: Charlie

调用结构体方法

Go 复制代码
type Person struct{}

func (p Person) Say(name string) {
    fmt.Println("Hello,", name)
}

p := Person{}
v := reflect.ValueOf(p)
m := v.MethodByName("Say")
args := []reflect.Value{reflect.ValueOf("Go")}
m.Call(args) // 输出: Hello, Go
相关推荐
lolo大魔王1 小时前
Go语言的函数与指针的定义
开发语言·后端·golang
liuyao_xianhui2 小时前
map和set_C++
java·开发语言·数据结构·c++·算法·宽度优先
香蕉鼠片2 小时前
八股C++
开发语言·c++
AI视觉网奇2 小时前
python 截取矩形 缩放,旋转
开发语言·python·numpy
清心歌2 小时前
ArrayList 深入解析
java
Yyyyy123jsjs2 小时前
轻松通过Python调用外汇api获取汇率数据
开发语言·python
墨^O^2 小时前
C++ Memory Order 完全指南:从 relaxed 到 seq_cst,深入理解无锁编程与 happens-before
linux·开发语言·c++·笔记·学习·算法·缓存
算.子2 小时前
【Spring AI 实战】五、RAG 核心原理:为什么需要检索增强生成?
java·人工智能·spring