外观
method
Phase 01 — Go Fundamentals · 知识点 13
1. 学习目标
- 为 struct 定义 method
- 区分值接收者
(a AGV)与指针接收者(a *AGV) - 知道何时必须用指针接收者
- 理解 method 不是 class 的 method,无继承
2. 为什么需要
method 把数据和操作绑在一起:agv.Move()、agv.IsOverspeed()。比独立函数 Move(agv) 更符合面向对象风格,但 Go 的 method 是语法糖,底层仍是函数。
3. 核心概念
go
type AGV struct {
ID string
Speed float64
}
// 值接收者 — 操作副本
func (a AGV) String() string {
return fmt.Sprintf("%s (%.1f m/s)", a.ID, a.Speed)
}
// 指针接收者 — 可修改原对象
func (a *AGV) SetSpeed(s float64) {
a.Speed = s
}
func (a *AGV) IsOverspeed(max float64) bool {
return a.Speed > max
}| 接收者 | 何时用 |
|---|---|
值 (a AGV) | 不修改 struct、小 struct、需要副本 |
指针 (a *AGV) | 修改 struct、大 struct、保持一致性 |
惯例:如果一个 method 用指针接收者,同一类型的所有 method 都用指针接收者。
4. 基础语法
go
package main
import "fmt"
type AGV struct {
ID string
X, Y float64
Speed float64
}
func (a *AGV) Move(dx, dy float64) {
a.X += dx
a.Y += dy
}
func (a AGV) DistanceToOrigin() float64 {
return math.Sqrt(a.X*a.X + a.Y*a.Y)
}
func main() {
agv := &AGV{ID: "AGV-001", X: 3, Y: 4}
fmt.Println(agv.DistanceToOrigin()) // 5
agv.Move(1, 1)
fmt.Printf("%+v\n", agv)
}Go 自动取地址:agv.Move() 即使 agv 是值也会自动 (&agv).Move()。
5. 代码解析
- method 是带接收者的函数:
func (receiver Type) Name() {} - 非 struct 类型也可有 method(如
type MyInt int) - method set:
*T的 method set 包含*T和T的 method;T的 method set 只含T的
6. JavaScript / TypeScript 对比
| Go method | JS class |
|---|---|
| 定义在 type 外 | 定义在 class 内 |
| 无 this 绑定问题 | 需注意 this |
| 无继承 | extends 继承 |
| 值/指针接收者显式 | 对象总是引用 |
7. 常见错误
- 值接收者修改字段无效 → 改用指针接收者
- nil 指针调用 method → 可以,method 内需检查 nil
- 混用值/指针接收者 → 团队风格不一致
- 过度 OOP → Go 倾向小 struct + 简单 method
8. 实际应用
go
func (a *AGV) ToJSON() ([]byte, error) {
return json.Marshal(a)
}
func (a *AGV) UpdateFromTelemetry(x, y, speed float64) {
a.X, a.Y, a.Speed = x, y, speed
}数字孪生中,设备 struct + method 构成领域模型,后续 interface 实现多态。
9. 深入理解
method 是编译期绑定,非 virtual dispatch(除非通过 interface)。这是 Go 与 Java/C++ 虚函数的本质区别。
10. 练习
- L1:值接收者 String() method
- L2:指针接收者 SetSpeed / Move
- L3:IsOverspeed / DistanceToOrigin
- L4:AGV 完整 method set
11. 学习检查
- [ ] 值接收者与指针接收者区别?
- [ ] 修改字段该用哪种接收者?
- [ ] nil 指针能调 method 吗?
12. 下一步
→ Phase 02 interface:method set 与多态