1. 方法(Method)是什么?
在 Go 中 没有类 (class) ,但你可以给任意用户定义类型添加方法。
方法就是带有 接收者(receiver) 的函数,接收者在 func 关键字与方法名之间定义。(Go Tour)
基础方法声明格式
func (r ReceiverType) MethodName(params) returns {
// 方法体
}
这里:
-
(r ReceiverType)就是接收者 -
r相当于 Go 中的 this / self -
方法属于其接收者类型
示例:给自定义类型定义方法
package main
import "fmt"
type Circle struct {
radius float64
}
// 为 Circle 类型定义 Area 方法
func (c Circle) Area() float64 {
return 3.1416 * c.radius * c.radius
}
func main() {
c := Circle{radius: 5}
fmt.Println("面积:", c.Area())
}
2. 值接收者 vs 指针接收者
Go 中有两种方法接收者:
值接收者(value receiver)
func (c Circle) Area() float64 { ... }
-
用于 不会修改对象本身 的方法
-
像基础值传入一样复制一份
指针接收者(pointer receiver)
func (c *Circle) Scale(factor float64) {
c.radius *= factor
}
-
使用
*Type -
可修改原始值
-
性能更节省复制开销
3. 为什么用方法而不是普通函数?
方法可以:
✔ 把行为 绑到某个类型上
✔ 实现抽象 / 多态
✔ 与接口配合发挥更强逻辑
4. 接口(Interface)是什么?
接口定义了一组 方法签名 。
只要某个类型实现了接口中的所有方法,这个类型就是接口的实现者。
Go 中的接口是 隐式实现(implicit implementation) ,无需显式声明。(HackMD)
定义接口示例
type Shape interface {
Area() float64
}
这里 Shape 是一个接口,任何拥有 Area() float64 方法的类型都实现了 Shape。
赋值到接口变量
Go 允许 Shape 类型的变量保存任何实现了 Area() 的类型:
var s Shape
s = Circle{radius: 5}
fmt.Println(s.Area())
5. 接口使用技巧
多个方法的接口
type FullName interface {
FirstName() string
LastName() string
}
一个类型必须实现全部才能 satisfy 接口。
空接口(interface{})
Go 中任何类型都实现了空接口。空接口可以持有任意类型:
var x interface{}
x = 42
x = "Hello"
6. 接口的动态值与类型
接口值内部有两部分:
🔹 动态类型 (实际存放值的类型)
🔹 动态值(当前值)
当你调用接口方法时,Go 会根据动态值去执行实际类型的方法。
7. 接口的零值
var s Shape
此时 s 为 nil 接口值,调用其方法会 panic。
8. 接口常见用途
✔ 抽象行为
✔ 编写函数更灵活
✔ 支持多态
✔ 组合更复杂的逻辑
例如:
func PrintArea(s Shape) {
fmt.Println(s.Area())
}
只要是 Shape,就可以传入。
总结
| 概念 | 说明 |
|---|---|
| 方法 | 有接收者的函数,属于类型 |
| 值接收者 | 不修改原值 |
| 指针接收者 | 修改原值 |
| 接口 | 方法集合,行为抽象 |
| 隐式实现 | 不需显式声明 implements |