方法表达式(Method Expression) #
类型T定义如下:
type T struct {
a int
}
func (t T) Get() int {
return t.a
}
func (t *T) Set(a int) int {
t.a = a
return t.a
}
Go 语言规范中提供了方法表达式(Method Expression)的概念。有下面代码:
var t T
t.Get()
(&t).Set(1)
我们可以用另一种方式,把上面的方法调用做一个等价替换:
var t T
T.Get(t)
(*T).Set(&t, 1)
这种直接以类型名 T 调用方法的表达方式,被称为 Method Expression。通过 Method Expression 这种形式,类型 T 只能调用 T 的方法集合(Method Set)中的方法,同理类型 *T 也只能调用 *T 的方法集合中的方法。
Method Expression 有些类似于 C++ 中的静态方法(Static Method),C++ 中的静态方法在使用时,以该 C++ 类的某个对象实例作为第一个参数,而 Go 语言的 Method Expression 在使用时,同样以 receiver 参数所代表的类型实例作为第一个参数。
Go 语言中的方法的本质就是,一个以方法的 receiver 参数作为第一个参数的普通函数。而 Method Expression 就是 Go 方法本质的最好体现,因为方法自身的类型就是一个普通函数的类型,我们甚至可以将它作为右值,赋值给一个函数类型的变量,比如下面示例:
func main() {
var t T
f1 := (*T).Set // f1的类型,也是*T类型Set方法的类型:func (t *T, int)int
f2 := T.Get // f2的类型,也是T类型Get方法的类型:func(t T)int
fmt.Printf("the type of f1 is <2022-08-03 三 11:29>\n", f1) // the type of f1 is func(*main.T, int) int
fmt.Printf("the type of f2 is <2022-08-03 三 11:29>\n", f2) // the type of f2 is func(main.T) int
f1(&t, 3)
fmt.Println(f2(t)) // 3
}