reflect.Value.Methods()返回导出方法的reflect.Method切片,不包含接收者信息;调用前需确保Value可寻址、有效且CanCall为true,并严格匹配接收者类型与参数类型。

用 reflect.Value.Methods() 获取导出方法列表
Go 的反射只能访问导出(首字母大写)的方法,reflect.Value.Methods() 返回的是所有导出方法的 reflect.Method 切片,不是函数值本身。它不包含接收者类型信息,也不区分指针/值接收者——只反映方法签名在类型定义中的导出状态。
- 必须传入
reflect.Value(不能是reflect.Type),且该值需为结构体、指针或接口类型 - 若传入非导出结构体实例(如
struct{ x int }),Methods()返回空切片,哪怕它有方法 - 想获取全部方法(含未导出),得用
reflect.TypeOf(t).Method(i)遍历NumMethod(),但返回的reflect.Method.Func仍是不可调用的零值
调用方法前必须确保接收者可寻址且可设置
反射调用方法本质是调用 reflect.Value.Call(),但前提是该 Value 是可寻址的(CanAddr() 为 true),且若方法是**指针接收者**,你传入的必须是地址——否则会 panic:call of reflect.Value.Call on zero Value 或 panic: reflect: Call using zero Value argument。
- 对值类型变量:用
reflect.ValueOf(&v).Elem()获得可寻址的副本;直接reflect.ValueOf(v)只能调用值接收者方法 - 对已是指针的变量:用
reflect.ValueOf(ptr).Elem()得到其指向的值,再调用MethodByName() - 调用前务必检查
IsValid()和CanCall(),尤其在动态查找方法名时,避免MethodByName()返回零值后直接Call()
MethodByName() 查不到方法?先确认接收者类型和大小写
常见失败不是反射写错了,而是方法根本没被识别:Go 方法名必须导出(大写开头),且调用时的接收者类型必须与方法定义完全匹配——比如方法定义在 *MyStruct 上,你就不能用 reflect.ValueOf(MyStruct{}) 去查。
- 错误示例:
type T struct{}; func (t T) Foo() {}→ 只能用reflect.ValueOf(T{})查到Foo;若用reflect.ValueOf(&T{}),则查不到(因为方法不在*T上) - 正确配对:
func (t *T) Bar()→ 必须用reflect.ValueOf(&T{}).Elem()或reflect.ValueOf(new(T)).Elem() - 方法名拼写、大小写、是否带包名前缀(如
pkg.T.Foo)不影响MethodByName("Foo"),它只认本地方法名
参数传递必须严格匹配类型,interface{} 不自动解包
调用 Call([]reflect.Value) 时,每个参数都必须是 reflect.Value,且类型要和方法签名完全一致。传 int 却给 int64,或传 string 却期望 *string,都会 panic:reflect: Call using xxx as type yyy。
立即学习“go语言免费学习笔记(深入)”;
- 基本类型转换:用
reflect.ValueOf(x).Convert(reflect.TypeOf(y).Type)(仅当底层类型兼容) - 指针参数:必须传
reflect.ValueOf(&x).Elem(),而不是reflect.ValueOf(x) - 切片/映射/通道等引用类型,直接
reflect.ValueOf(s)即可,无需额外取地址 - 空接口
interface{}参数无法靠反射自动“展开”,必须显式构造对应类型的reflect.Value
fmt.Printf("%v %v %v\n", v.Kind(), v.CanAddr(), v.CanInterface()),比反复改 Call() 参数更快定位问题。










