方法

2023/1/15

# Go方法定义

Go 引入方法这一元素,并不是要支持面向对象编程范式,而是 Go 践行组合设计哲学的一种实现层面的需要。 一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。语法格式如下:

func (variable_name variable_data_type) function_name() [return_type]{
   /* 函数体*/
}

# 方法调用

package main
import "fmt"

type T struct {
	a int
}

func(t T) Get() int {
	return t.a
}

func(t *T) Set(i int)  {
	t.a = i
}

func (t *T) Print() {
	fmt.Printf("%p, %v, %d \n",t, t, t.a)
}
func main() {
	var t = &T{}

	// 普通方法调用
	t.Set(1)
	fmt.Println(t.Get())

	// 方法值调用
	f := t.Set
	f(2)
	t.Print()


	// 方法表达式调用
	m :=T{a:3}
	f1 := T.Get;f1(m) // 与普通方法等价 m.Get()
	f2 :=(*T).Set; f2(&m,4) // 与普通方法等价 m.Set(4)
}

# 一般方法调用

# 方法值调用

变量x的静态类型是T,M是类型T的一个方法,x.M被称为方法值,x.M是一个函数类型变量,可以赋值给其他变量,并像普通的函数名一样使用。

方法值其实是一个闭包的函数变量,其底层实现原理和待遇闭包的匿名函数类似,接收值被隐式地绑定到方法值的闭包环境中,后续调用不需要再显式地传递接收者。

# 方法表达式调用

方法表达式相当于提供一种语法将类型方法调用显式地转换未函数调用,接收者必须显示地传递进去。

# 方法集

为了简化描述,将接收者receiver为值类型T的方法的集合记录为S,将接收者receiver为指针类型T的方法的集合记录为S, 类型的方法集总结如下:

  • T类型的方法集是S
  • T类型的方法集是S和S

# 值调用的方法集

# 表达式调用的方法集

# 嵌套组合

# 内部类型的方法可以被提升到外部类型

# 内部类型实现的接口会自动提升到外部类型

# 外部类型并不需要使用内部类型的实现,而想另外实现

外部类型定义与内部类型同名方法,这样内部类型实现的接口不会提升到外部类型

# 组合的方法集

组合结构的方法集有如下规则:

  • 1、若类型S包含匿名字段T,则S的方法集包含T的方法集
  • 2、若类型S包含匿名字段T,则S的方法集包含T和T方法集
  • 3、不管类型S中嵌入的匿名字段是T还是*T,S方法集总是包含T和T方法集合