DEEP 188 · 第十六辑 · 小白基础课 · LEARN NOTES

收进学习手册 · 2026-09-11 · duck.whatled.com

解读 188 · Rust 入门(一):变量与所有权

解读对象:概念课 · 以 duck-control/src/(bus.rs、safety.rs、io.rs)为教材
需要的前置:零基础可读;下一篇:解读 189

Rust 最出名的一条规矩是"所有权"。本篇不背定义,只用这只鸭子代码里的真实片段,讲三件事:let、mut、以及"钥匙移交"。

let 与 mut:默认上锁的盒子

let 声明一个变量,但 Rust 的变量默认不可变——像个贴了封条的盒子,想改内容必须声明 mut(mutable)。DynamixelIo::open 里有一段标准示范(bus.rs:118-122):

let controller = open_controller(port, BAUD_RATE)?;

let mut ids = Vec::with_capacity(NUM_JOINTS + 1);
ids.push(IMU_DXL_ID);
ids.extend_from_slice(&JOINT_IDS);

逐行看:controller 没有 mut,因为它开好之后只被读;ids 是要往后添加设备的名单,所以声明成 let mut,下面才能 push。这不是啰嗦,是文档——读到 let 你就知道这名字不会再被赋值,读到 let mut 你会多看一眼谁在改它。

所有权:钥匙移交,原主人失效

Rust 规定:每块数据有一把"钥匙"(所有权),赋值或传参 = 把钥匙交给对方,原变量就此失效,再用会编译报错。FakeIo::at 里能看到一次完整的"造出来→交出去"(io.rs:235-239):

pub fn at(positions: [f64; NUM_JOINTS]) -> Self {
    let mut io = Self::new();
    io.sensors.positions = positions;
    io
}

最后一行没有分号——把 io 这把钥匙移交给调用者。移交更严肃的用法在安全层:Safety::new(io: T, config: SafetyConfig) 把 io 整个收进 Safety(safety.rs:117),从此谁也别想绕开安全层直接摸电机。源码注释说得直白:"Safety 拥有唯一的 RobotIo 句柄……这是借入检查器强制执行的事实,而不是一条靠自觉的约定"。类比:把房子钥匙交给管家,你手里那把自动作废——想开锁只能走管家,这正是安全层要的效果。

借用:不交钥匙,借出去用一下

钥匙移交太狠?多数时候只需要"借用":加 & 表示临时借,用完归还,原主人还在。io.rs:116 的写信号签名:

fn write(&mut self, targets: &JointTargets) -> Result<()>;

targets 前面的 & 就是"借":调用者把目标位姿借给 write 抄一遍,自己照旧持有。&mut(可变借用)则规定同一时刻只能有一个借用人——房子要么一个人在里面装修,要么一群人隔着窗户看,不许边装修边围观。前一段代码里的 &JOINT_IDS 也是借用:只读那份关节编号表,不把表抢走。

你带走的收获

延伸

什么鸭 WHATDUCK · 复刻学习笔记 ← 全部手册 · 首页