方法的一些注意事项

1. 方法的 receiver type 并非一定要是 struct 类型,type 定义的类型别名、slice、map、channel、func 类型等都可以。但内置简单数据类型 (int、float 等) 不行,interface 类型不行

  1. package main
  2. import "fmt"
  3. type myint int
  4. func (i *myint) numadd(n int) int {
  5. return n + 1
  6. }
  7. func main() {
  8. n := new(myint)
  9. fmt.Println(n.numadd(4))
  10. }

以 slice 为类型,定义属于它的方法:

  1. package main
  2. import "fmt"
  3. type myslice []int
  4. func (v myslice) sumOfSlice() int {
  5. sum := 0
  6. for _, value := range v {
  7. sum += value
  8. }
  9. return sum
  10. }
  11. func main() {
  12. s := myslice{11, 22, 33}
  13. fmt.Println(s.sumOfSlice())
  14. }

2.struct 结合它的方法就等价于面向对象中的类。只不过 struct 可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。所以,没有办法直接在 int、float 等内置的简单类型上定义方法,真要为它们定义方法,可以像上面示例中一样使用 type 定义这些类型的别名,然后定义别名的方法

3. 方法有两种类型(T Type)(T *Type)

它们之间有区别,后文解释。

4. 方法就是函数,所以 Go 中没有方法重载 (overload) 的说法,也就是说同一个类型中的所有方法名必须都唯一。但不同类型中的方法,可以重名

例如:

  1. 1func (a *mytype1) add() ret_type {}
  2. func (a *mytype2) add() ret_type {}

5.type 定义类型的别名时,别名类型不会拥有原始类型的方法

例如 mytype 上定义了方法 add(),mytype 的别名 new_type 不会有这个方法,除非自己重新定义。

6. 如果 receiver 是一个指针类型,则会自动解除引用

例如,下面的 a 是指针,它会自动解除引用使得能直接调用属于 mytype1 实例的方法 add()。

  1. func (a *mytype1) add() ret_type {}
  2. a.add()

7.(T Type)(T *Type)的 T,其实就是面向对象语言中的 this 或 self,表示调用该实例的方法。如果愿意,自然可以使用 self 或 this,例如(self Type),但这是可以随意的。

8. 方法和 type 是分开的,意味着实例的行为 (behavior) 和数据存储 (field) 是分开的,但是它们通过 receiver 建立起关联关系