关于 m01-ownership
m01-ownership 是面向 Rust 开发者的学习技能,用于分析所有权和生命周期问题。它将编译器错误转化为设计问题,并关联到具体实现模式。
主要功能
- 01所有权与生命周期设计提示
- 02Rust 错误代码指南
- 03移动、借用与克隆参考
- 04使用 Rc 和 Arc 共享所有权
- 05关联其他设计技能
适用场景
- 01排查借用检查器错误
- 02选择移动还是借用数据
- 03评估克隆是否必要
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ actionbook/ rust-skills --skill m01-ownership安装后在 Claude Code 中输入/m01-ownership确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
comparison.mdexamples/best-practices.mdpatterns/common-errors.mdlifetime-patterns.md详细介绍
所有权与生命周期
第 1 层:语言机制
核心问题
这份数据应该由谁拥有,拥有多久?
在修复所有权错误之前,先了解数据的作用:
- 它是共享的还是独占的?
- 它的生命周期短还是长?
- 它会被转换,还是仅被读取?
错误 → 设计问题
| 错误 | 别只说 | 应该问 |
|---|---|---|
| E0382 | “克隆它” | 这份数据应该由谁拥有? |
| E0597 | “延长生命周期” | 作用域边界是否合适? |
| E0506 | “先结束借用” | 是否应该在别处进行修改? |
| E0507 | “移动前先克隆” | 为什么要从引用中移出数据? |
| E0515 | “返回所有权值” | 是否应该由调用方拥有这份数据? |
| E0716 | “绑定到变量” | 为什么这是临时值? |
| E0106 | “添加 'a” | 实际的生命周期关系是什么? |
思考提示
修复所有权错误前,先问:
-
这份数据在领域中的作用是什么?
- 实体(唯一标识)→ 由其拥有
- 值对象(可互换)→ 可以克隆/复制
- 临时值(计算结果)→ 也许应该调整结构
-
所有权设计是有意为之的吗?
- 有意设计 → 在约束范围内处理
- 意外造成 → 考虑重新设计
-
是修复症状,还是重新设计?
- 如果是第 3 次尝试 → 升级到第 2 层
向上追溯 ↑
错误持续出现时,向上追溯到设计层:
E0382 (moved value)
↑ Ask: What design choice led to this ownership pattern?
↑ Check: m09-domain (is this Entity or Value Object?)
↑ Check: domain-* (what constraints apply?)
| 持续出现的错误 | 追溯到 | 问题 |
|---|---|---|
| E0382 重复出现 | m02-resource | 是否应该使用 Arc/Rc 进行共享? |
| E0597 重复出现 | m09-domain | 作用域边界是否设在了合适的位置? |
| E0506/E0507 | m03-mutability | 是否应该使用内部可变性? |
向下追溯 ↓
从设计决策落实到实现:
"Data needs to be shared immutably"
↓ Use: Arc<T> (multi-thread) or Rc<T> (single-thread)
"Data needs exclusive ownership"
↓ Use: move semantics, take ownership
"Data is read-only view"
↓ Use: &T (immutable borrow)
快速参考
| 模式 | 所有权 | 成本 | 适用场景 |
|---|---|---|---|
| Move | 转移 | 零 | 调用方不再需要数据 |
&T | 借用 | 零 | 只读访问 |
&mut T | 独占借用 | 零 | 需要修改 |
clone() | 复制 | 分配 + 复制 | 确实需要副本 |
Rc<T> | 共享(单线程) | 引用计数 | 单线程共享 |
Arc<T> | 共享(多线程) | 原子引用计数 | 多线程共享 |
Cow<T> | 写时克隆 | 修改时分配 | 可能会修改 |
错误代码参考
| 错误 | 原因 | 快速修复 |
|---|---|---|
| E0382 | 值已被移动 | 克隆、使用引用,或重新设计所有权 |
| E0597 | 引用的生命周期超出所有者 | 延长所有者的作用域或调整结构 |
| E0506 | 借用时赋值 | 修改前结束借用 |
| E0507 | 从借用值中移出数据 | 克隆或使用引用 |
| E0515 | 返回局部引用 | 返回所有权值 |
| E0716 | 临时值已被释放 | 绑定到变量 |
| E0106 | 缺少生命周期 | 添加 'a 注解 |
反模式
| 反模式 | 不妥之处 | 更好的做法 |
|---|---|---|
到处使用 .clone() | 掩盖设计问题 | 正确设计所有权 |
| 与借用检查器对抗 | 增加复杂性 | 配合编译器工作 |
所有内容都用 'static | 限制灵活性 | 使用合适的生命周期 |
用 Box::leak 泄漏内存 | 内存泄漏 | 正确设计生命周期 |
相关技能
| 场景 | 参阅 |
|---|---|
| 需要智能指针 | m02-resource |
| 需要内部可变性 | m03-mutability |
| 数据是领域实体 | m09-domain |
| 学习所有权概念 | m14-mental-model |
评论
支持 Markdown