其他
用 Rust 构建高性能、内存安全的系统程序时:用所有权…
适用于用 Rust 开发系统软件、高性能服务、并发/异步程序、FFI/Wasm/嵌入式等需要编译期内存安全与零成本抽象的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 49/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
用 Rust 构建高性能、内存安全的系统通用
解决思路
- 所有权:每个值只有一个所有者;所有者离开作用域时值被 drop;所有权可 move 给新所有者。
- 移动语义:对未实现 Copy 的类型,赋值/传参默认 move;move 后不要使用原变量,避免 double-free 和 use-after-move。
- Copy 类型:对 i32 等实现 Copy 的类型,赋值是复制,原变量仍可用。
- 不可变借用:用 &T 临时访问数据而不取得所有权;借用期间原变量仍可用。
- 可变借用:用 &mut T 取得独占可变访问;Rust 在编译期阻止数据竞争。
- 借用规则:同一作用域只能有一个可变引用,或有任意多个不可变引用;引用必须始终有效;可变与不可变借用不能共存。
- 借用冲突处理:先结束旧借用再创建新借用,利用 NLL 调整作用域;如先 println 使用不可变借用后再创建可变闭包。
- 生命周期:用 fn longest<'a>(x: &'a str, y: &'a str) -> &'a str 等显式标注,保证返回引用与输入引用一样长。
- 单线程共享所有权:用 Rc<RefCell<T>>;clone 增加引用计数;RefCell::borrow_mut 提供内部可变性,运行时检查借用。
- 多线程共享所有权:用 Arc<T>;clone 后 move 到 thread::spawn;Arc 用原子操作计数,保证线程安全。
- Box 堆分配:用 Box<T> 作为拥有堆数据的指针,适合递归类型、大值避免栈复制、trait object 动态分发。
- 线程消息传递:用 std::sync::mpsc::channel;spawn 线程 move tx 发送消息;rx.recv 接收。
- 共享状态:用 Arc<Mutex<T>>;每个线程 clone Arc,lock 后修改;join 所有 handle。
- 并发类型选择:Mutex<T> 互斥锁;RwLock<T> 读多写少;Arc<T> 线程安全共享;mpsc 多生产者单消费者通道。
- 数据竞争检测:用 ThreadSanitizer,设置 RUSTFLAGS=-Zsanitizer=thread,运行并发访问 static mut 的代码,查看 data race 报告。
- async/await:用 async fn 和 .await 写 I/O 并发,不阻塞线程。
- 递归 async:递归 async fn 需要 Box::pin(foo(n - 1)).await,给 future 已知大小。
- async 闭包 move:需要 AsyncFnOnce 时用 async move || 按 move 捕获,确保所有权。
- async move 闭包借用:即使 move 捕获,也可能只捕获解引用值,使内部协程按原始生命周期重新借用,如 let x=&1; async move || println!(*x)。
- async 闭包可变借用:let mut x; async || { x=1; } 父级可变借用 x;调用时隐式 autoref 给 AsyncFnMut::async_call_mut,内部协程按闭包生命周期捕获。
- E0373:async 块捕获短生命周期变量且需要 'static/Send 时,改用 async move 把变量移入。
- unsafe 使用范围:仅在必要时用 unsafe,手动保证安全;包括解引用裸指针、调用 unsafe fn/method、访问/修改可变 static、实现 unsafe trait、访问 union 字段。
- unsafe 解引用裸指针:用宏将 &() as *const () 后解引用,确保指针有效。
- unsafe impl Sync:手动实现 unsafe impl<T> Sync for NotThreadSafe<T> 时,必须确保类型实际线程安全;Cell 默认非 Sync,需要自行论证。
- FFI 声明与调用:用 #[link(name = "foo")] extern "C" 声明 C 函数;用 unsafe extern "C" fn 定义回调;调用 C 函数需 unsafe。
- FFI 类型安全与 CFI:不要用 mem::transmute 把函数指针变成不匹配签名;启用 Control Flow Integrity 时会终止程序,防止控制流劫持。
- 内联汇编系统调用:用 core::arch::asm! 执行系统调用,传 const/sym 参数并设置 options(noreturn),如 Windows VirtualFree 内存释放。
- Result/Option 错误处理:用 Result<T,E> 和 Option<T> 显式表达错误/缺失;用 match 处理 Ok/Err。
- ? 运算符:在返回 Result 的函数中用 ? 传播错误,保持错误类型匹配。
- 自定义错误:定义 enum AppError,包含 IoError/ParseError/Custom;实现 fmt::Display 和 std::error::Error。
- AddressSanitizer 配置:设置 RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address,用 cargo run -Zbuild-std --target x86_64-unknown-linux-gnu。
- ASan 检测栈溢出:对数组 as_ptr().offset(4) 越界读取,ASan 报告 stack-buffer-overflow。
- ASan 检测堆溢出:对 Vec as_ptr().offset(4) 越界读取,ASan 报告 heap-buffer-overflow。
- ASan 检测 use-after-scope:将局部变量地址存入 static mut P,离开作用域后 write_volatile,ASan 报告 stack-use-after-scope。
- 零成本抽象:用迭代器链 (1..100).filter().map().sum(),编译器会优化为紧凑循环。
- 内联与单态化:用 #[inline] 和泛型 add<T>;泛型会为 i32、f64 等具体类型单态化生成专用代码。
- 智能指针开销:Box 单次堆分配无额外开销;Rc 引用计数有开销;Arc 原子引用计数开销更高;Mutex 锁获取有开销;RefCell 运行时借用检查有开销。
- 避免分配:优先返回 impl std::fmt::Display + '_ 并使用 format_args!,而不是 format! 返回新 String。
- Builder 模式:为 Config 提供 ConfigBuilder,字段用 Option,链式 host/port 方法,build 设置默认值。
- Newtype 模式:用 struct UserId(u64) 和 PostId(u64) 区分 ID 类型,防止把 PostId 传给 get_user。
- RAII:为 FileGuard 实现 Drop,在析构时自动关闭文件并执行清理。
- E0500:闭包需要唯一访问已被借用的变量时,先使用旧借用并让其结束,利用 NLL,再创建闭包。
- E0502:同一作用域不能同时可变和不可变借用;先执行可变借用,再创建不可变借用,或调整顺序。
- E0505:值被借用时不要移动;结束借用、重新组织代码、克隆或先释放引用后再移动。
- E0524 方案1:两个闭包要可变借用同一变量时,用块/作用域顺序执行,先 drop c1 再创建 c2。
- E0524 方案2:用 Rc<RefCell<T>> 共享可变访问,在闭包内 borrow_mut 后调用 set。
- E0507 方案1:不能从借用内容 move 时,将方法改为 &self 只借用。
- E0507 方案2:用 into_inner 取回所有权后再 move 并调用方法。
- 结构化日志:用 tracing 的 info/warn/error 和 #[instrument] 为 async fn 记录请求 ID 和错误。
- 配置管理:用 serde 反序列化 AppConfig,用 config::Config::builder 加载 config 文件和 APP_ 环境变量。
- 优雅关闭:用 tokio::signal 监听 ctrl_c 和 Unix terminate,通过 tokio::select! 等待后执行 shutdown。
- 连接池:用 deadpool_postgres Config/Runtime 创建 Pool,从池中 get client 并 query_one 查询。
- API 设计-引用优先:默认接受 &T 而不是 T,除非确实需要所有权。
- API 设计-返回拥有类型:返回 String 而不是 &str,简化 API。
- API 设计-标准 trait:实现或 derive Debug、Clone、PartialEq、Send、Sync。
- API 设计-Into 灵活:用 impl Into<String> 等让调用方传入多种类型。
- API 设计-类型系统:用 newtype、enum、Result 让类型系统保证正确性。
- 测试:用 #[cfg(test)] mod tests、#[test]、#[should_panic(expected = division by zero)]、#[tokio::test] 覆盖同步/panic/async。
- 文档:用 /// 编写文档、Examples、Panics,并用 doctest 验证示例。
- 依赖管理:在 Cargo.toml 声明 tokio features、serde derive、tracing、dev-dependencies criterion,并在 release profile 设置 lto=true 和 codegen-units=1。
- 借用检查器问题:不可变借用未结束时可变借用报错;确保借用作用域不重叠。
- 借用检查器问题:不能从借用内容 move;改用 clone、引用或 Rc<RefCell<T>>。
- 借用检查器问题:生命周期复杂;添加显式生命周期标注或重构代码。
- 性能问题-编译慢:使用增量编译、减少泛型实例化、用 cargo check。
- 性能问题-运行时慢:用 perf 分析、开启 LTO、检查不必要分配/克隆。
- 性能问题-内存高:用引用替代克隆、流式处理、用 Valgrind 分析。
- 并发问题-死锁:多 mutex 固定加锁顺序,使用 try_lock 配合超时。
- 并发问题-unsafe 数据竞争:用 ThreadSanitizer 运行并仔细审查 unsafe 块。
- 并发问题-async 不推进:检查 async 中的阻塞操作,CPU 密集用 spawn_blocking。
- 智能指针速查:Box 单所有者堆分配;Rc 单线程引用计数;Arc 线程安全原子引用计数;Mutex 互斥锁;RwLock 读写锁;RefCell 运行时借用检查;Cell 为 Copy 类型提供内部可变性。
- 常用 trait 实现:为结构体 derive Debug/Clone/PartialEq/Eq/Hash,实现 Default 和 Display。
- 异步运行时比较:Tokio 功能全、生态好;async-std 类似 std API、适合初学者;smol 轻量、依赖少。
- 查阅资源:Rust Book、Rust by Example、Rustonomicon、Async Book、Rust Performance Book、docs.rs。
适用边界 · 注意事项
- 不适用于非 Rust 项目,或不需要内存安全、系统级、高性能优化的普通业务开发。
- 不适用于无法接受严格借用检查/编译期约束,或团队缺乏 unsafe、FFI 代码审查能力的项目。
- 不适用于必须依赖 GC 且不愿进行所有权建模的快速原型/脚本场景。