如果我以这种方式生成10个随机数,它会起作用(它会产生不同的值)

fn main() {
    let seed = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .expect("system time cannot be before unix epoch")
        .as_millis() as u64;

    let mut rng = oorandom::Rand32::new(seed);

    for _ in 0..10 {
        println!("Your random number is: {}", &rng.rand_range(0..4));
    }

但是,如果我将它们分解到一个 struct 中,生成的值总是相同的:

use oorandom::{self, Rand32};

struct Util {
    rng: Rand32,
}
impl Util {
    pub fn new() -> Self {
        let seed = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap()
            .as_millis() as u64;
        println!("new color util {}", seed);
        let rng = Rand32::new(seed);
        Util { rng }
    }
    pub fn get_random(&self) -> u32 {
        let mut rng = self.rng;
        let random_number = rng.rand_range(0..4);
        random_number
    }
}

fn main() {
    let util = Util::new();
    for _ in 0..10 {
        println!("Your random number is: {}", util.get_random());
    }
}

这两种使用get_randomAPI的方式有什么不同,为什么当我将rng放在 struct 中时它会中断?

推荐答案

这不起作用,因为您正在将rng从 struct 中复制出来,然后对其进行变异(注册您已经采样了一个数字):

impl Util {
    pub fn get_random(&self) -> u32 {
        let mut rng = self.rng;  // <-- here you copy `rng`,
                                 // creating a new value, unrelated with `self.rng`
        let random_number = rng.rand_range(0..4); // <-- here you mutate `rng`,
        random_number                             // but leave `self.rng` untouched
    }
}

相反,你必须取mutable borrowself才能在适当的位置变异rng:

impl Util {
    pub fn get_random(&mut self) -> u32 {
        //             +++ `mut` has been added, to allow mutation of `self`
        let rng = &mut self.rng;  // this does not copy `self.rng`
        let random_number = rng.rand_range(0..4);
        random_number
    }
}

或者,更简短地说

impl Util {
    pub fn get_random(&mut self) -> u32 {
        let random_number = self.rng.rand_range(0..4);
        random_number
    }
}

甚至是

impl Util {
    pub fn get_random(&mut self) -> u32 {
        self.rng.rand_range(0..4)
    }
}

Rust相关问答推荐

什么样的 struct 可以避免使用RefCell?

抽象RUST中的可变/不可变引用

如何获取Serde struct 的默认实例

如何指定不同的类型来常量Rust中的泛型参数?

如何将像烫手山芋一样不透明的值从一个Enum构造函数移动到下一个构造函数?

取得本地对象字段的所有权

创建Rust中元对象协议的动态对象 Select /重新分配机制

在macro_rule中拆分模块和函数名

使用Rust WASM读取文件

Rust 中指向自身的引用如何工作?

如何为整数切片定义一个带有额外函数的特性别名?

push 方法是否取得所有权?

Some(v) 和 Some(&v) 有什么区别?

如何在 use_effect_with_deps 中设置监听器内的状态?

从现有系列和 map 值创建新系列

在 Rust 中为泛型 struct 编写一次特征绑定

覆盖类型的要求到底是什么?为什么单个元素元组满足它?

使用 rust-sqlx/tokio 时如何取消长时间运行的查询

守卫如何影响匹配语句?

如何在 Rust 中使用特征标志来捕获多行代码?