第十一篇:Rust 所有权系统

36 阅读14分钟

Rust 所有权系统

Rust 的所有权系统是其最核心、最独特的特性,在编译期保证内存安全,无需垃圾回收器。

目录

  1. 所有权基础
  2. 移动语义(Move)
  3. 借用与引用
  4. 生命周期
  5. 智能指针
  6. 所有权与函数
  7. 所有权与结构体
  8. 实战模式

所有权基础

三大规则

  1. 每个值都有一个所有者(owner)
  2. 同一时刻只能有一个所有者
  3. 所有者离开作用域时,值被丢弃(drop)

1. 栈与堆

fn main() {
    // 栈上分配(已知固定大小)
    let x = 5;              // i32,栈上
    let y = true;           // bool,栈上
    let z = 3.14;           // f64,栈上
    
    // 堆上分配(大小可变或运行时确定)
    let s1 = String::from("hello");     // String,堆上
    let v1 = vec![1, 2, 3];             // Vec,堆上
    let b1 = Box::new(5);               // Box,堆上
    
    println!("栈: {}, {}, {}", x, y, z);
    println!("堆: {}, {:?}, {}", s1, v1, b1);
}

2. 基本所有权示例

fn main() {
    {
        let s = String::from("hello");  // s 进入作用域
        println!("{}", s);               // s 有效
    }  // s 离开作用域,自动调用 drop,内存释放
    
    // println!("{}", s);  // ❌ 错误:s 已失效
}

3. 所有权转移(Move)

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // s1 的所有权移动到 s2
    
    println!("{}", s2);  // ✅ 正确
    // println!("{}", s1);  // ❌ 错误:s1 已失效
}
为什么会移动?
// 内部机制(简化版)
struct String {
    ptr: *mut u8,      // 指向堆内存的指针
    len: usize,        // 长度
    capacity: usize,   // 容量
}

// 当执行 let s2 = s1 时:
// 1. 复制栈上的数据(ptr、len、capacity)
// 2. s1 失效,防止双重释放(double free)

4. 克隆(Clone)- 深拷贝

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();  // 深拷贝,堆内存也被复制
    
    println!("s1 = {}, s2 = {}", s1, s2);  // ✅ 两个都有效
}

5. 拷贝(Copy)- 栈上数据

fn main() {
    // 实现了 Copy trait 的类型会自动复制
    let x = 5;
    let y = x;  // 复制(不是移动)
    
    println!("x = {}, y = {}", x, y);  // ✅ 两个都有效
    
    // Copy trait 的类型:
    // - 所有整数类型:i32, u64, etc.
    // - 布尔类型:bool
    // - 浮点类型:f64, f32
    // - 字符类型:char
    // - 元组(如果所有元素都是 Copy)
    // - 数组(如果元素是 Copy)
}
Copy vs Clone
// Copy - 隐式、廉价、栈上
let x = 5;
let y = x;  // 自动复制

// Clone - 显式、可能昂贵、可能涉及堆
let s1 = String::from("hello");
let s2 = s1.clone();  // 显式调用

移动语义

1. 移动的本质

fn main() {
    let s1 = String::from("hello");
    
    // 移动发生在:
    let s2 = s1;              // 1. 赋值
    take_ownership(s2);       // 2. 传参
    // let s3 = return_string(); // 3. 返回值
    
    // s1 和 s2 都已失效
}

fn take_ownership(s: String) {
    println!("{}", s);
}  // s 在这里被 drop

2. 部分移动

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn main() {
    let person = Person {
        name: String::from("Alice"),
        age: 25,
    };
    
    // 部分移动
    let name = person.name;  // name 被移动
    let age = person.age;    // age 被复制(u32 是 Copy)
    
    // println!("{:?}", person);  // ❌ 错误:person.name 已移动
    println!("age: {}", age);     // ✅ 正确
    println!("name: {}", name);   // ✅ 正确
}

3. 移动与集合

fn main() {
    let v = vec![
        String::from("hello"),
        String::from("world"),
    ];
    
    // 索引访问会尝试移动
    // let s = v[0];  // ❌ 错误:不能移出索引
    
    // 解决方案1:克隆
    let s1 = v[0].clone();
    
    // 解决方案2:借用
    let s2 = &v[0];
    
    // 解决方案3:获取所有权(消耗 Vec)
    let mut v = v;
    let s3 = v.remove(0);
    
    println!("{}, {}, {}", s1, s2, s3);
}

4. 移动与闭包

fn main() {
    let data = String::from("hello");
    
    // 闭包捕获所有权
    let closure = || {
        println!("{}", data);  // data 被借用
    };
    
    closure();
    println!("{}", data);  // ✅ data 仍然有效
    
    // 使用 move 强制移动
    let data2 = String::from("world");
    let closure2 = move || {
        println!("{}", data2);  // data2 被移动
    };
    
    closure2();
    // println!("{}", data2);  // ❌ 错误:data2 已移动
}

借用与引用

1. 不可变借用(&T)

fn main() {
    let s1 = String::from("hello");
    
    let len = calculate_length(&s1);  // 借用 s1
    
    println!("'{}' 的长度是 {}", s1, len);  // s1 仍然有效
}

fn calculate_length(s: &String) -> usize {
    s.len()
}  // s 离开作用域,但不会 drop,因为没有所有权
借用规则图示
所有者: s1 ──┐
             
             ├──> 借用1: &s1
             ├──> 借用2: &s1
             └──> 借用3: &s1
             
可以同时存在多个不可变借用

2. 可变借用(&mut T)

fn main() {
    let mut s = String::from("hello");
    
    change(&mut s);
    
    println!("{}", s);  // "hello, world"
}

fn change(s: &mut String) {
    s.push_str(", world");
}

3. 借用规则

核心规则:

  • ✅ 可以有任意数量的不可变借用
  • ✅ 可以有一个可变借用
  • ❌ 不可变借用和可变借用不能同时存在
fn main() {
    let mut s = String::from("hello");
    
    // ✅ 多个不可变借用
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);
    // r1 和 r2 在这之后不再使用
    
    // ✅ 一个可变借用
    let r3 = &mut s;
    r3.push_str(" world");
    println!("{}", r3);
}

4. 借用作用域(NLL - Non-Lexical Lifetimes)

fn main() {
    let mut s = String::from("hello");
    
    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);
    // r1 和 r2 的作用域在这里结束(最后一次使用)
    
    let r3 = &mut s;  // ✅ 正确:r1 和 r2 已不再使用
    r3.push_str(" world");
    println!("{}", r3);
}

5. 悬垂引用(Dangling Reference)

// ❌ 错误示例
fn dangle() -> &String {
    let s = String::from("hello");
    &s  // 错误:返回对局部变量的引用
}  // s 被 drop,引用指向无效内存

// ✅ 正确方式1:返回所有权
fn no_dangle1() -> String {
    let s = String::from("hello");
    s  // 移动所有权
}

// ✅ 正确方式2:使用生命周期参数
fn no_dangle2(s: &String) -> &String {
    s  // 返回传入的引用
}

6. 引用与解引用

fn main() {
    let x = 5;
    let y = &x;  // y 是 x 的引用
    
    // 解引用
    assert_eq!(5, x);
    assert_eq!(5, *y);  // *y 解引用,获取值
    
    // 自动解引用
    let s = String::from("hello");
    let r = &s;
    println!("长度: {}", r.len());  // 自动解引用调用方法
}

生命周期

1. 生命周期基础

生命周期是引用有效的作用域。

fn main() {
    let r;                    // ---------+-- 'a
                              //          |
    {                         //          |
        let x = 5;            // -+-- 'b  |
        r = &x;               //  |       |
    }                         // -+       |
                              //          |
    // println!("{}", r);     // ❌ 错误:x 已失效
}                             // ---------+

2. 函数中的生命周期标注

// 生命周期标注语法
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

fn main() {
    let string1 = String::from("long string");
    let string2 = String::from("xyz");
    
    let result = longest(string1.as_str(), string2.as_str());
    println!("最长的字符串是 {}", result);
}
生命周期标注含义
// 'a 表示返回值的生命周期至少与参数中较短的那个一样长
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    // 返回值的生命周期 = min(x 的生命周期, y 的生命周期)
}

3. 生命周期省略规则

编译器可以自动推断生命周期的情况:

// 规则1:每个引用参数都有自己的生命周期
fn foo(x: &str) -> &str { x }
// 等价于
fn foo<'a>(x: &'a str) -> &'a str { x }

// 规则2:如果只有一个输入生命周期,赋给所有输出
fn first_word(s: &str) -> &str {
    s.split_whitespace().next().unwrap()
}

// 规则3:如果有 &self 或 &mut self,生命周期赋给所有输出
impl MyStruct {
    fn get_data(&self) -> &str {
        &self.data
    }
}

struct MyStruct {
    data: String,
}

4. 结构体中的生命周期

// 结构体包含引用必须标注生命周期
struct ImportantExcerpt<'a> {
    part: &'a str,
}

impl<'a> ImportantExcerpt<'a> {
    fn level(&self) -> i32 {
        3
    }
    
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("注意: {}", announcement);
        self.part
    }
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    
    let excerpt = ImportantExcerpt {
        part: first_sentence,
    };
    
    println!("摘录: {}", excerpt.part);
}

5. 静态生命周期('static)

// 'static 生命周期持续整个程序
let s: &'static str = "硬编码的字符串";

// 字符串字面量都是 'static
fn get_static_str() -> &'static str {
    "hello"
}

// 有时需要显式标注
static GLOBAL: &str = "全局变量";

6. 多个生命周期参数

// 不同参数可以有不同生命周期
fn complex<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
    println!("y = {}", y);
    x  // 只返回 x
}

fn main() {
    let string1 = String::from("hello");
    
    {
        let string2 = String::from("world");
        let result = complex(&string1, &string2);
        println!("{}", result);
    }  // string2 可以在这里释放
}

智能指针

1. Box - 堆分配

fn main() {
    // 将值放在堆上
    let b = Box::new(5);
    println!("b = {}", b);
    
    // 递归类型必须使用 Box
    #[derive(Debug)]
    enum List {
        Cons(i32, Box<List>),
        Nil,
    }
    
    use List::{Cons, Nil};
    
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    println!("{:?}", list);
}

2. Rc - 引用计数

use std::rc::Rc;

fn main() {
    let a = Rc::new(String::from("hello"));
    println!("引用计数: {}", Rc::strong_count(&a));  // 1
    
    let b = Rc::clone(&a);
    println!("引用计数: {}", Rc::strong_count(&a));  // 2
    
    {
        let c = Rc::clone(&a);
        println!("引用计数: {}", Rc::strong_count(&a));  // 3
    }
    
    println!("引用计数: {}", Rc::strong_count(&a));  // 2
    
    println!("值: {}", a);
}

3. Arc - 原子引用计数(线程安全)

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(vec![1, 2, 3]);
    let mut handles = vec![];
    
    for i in 0..3 {
        let data = Arc::clone(&data);
        let handle = thread::spawn(move || {
            println!("线程 {}: {:?}", i, data);
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
}

4. RefCell - 内部可变性

use std::cell::RefCell;

fn main() {
    let data = RefCell::new(5);
    
    // 运行时借用检查
    {
        let mut borrow = data.borrow_mut();
        *borrow += 1;
    }  // 可变借用在这里结束
    
    println!("值: {}", data.borrow());  // 6
}

// 结合 Rc 实现共享可变性
use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug)]
struct Node {
    value: i32,
    next: Option<Rc<RefCell<Node>>>,
}

fn main() {
    let node1 = Rc::new(RefCell::new(Node {
        value: 1,
        next: None,
    }));
    
    let node2 = Rc::new(RefCell::new(Node {
        value: 2,
        next: Some(Rc::clone(&node1)),
    }));
    
    println!("{:?}", node2);
}

5. Mutex 和 RwLock

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("结果: {}", *counter.lock().unwrap());
}

所有权与函数

1. 参数传递

fn main() {
    let s = String::from("hello");
    
    // 移动所有权
    takes_ownership(s);
    // println!("{}", s);  // ❌ 错误:s 已失效
    
    let x = 5;
    
    // 复制
    makes_copy(x);
    println!("{}", x);  // ✅ 正确:x 仍然有效
}

fn takes_ownership(some_string: String) {
    println!("{}", some_string);
}  // some_string 被 drop

fn makes_copy(some_integer: i32) {
    println!("{}", some_integer);
}  // 无特殊操作

2. 返回值与所有权

fn main() {
    let s1 = gives_ownership();
    println!("{}", s1);
    
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
    println!("{}", s3);
    // println!("{}", s2);  // ❌ 错误:s2 已移动
}

fn gives_ownership() -> String {
    let some_string = String::from("yours");
    some_string  // 移动给调用者
}

fn takes_and_gives_back(a_string: String) -> String {
    a_string  // 移动给调用者
}

3. 返回多个值

fn main() {
    let s1 = String::from("hello");
    
    let (s2, len) = calculate_length(s1);
    
    println!("'{}' 的长度是 {}", s2, len);
}

fn calculate_length(s: String) -> (String, usize) {
    let length = s.len();
    (s, length)  // 返回元组
}

4. 使用引用避免所有权转移

fn main() {
    let s1 = String::from("hello");
    
    let len = calculate_length(&s1);
    
    println!("'{}' 的长度是 {}", s1, len);  // s1 仍然有效
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

所有权与结构体

1. 所有权结构体

struct User {
    username: String,    // 拥有所有权
    email: String,       // 拥有所有权
    sign_in_count: u64,  // Copy 类型
    active: bool,        // Copy 类型
}

fn main() {
    let user1 = User {
        username: String::from("user1"),
        email: String::from("user1@example.com"),
        sign_in_count: 1,
        active: true,
    };
    
    // 部分移动
    let username = user1.username;
    // println!("{:?}", user1);  // ❌ 错误:username 已移动
    println!("{}", username);    // ✅ 正确
}

2. 引用结构体

// 需要生命周期标注
struct UserRef<'a> {
    username: &'a str,
    email: &'a str,
}

fn main() {
    let username = String::from("user1");
    let email = String::from("user1@example.com");
    
    let user = UserRef {
        username: &username,
        email: &email,
    };
    
    println!("{}, {}", user.username, user.email);
}

3. 方法中的所有权

struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 不可变借用 self
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    // 可变借用 self
    fn scale(&mut self, factor: u32) {
        self.width *= factor;
        self.height *= factor;
    }
    
    // 获取所有权(消费 self)
    fn into_tuple(self) -> (u32, u32) {
        (self.width, self.height)
    }
}

fn main() {
    let mut rect = Rectangle { width: 30, height: 50 };
    
    println!("面积: {}", rect.area());
    
    rect.scale(2);
    println!("缩放后面积: {}", rect.area());
    
    let (w, h) = rect.into_tuple();
    println!("宽: {}, 高: {}", w, h);
    // println!("{}", rect.area());  // ❌ 错误:rect 已被消费
}

实战模式

1. 构建器模式(Builder Pattern)

struct User {
    username: String,
    email: String,
    age: u32,
}

struct UserBuilder {
    username: Option<String>,
    email: Option<String>,
    age: Option<u32>,
}

impl UserBuilder {
    fn new() -> Self {
        Self {
            username: None,
            email: None,
            age: None,
        }
    }
    
    // 接受所有权并返回自身
    fn username(mut self, username: String) -> Self {
        self.username = Some(username);
        self
    }
    
    fn email(mut self, email: String) -> Self {
        self.email = Some(email);
        self
    }
    
    fn age(mut self, age: u32) -> Self {
        self.age = Some(age);
        self
    }
    
    fn build(self) -> User {
        User {
            username: self.username.expect("username required"),
            email: self.email.expect("email required"),
            age: self.age.unwrap_or(0),
        }
    }
}

fn main() {
    let user = UserBuilder::new()
        .username(String::from("alice"))
        .email(String::from("alice@example.com"))
        .age(25)
        .build();
    
    println!("用户: {}, {}, {}", user.username, user.email, user.age);
}

2. 缓存模式(Cache-Aside)

use std::collections::HashMap;

struct Cache {
    data: HashMap<String, String>,
}

impl Cache {
    fn new() -> Self {
        Self {
            data: HashMap::new(),
        }
    }
    
    // 借用 self,不转移所有权
    fn get(&self, key: &str) -> Option<&String> {
        self.data.get(key)
    }
    
    // 可变借用 self
    fn set(&mut self, key: String, value: String) {
        self.data.insert(key, value);
    }
    
    // 接受所有权
    fn insert_owned(&mut self, key: String, value: String) {
        self.data.insert(key, value);
    }
    
    // 借用参数
    fn insert_borrowed(&mut self, key: &str, value: &str) {
        self.data.insert(key.to_string(), value.to_string());
    }
}

fn main() {
    let mut cache = Cache::new();
    
    cache.set(String::from("key1"), String::from("value1"));
    cache.insert_borrowed("key2", "value2");
    
    if let Some(value) = cache.get("key1") {
        println!("找到: {}", value);
    }
}

3. 资源管理(RAII)

use std::fs::File;
use std::io::Write;

struct FileWriter {
    file: File,
}

impl FileWriter {
    fn new(path: &str) -> std::io::Result<Self> {
        let file = File::create(path)?;
        Ok(Self { file })
    }
    
    fn write(&mut self, data: &str) -> std::io::Result<()> {
        self.file.write_all(data.as_bytes())
    }
}

impl Drop for FileWriter {
    fn drop(&mut self) {
        println!("文件被关闭");
    }
}

fn main() -> std::io::Result<()> {
    {
        let mut writer = FileWriter::new("test.txt")?;
        writer.write("Hello, World!")?;
    }  // writer 在这里自动关闭文件
    
    Ok(())
}

4. 本项目实际应用

服务层所有权管理
// src/services/user_service.rs
pub struct UserService {
    db: MySqlPool,        // 拥有连接池
    cache: RedisCache,    // 拥有缓存客户端
}

impl UserService {
    // 获取所有权
    pub fn new(db: MySqlPool, cache: RedisCache) -> Self {
        Self { db, cache }
    }

    // 借用 self,不转移所有权
    pub async fn create_user(&self, payload: CreateUserRequest) -> Result<User> {
        // payload 的所有权被转移
        let password_hash = format!("hashed_{}", payload.password);
        
        let result = sqlx::query!(
            "INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)",
            payload.username,
            payload.email,
            password_hash
        )
        .execute(&self.db)  // 借用 db
        .await?;
        
        let user_id = result.0 as i64;
        
        // 查询创建的用户
        let user = sqlx::query_as!(
            User,
            "SELECT id, username, email, password_hash, created_at, updated_at FROM users WHERE id = ?",
            user_id
        )
        .fetch_one(&self.db)
        .await?;
        
        // 缓存(借用字段)
        let cache_key = format!("user:{}", user.id);
        let user_json = serde_json::to_string(&user)?;
        self.cache.set(&cache_key, &user_json, 3600).await?;
        
        Ok(user)  // 移动所有权给调用者
    }

    // 返回 Option,可能没有所有权
    pub async fn get_user(&self, user_id: i64) -> Result<Option<User>> {
        let cache_key = format!("user:{}", user_id);
        
        // 先查缓存
        if let Ok(Some(cached)) = self.cache.get_typed::<User>(&cache_key).await {
            return Ok(Some(cached));  // 返回缓存的值
        }
        
        // 查数据库
        let user = sqlx::query_as!(
            User,
            "SELECT id, username, email, password_hash, created_at, updated_at FROM users WHERE id = ?",
            user_id
        )
        .fetch_optional(&self.db)
        .await?;
        
        // 写入缓存
        if let Some(ref u) = user {
            let user_json = serde_json::to_string(u)?;
            let _ = self.cache.set(&cache_key, &user_json, 3600).await;
        }
        
        Ok(user)
    }
}
控制器所有权管理
// src/controllers/user_controller.rs
pub async fn create_user(
    State(state): State<AppState>,  // 克隆 AppState
    Json(payload): Json<CreateUserRequest>,  // payload 所有权转移
) -> Result<Json<UserResponse>, (StatusCode, String)> {
    // 创建 UserService(获取所有权)
    let service = UserService::new(state.db, state.cache);
    
    // 调用服务(payload 所有权转移)
    match service.create_user(payload).await {
        Ok(user) => {
            let response = UserResponse {
                id: user.id,
                username: user.username,
                email: user.email,
                created_at: user.created_at,
                updated_at: user.updated_at,
            };
            Ok(Json(response))  // 移动所有权
        }
        Err(e) => Err((
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("创建用户失败: {}", e),
        )),
    }
}
应用状态克隆
// src/config/app_state.rs
#[derive(Clone)]
pub struct AppState {
    pub db: MySqlPool,      // MySqlPool 实现了 Clone(内部是 Arc)
    pub cache: RedisCache,  // RedisCache 实现了 Clone
}

impl AppState {
    pub fn new(db: MySqlPool, cache: RedisCache) -> Self {
        Self { db, cache }
    }
}

// 在路由中使用
let app = Router::new()
    .route("/api/users", post(create_user))
    .with_state(state);  // state 被移动到路由

常见陷阱与解决方案

1. 忘记所有权已转移

// ❌ 错误
fn main() {
    let s = String::from("hello");
    let s2 = s;
    println!("{}", s);  // 编译错误:s 已移动
}

// ✅ 解决方案1:克隆
fn main() {
    let s = String::from("hello");
    let s2 = s.clone();
    println!("{} and {}", s, s2);
}

// ✅ 解决方案2:使用引用
fn main() {
    let s = String::from("hello");
    let s2 = &s;
    println!("{} and {}", s, s2);
}

2. 借用规则冲突

// ❌ 错误
fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    let r2 = &mut s;  // 错误:不可变借用存在时不能可变借用
    println!("{}, {}", r1, r2);
}

// ✅ 解决方案:确保借用不重叠
fn main() {
    let mut s = String::from("hello");
    let r1 = &s;
    println!("{}", r1);
    // r1 不再使用
    
    let r2 = &mut s;
    r2.push_str(" world");
    println!("{}", r2);
}

3. 返回局部变量的引用

// ❌ 错误
fn dangle() -> &String {
    let s = String::from("hello");
    &s  // 错误:s 被 drop
}

// ✅ 解决方案:返回所有权
fn no_dangle() -> String {
    let s = String::from("hello");
    s
}

4. 循环引用

use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug)]
struct Node {
    next: Option<Rc<RefCell<Node>>>,
}

// ❌ 可能导致内存泄漏
fn create_cycle() {
    let a = Rc::new(RefCell::new(Node { next: None }));
    let b = Rc::new(RefCell::new(Node { next: Some(Rc::clone(&a)) }));
    a.borrow_mut().next = Some(Rc::clone(&b));
    // a -> b -> a 循环引用
}

// ✅ 解决方案:使用 Weak
use std::rc::Weak;

#[derive(Debug)]
struct NodeWeak {
    next: Option<Rc<RefCell<NodeWeak>>>,
    prev: Option<Weak<RefCell<NodeWeak>>>,  // 使用 Weak 打破循环
}

总结

核心概念速查

概念说明示例
所有权每个值有唯一所有者let s = String::from("hello");
移动转移所有权let s2 = s;
克隆深拷贝let s2 = s.clone();
拷贝栈上自动复制let y = x; (i32)
借用引用,不获取所有权&s / &mut s
生命周期引用有效期'a

借用规则

1. 同一时刻,要么有一个可变借用,要么有任意多个不可变借用
2. 引用必须总是有效的(不能悬垂)

智能指针选择

类型用途线程安全
Box<T>堆分配
Rc<T>共享所有权
Arc<T>共享所有权
RefCell<T>内部可变性
Mutex<T>互斥锁

何时使用什么?

// 需要所有权:参数类型为 T
fn take_ownership(s: String) { }

// 只读访问:参数类型为 &T
fn borrow(s: &String) { }

// 修改数据:参数类型为 &mut T
fn borrow_mut(s: &mut String) { }

// 返回引用:需要生命周期标注
fn return_ref<'a>(s: &'a String) -> &'a str { }

// 共享所有权:使用 Rc/Arc
let shared = Rc::new(data);

本项目最佳实践

  1. ✅ 服务层持有连接池和缓存(所有权)
  2. ✅ 方法使用 &self 借用(避免所有权转移)
  3. ✅ DTO 通过移动传递(CreateUserRequest)
  4. ✅ 连接池使用 Clone(内部 Arc)
  5. ✅ 异步函数返回 Result<T>(明确所有权)

延伸阅读