方法的一些注意事项
1. 方法的 receiver type 并非一定要是 struct 类型,type 定义的类型别名、slice、map、channel、func 类型等都可以。但内置简单数据类型 (int、float 等) 不行,interface 类型不行。
package main
import "fmt"
type myint int
func (i *myint) numadd(n int) int {
return n + 1
}
func main() {
n := new(myint)
fmt.Println(n.numadd(4))
}
以 slice 为类型,定义属于它的方法:
package main
import "fmt"
type myslice []int
func (v myslice) sumOfSlice() int {
sum := 0
for _, value := range v {
sum += value
}
return sum
}
func main() {
s := myslice{11, 22, 33}
fmt.Println(s.sumOfSlice())
}
2.struct 结合它的方法就等价于面向对象中的类。只不过 struct 可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。所以,没有办法直接在 int、float 等内置的简单类型上定义方法,真要为它们定义方法,可以像上面示例中一样使用 type 定义这些类型的别名,然后定义别名的方法。
3. 方法有两种类型:(T Type)
和(T *Type)
,
它们之间有区别,后文解释。
4. 方法就是函数,所以 Go 中没有方法重载 (overload) 的说法,也就是说同一个类型中的所有方法名必须都唯一。但不同类型中的方法,可以重名。
例如:
1func (a *mytype1) add() ret_type {}
func (a *mytype2) add() ret_type {}
5.type 定义类型的别名时,别名类型不会拥有原始类型的方法。
例如 mytype 上定义了方法 add(),mytype 的别名 new_type 不会有这个方法,除非自己重新定义。
6. 如果 receiver 是一个指针类型,则会自动解除引用。
例如,下面的 a 是指针,它会自动解除引用使得能直接调用属于 mytype1 实例的方法 add()。
func (a *mytype1) add() ret_type {}
a.add()
7.(T Type)
或(T *Type)
的 T,其实就是面向对象语言中的 this 或 self,表示调用该实例的方法。如果愿意,自然可以使用 self 或 this,例如(self Type)
,但这是可以随意的。
8. 方法和 type 是分开的,意味着实例的行为 (behavior) 和数据存储 (field) 是分开的,但是它们通过 receiver 建立起关联关系。