所有权设计先把资源权限讲清

📅 发布时间:2026/8/28 2:20:28
所有权设计先把资源权限讲清
所有权设计先把资源权限讲清我把“谁能修改数据”写进函数签名而不是靠调用者自觉。读取配置时传Config只有更新函数接受mut Configfn show(c: Config) { println!({}, c.name); } fn rename(c: mut Config, name: String) { c.name name; }编译器会阻止同一时间的读写混用这比注释可靠。mut也不是权限系统跨进程、跨用户的权限仍要由服务端校验不能把 Rust 的借用检查误当成安全边界。先说清函数需要什么能力一个函数接收所有权、共享借用还是可变借用分别表达了不同承诺。只读函数没有必要取得整个值的所有权需要修改局部状态时也不应顺手暴露与任务无关的字段。签名越准确调用者越容易判断值在调用后是否还能使用审查者也能看出修改可能发生在哪里。设计接口时可以从最窄能力开始。只需要名称就接收str只需要遍历就接收切片或迭代器确实要保存数据时再取得所有权。这样做不是为了追求短签名而是避免内部实现无意间得到额外权力。若后续需求改变再有依据地扩大能力比一开始就传入可变的完整对象更容易控制影响范围。所有权还包括释放责任文件、连接、锁守卫和临时目录都有生命周期。把资源包装进类型可以让离开作用域时的清理路径更明确但仍要考虑清理失败、提前返回和任务取消。比如持锁期间调用外部服务等待时间就会扩大临界区把锁守卫藏进长生命周期结构也可能使其他任务无法推进。审查资源类型时应回答谁创建、谁关闭、能否复制、能否跨线程以及取消后由谁收尾。Drop能帮助释放本地资源却不能保证远端事务已经提交或撤销。涉及外部状态时仍需显式的完成协议和错误处理不能把离开作用域当作所有清理都已成功。内部可变性不是免费通行证RefCell、Mutex和原子类型允许在不同约束下修改共享状态它们解决的是特定并发或借用问题不是把设计责任交给运行时。使用前要写清共享的理由、冲突时的行为和锁的顺序。否则编译期问题可能变成运行时 panic、死锁或难以复现的状态竞争。有些数据根本不必共享。把任务拆成拥有独立状态的部分通过消息传递结果往往比让所有线程访问同一个可变对象更容易测试。确需共享时把同步原语封装在小模块内外部只看到能维持不变量的方法不让调用方自行组合锁与字段修改。借用规则与业务授权分属两层Rust 可以证明某段进程内代码遵守内存访问规则却不知道当前用户是否有权修改这条记录。服务端收到请求后仍要根据认证身份、资源归属和具体动作做授权。即使业务对象以不可变借用传入如果数据在进入进程前已经越权读取借用检查也无法补救。反过来权限校验通过也不代表资源使用一定安全。授权层决定“谁可以做”类型和所有权设计约束“代码如何做”。两者都应有拒绝测试无权用户不能进入修改路径合法用户触发错误时也不能留下半更新状态或泄漏资源。用测试验证边界而不是语法编译失败用例可以说明错误的借用方式确实被拒绝普通单元测试则检查公开方法是否保持不变量。并发代码还要覆盖取消、超时和多个调用者争用资源的情况。测试不必依赖真实账号或生产数据用小型结构就能验证所有权转移和错误返回。好的所有权设计不会让所有函数都显得“高级”。它只是把读取、修改、保存和释放放在合适的类型与接口上让不该发生的组合难以表达。业务权限继续由业务层负责两层边界各自清楚代码才不会用一种安全机制替另一种安全机制背书。