
go 语言没有 ruby 那样直接调用 obj.methods 的语法糖,但可通过 reflect 包在运行时获取任意类型的公开方法名列表,适用于调试、元编程等场景。
go 语言没有 ruby 那样直接调用 obj.methods 的语法糖,但可通过 reflect 包在运行时获取任意类型的公开方法名列表,适用于调试、元编程等场景。
在 Go 中,类型的方法集(method set)是编译期静态确定的,语言本身不提供类似 Ruby 的动态方法枚举接口。但标准库中的 reflect 包提供了运行时类型检查能力,允许我们遍历结构体、指针或接口值所承载类型的所有导出方法。
以下是一个典型示例,展示如何列出某个结构体类型的所有导出方法名:
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
}
func (u User) GetName() string { return u.Name }
func (u *User) SetName(name string) { u.Name = name }
func (u User) privateHelper() {} // 非导出方法,不会被反射列出
func main() {
t := reflect.TypeOf(User{}) // 获取类型对象(注意:传值而非指针,影响方法集)
fmt.Println("Methods on User (value receiver):")
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Printf("- %s (func %s)\n", m.Name, m.Type)
}
// 对比:使用指针类型可获取指针接收者方法(如 SetName)
tp := reflect.TypeOf(&User{})
fmt.Println("\nMethods on *User (pointer receiver):")
for i := 0; i < tp.NumMethod(); i++ {
m := tp.Method(i)
fmt.Printf("- %s (func %s)\n", m.Name, m.Type)
}
}输出结果:
Methods on User (value receiver): - GetName (func (main.User) string) Methods on *User (pointer receiver): - GetName (func (main.User) string) - SetName (func (*main.User) string)
⚠️ 注意事项:
- reflect.TypeOf(x) 获取的是 x 的静态类型,其 NumMethod() 和 Method(i) 仅返回该类型方法集中的导出方法(首字母大写),非导出方法(如 privateHelper)会被忽略;
- 方法是否可见取决于接收者类型:User{} 的方法集只包含值接收者方法;&User{} 的方法集包含值+指针接收者方法;
- 反射操作有运行时开销且破坏类型安全,不推荐用于常规业务逻辑——它更适合工具链(如序列化器、测试框架、RPC 服务)或调试辅助;
- 若目标是“检查某类型是否实现某接口”,应优先使用类型断言或编译期检查(如 _ = interface{}(x).(io.Reader)),而非反射枚举;
- 对于结构体字段访问,请使用 t.NumField() + t.Field(i),与方法枚举逻辑类似但语义不同。
总结:Go 的哲学强调显式性与编译期安全,因此“动态探查方法”并非第一选择。但在需要泛型抽象、自省式开发或构建基础设施时,reflect.TypeOf(x).Method(i) 是可靠、标准且跨平台的解决方案。

















