跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Golang反射如何获取结构体的所有方法_Golang通过反射获取结构体方法与调用

只有导出方法才能被reflect获取,非导出方法在reflect.Type中根本不存在;值类型反射仅见值接收者方法,指针类型可见全部导出方法;MethodByName查不到返回零值,调用前须确保接收者匹配且参数类型数量严格一致。 用
reflect.TypeOf
获取结构体类型再调用
NumMethod
和
Method
Go 的反射中,只有导出(首字母大写)方法才能被
reflect
获取到。非导出方法在
reflect.Type
中完全不可见,不是“获取不到”,而是根本不存在于方法集里。 正确路径是:先用
reflect.TypeOf
拿到类型对象(注意传指针或值本身会影响方法集——接口实现和接收者类型有关),再遍历方法:
type User struct{ Name string } func (u User) GetName() string { return u.Name } func (u *User) SetName(n string) { u.Name = n } u := User{} t := reflect.TypeOf(u) // 值类型,只能看到值接收者方法 fmt.Println(t.NumMethod()) // 输出 1(只有 GetName) t2 := reflect.TypeOf(&u) // 指针类型,能看到值+指针接收者方法 fmt.Println(t2.NumMethod()) // 输出 2(GetName + SetName)
区分
Method
和
MethodByName
:一个遍历,一个查单个
Method(i)
按索引取方法,返回
reflect.Method
,含名称、类型、函数值;
MethodByName(name)
直接查,查不到返回零值(
reflect.Value{}
),不报错。 遍历所有方法时用
Method(i)
,配合
NumMethod()
明确知道方法名且只调一个,用
MethodByName
更简洁 注意:方法名必须完全匹配,大小写敏感,且必须导出
MethodByName
返回的是
reflect.Value
,不是
reflect.Method
,不能直接读元信息(如参数列表),要读得用
Method
配合
Type().In(i)
调用前必须检查接收者类型是否匹配 反射调用方法本质是调用函数值,但 Go 对接收者有严格约束:值接收者方法不能在指针实例上调用(除非自动取地址),指针接收者方法不能在纯值上直接调(会 panic)。 立即学习 “ go语言免费学习笔记(深入) ”; 常见 panic:
reflect: Call using zero Value argument
或
reflect: Call of method on zero Value
,多数是因为
reflect.Value
是零值,或接收者不匹配。 用
reflect.ValueOf(x)
获取实例时,确保
x
非 nil(尤其指针) 调用指针接收者方法,必须传
reflect.ValueOf(&x)
,而不是
reflect.ValueOf(x)
调用前可用
v.CanAddr()
和
v.Kind() == reflect.Ptr
判断是否可安全取地址 稳妥做法:统一用指针传入,再用
v.Elem()
处理值接收者(如果需要) 实际调用要处理参数和返回值的
reflect.Value
转换 反射调用不是直接传 Go 原生参数,所有参数都得是
reflect.Value
切片,返回值也是
reflect.Value
切片。没转换好就会 panic 或静默失败。 参数必须数量、类型完全匹配方法签名,不能自动转换(比如
int
不能当
int64
) 用
reflect.ValueOf(arg).Convert(targetType)
强转前,先确认
arg
类型是否可转换(
CanConvert
) 返回值切片长度取决于方法声明的返回值个数,哪怕返回
error
也要显式接收 若方法返回多值,别漏掉
rets[0].Interface()
之后的
rets[1].Interface()
最易忽略的一点:结构体字段未导出时,其所在方法即使导出,也可能因内部访问字段而运行时报错(比如方法里读了私有字段但调用方无权访问),这不是反射问题,是 Go 的可见性规则在运行时生效。

相关文章