主题
05 · 结构体、方法与接口
目标:用「组合 + 隐式接口」表达依赖,而不是硬套 Java/TS 的类继承。
官方:Tour Methods & Interfaces · Effective Go · Interfaces · Go Proverbs 中的 Accept interfaces, return structs
1. Struct 与方法
go
type Note struct {
ID string
Content string
}
func (n Note) Preview(max int) string {
if len(n.Content) <= max {
return n.Content
}
return n.Content[:max] + "..."
}
func (n *Note) Append(s string) {
n.Content += s
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| 接收者 | 何时用 |
|---|---|
值接收者 (n Note) | 不改接收者;小结构体 |
指针接收者 (n *Note) | 要改字段;大结构体;或需与指针方法集一致 |
同一类型的方法集要一致:若已有指针方法,调用时注意可寻址性。细节见规范与 Tour。
导出规则:大写字段/方法名包外可见——类似「public」,但粒度在标识符。
2. 接口:隐式满足(对 TS 用户最反直觉)
go
type Storer interface {
Save(n Note) error
Get(id string) (Note, error)
}
type MemoryStore struct {
data map[string]Note
}
func (m *MemoryStore) Save(n Note) error { /* ... */ return nil }
func (m *MemoryStore) Get(id string) (Note, error) { /* ... */ return Note{}, nil }
// MemoryStore 只要方法集匹配,就满足 Storer——无需 implements 关键字
var _ Storer = (*MemoryStore)(nil) // 编译期断言:实现是否完整1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
要点:
- 接口由方法签名定义,不是由「声明实现」定义。
- 小接口更香:
io.Reader、io.Writer是典范(读标准库)。 - 常见模式:函数参数收接口,构造返回具体类型。
3. 对照 TypeScript
| TS | Go |
|---|---|
class Foo implements Bar | 隐式满足;可用 var _ Bar = (*Foo)(nil) 检查 |
继承 extends | 优先 嵌入(embedding) 组合 |
any / 过度 interface | 先具体类型;边界处再抽接口 |
| duck typing 靠结构 | 方法集 duck typing,但是静态检查 |
go
type Logger struct{ prefix string }
type Service struct {
Logger // 嵌入:提升方法
}1
2
3
4
5
2
3
4
5
4. 空接口与 any
interface{} / any:任意类型,但失去静态信息。入门期少用;解析 JSON 进 map[string]any 时要格外小心类型断言。
go
var v any = "hello"
s, ok := v.(string)1
2
2
5. 最小练习
- 定义
Note+Storer接口。 - 实现
MemoryStore。 - 写
func Export(s Storer, id string) (string, error),只依赖接口。 - 用
var _ Storer = (*MemoryStore)(nil)锁实现。
下一篇并发、再下一篇 HTTP 会复用这个边界。
6. AI 审查提示词
text
请按 Effective Go 的接口习惯审查:
- 接口是否过大?
- 是否该接受接口却收了具体类型?
- 方法接收者值/指针是否一致?
- 有无不必要的 any?
引用可对照的标准库接口(如 io.Reader)说明。1
2
3
4
5
6
2
3
4
5
6
7. 验收清单
- [ ] 能写带方法的 struct
- [ ] 理解「隐式满足」并用编译期断言
- [ ] 能说清为何入门少用继承、多用组合
- [ ] 读过
io.Reader文档一眼
8. 下一步
→ 06 · 并发:goroutine / channel / context
