需要防 rust 帮助:“无法将引用中的数据作为可变数据借用”的问题[duplicate]

k3bvogb1  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(188)

此问题在此处已有答案

How do I create a global, mutable singleton?(7个答案)
3天前关闭。
我是新来的 rust ,不能理解下面的问题。我试图存储的特点,动物的载体。
我的实现如下。

mod TestAnimal {
    use crate::stack;

    pub trait Animal {
        fn diagnose(&self) -> Result<(), stack::service::ServiceError>;
    }

    pub struct Hospital {
        animals: Vec<Box<dyn Animal>>,
    }

    static mut HOSPITAL: Hospital = Hospital { animals: Vec::new() };

    impl Hospital {
        pub fn add_animal(&mut self, animal: Box<dyn Animal>) {
            self.animals.push(animal);
        }
    }

    pub fn get_hospital() -> &'static Hospital {
        unsafe {
            return &HOSPITAL;
        }
    }
}

#[test]
fn test_hospital() {
    pub struct Cat;
    impl TestAnimal::Animal for Cat {
        fn diagnose(&self) -> Result<(), stack::service::ServiceError> {
            return Ok(());
        }
    }

    TestAnimal::get_hospital().add_animal(Box::new(Cat {}));
}

我面临的问题如下。

error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/main.rs:45:5
   |
45 |     TestAnimal::get_hospital().add_animal(Box::new(Cat {}));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
0sgqnhkj

0sgqnhkj1#

看起来您正在尝试变更静态变量。通常这是不安全的,因为多个线程同时编辑一个值可能会导致问题。您可以通过将变量 Package 在mutex中来确保安全。互斥体将确保一次只有一个线程可以变更变量。

mod test_animal {
    use crate::stack;
    use std::sync::Mutex;

    pub trait Animal { 0 implementations
        fn diagnose(&self) -> Result<(), stack::service::ServiceError>;
    }

    pub struct Hospital { 1 implementation
        animals: Vec<Box<dyn Animal + Send>>,
    }

    pub static HOSPITAL: Mutex<Hospital> = Mutex::new(Hospital {
        animals: Vec::new(),
    });

    impl Hospital {
        pub fn add_animal(&mut self, animal: Box<dyn Animal + Send>) {
            self.animals.push(animal);
        }
    }
}

#[test]
fn test_hospital() {
    pub struct Cat;
    impl test_animal::Animal for Cat {
        fn diagnose(&self) -> Result<(), stack::service::ServiceError> {
            return Ok(());
        }
    }

    test_animal::HOSPITAL
        .lock()
        .unwrap()
        .add_animal(Box::new(Cat {}));
}

也就是说,有时你会发现你实际上并不需要静态变量。可变的静态变量通常会让代码更难理解。你可以考虑这样做:

mod test_animal {
    use crate::stack;

    pub trait Animal {
        fn diagnose(&self) -> Result<(), stack::service::ServiceError>;
    }

    pub struct Hospital {
        animals: Vec<Box<dyn Animal + Send>>,
    }

    impl Hospital {
        pub fn new() -> Self {
            Self {
                animals: Vec::new(),
            }
        }

        pub fn add_animal(&mut self, animal: Box<dyn Animal + Send>) {
            self.animals.push(animal);
        }
    }
}

#[test]
fn test_hospital() {
    pub struct Cat;
    impl test_animal::Animal for Cat {
        fn diagnose(&self) -> Result<(), stack::service::ServiceError> {
            return Ok(());
        }
    }

    let mut hospital = test_animal::Hospital::new();
    hospital.add_animal(Box::new(Cat {}));
}

相关问题