Method Expression 的类型签名永远包含接收者,如 func(*T, int) 而非 func(int),T.Method 是编译期静态绑定的函数值,不经过接口查找,不能直接赋给无接收者的函数类型,需用 t.Method 或显式传参。

Method Expression 的类型签名永远带接收者
写 T.Method 不是在“调用方法”,而是在取一个函数值,它的类型必然包含接收者类型。比如 func(*T, int) 或 func(T, string),绝不会是 func(int)。
常见错误现象:sort.Slice(items, T.Less) 编译失败,报错类似 cannot use T.Less (type func(*T, int, int) bool) as type func(int, int) bool——因为 sort.Slice 要的是无接收者的比较函数,而你传的是带 *T 的完整签名。
- 用
reflect.TypeOf(T.Method)直接看类型,别猜 - 若方法定义为
func(t *T) Less(i, j int) bool,则T.Less类型就是func(*T, int, int) bool - 想传给需要
func(int, int) bool的地方,必须用t.Less(方法值),而不是T.Less
Method Expression 是静态绑定的纯函数,不依赖运行时类型
T.Method 在编译期就确定了具体实现,它不经过接口动态查找,也不触发任何运行时类型检查。只要 T 实现了该方法,T.Method 就能用,哪怕 T 是空结构体或未导出类型。
使用场景有限但关键:泛型约束中无法写 t.Method(因为 t 类型不确定),但可以写 T.Method 配合显式传参;反射调用前需先获取方法地址,也得靠 T.Method。
立即学习“go语言免费学习笔记(深入)”;
- 它不是闭包,不捕获任何上下文,只是把接收者“拉平”成第一个参数
- 值接收者版本的
T.Method会拷贝整个T实例,指针接收者版本才真正操作原数据 - 不能用于替代接口实现:它不满足接口类型,也不能被赋值给接口变量
混用 Method Value 和 Method Expression 导致编译失败
二者类型完全不同,Go 不做隐式转换。这不是运行时 panic,而是编译器直接拒收。错误信息通常直白:“mismatched types”,甚至会列出两个函数签名让你对比。
容易踩的坑:看到某个库函数接受 func(...) 类型,下意识把 T.Method 往里塞,结果编译不过。其实你要的是 t.Method,或者得手动补上接收者参数。
-
t.Method类型是func(其余参数),接收者已固化 -
T.Method类型是func(接收者, 其余参数),接收者必须显式传 - 同一个方法,
t.Method和T.Method的类型永远不同,哪怕接收者是*T
学习 Method Expression 的关键不是记语法,而是理解“接收者即参数”
Go 把方法看作“带隐式首参的函数”,T.Method 只是把这个隐式参数显式化。所以它本质上和普通函数没区别,只是命名空间挂在类型上。
初学者常卡在“为什么不能直接传 T.Method 给回调函数”,根本原因是没意识到:你写的不是“方法名”,而是一个函数类型声明——它多了一个参数。
- 把
T.Method当作func(T, ...)来思考,立刻明白调用时要多传一个t或&t - 调试时优先打印
reflect.TypeOf结果,比翻文档快得多 - 值接收者的方法表达式修改不了原值,这是设计使然,不是 bug


















