typora/note/Go/方法.md
2024-12-12 10:48:55 +08:00

153 lines
3.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### 方法
- Go 语言中的方法的本质就是,一个以方法的 receiver 参数作为第一个参数的普通函数
![](https://blog-heysq-1255479807.cos.ap-beijing.myqcloud.com/blog/wiki/go/methods.jpg)
- 方法支持赋值给变量,相当于第一个参数是结构体自身或者自身的指针类型
```go
package main
import "fmt"
type T struct{}
func (t *T) M(n int) {
fmt.Println(n)
}
func (t T)N(n int) {
fmt.Println(n)
}
func main() {
m1 := (*T).M
m1(&T{}, 2)
m2 := T.N
m2(T{}, 3)
}
```
### 方法接收receiver
```go
func (t *T或T) MethodName(参数列表) (返回值列表) {
// 方法体
}
```
- T为基类型
- receiver 参数的基类型本身不能为指针类型或接口类型
- 每个方法只能有一个 receiver 参数
- Go 不支持在方法的 receiver 部分放置包含多个 receiver 参数的参数列表,或者变长 receiver 参数
- 方法接收器receiver参数、函数 / 方法参数,以及返回值变量对应的作用域范围,都是函数 / 方法体对应的显式代码块
- receiver 部分的参数名不能与方法参数列表中的形参名,以及具名返回值中的变量名存在冲突,必须在这个方法的作用域中具有唯一性
- 如果在方法体中,我们没有用到 receiver 参数,我们也可以省略 receiver 的参数名
### 方法声明约束
- 方法声明要与 receiver 参数的基类型声明放在同一个包内
- 不能为原生类型(诸如 int、float64、map 等)添加方法
- 不能跨越 Go 包为其他包的类型声明新方法
### 选择receiver 原则
- 如果需要修改receiver内部属性使用指针类型
- 不需要修改内部属性,使用结构体类型,传参值拷贝,但是结构体过大时,选用指针类型
- 如果 T 类型需要实现某个接口,那就要使用 T 作为 receiver 参数的类型,来满足接口类型方法集合中的所有方法
### 方法集合
```go
- 用来判断一个类型是否实现了某接口类型的唯一手段
- T类型实现了M1方法
- *T类型实现了M1和M2方法
type Interface interface {
M1()
M2()
}
type T struct{}
func (t T) M1() {}
func (t *T) M2() {}
func main() {
var t T
var pt *T
var i Interface
i = pt
i = t // cannot use t (type T) as type Interface in assignment: T does not implement Interface (M2 method has pointer receiver)
}
```
### type定义的新类型和命名的类型的方法集合
- 自定义非接口类型的 defined 类型的方法集合为空
- 自定义接口类型的 defined 类型的方法集合为接口的方法
```go
package main
type T struct{}
func (T) M1() {}
func (*T) M2() {}
type T1 T
func main() {
var t T
var pt *T
var t1 T1
var pt1 *T1
dumpMethodSet(t)
dumpMethodSet(t1)
dumpMethodSet(pt)
dumpMethodSet(pt1)
}
main.T's method set:
- M1
main.T1's method set is empty!
*main.T's method set:
- M1
- M2
*main.T1's method set is empty!
```
- 无论原类型是接口类型还是非接口类型,类型别名都与原类型拥有完全相同的方法集合
```go
type T struct{}
func (T) M1() {}
func (*T) M2() {}
type T1 = T
func main() {
var t T
var pt *T
var t1 T1
var pt1 *T1
dumpMethodSet(t)
dumpMethodSet(t1)
dumpMethodSet(pt)
dumpMethodSet(pt1)
}
main.T's method set:
- M1
main.T's method set:
- M1
*main.T's method set:
- M1
- M2
*main.T's method set:
- M1
- M2
```