一个较小的例子
这是一个MCVE问题的:
fn main() {
let mut prefix = "!";
let mut i = 0;
loop {
let event = String::from("hello");
match i {
0 => prefix = &event,
_ => println!("{}", prefix),
}
i += 1;
}
}
铁锈 2015
error[E0597]: `event` does not live long enough
--> src/main.rs:9:28
|
9 | 0 => prefix = &event,
| ^^^^^ borrowed value does not live long enough
...
14 | }
| - `event` dropped here while still borrowed
15 | }
| - borrowed value needs to live until here
铁锈 2018
error[E0597]: `event` does not live long enough
--> src/main.rs:9:27
|
9 | 0 => prefix = &event,
| ^^^^^^ borrowed value does not live long enough
10 | _ => println!("{}", prefix),
| ------ borrow used here, in later iteration of loop
...
14 | }
| - `event` dropped here while still borrowed
核心问题是event
在每次迭代结束时被丢弃。但是,该代码尝试使用prefix
,参考event
,在后续迭代中。如果允许这种情况发生,您将访问无效内存,从而导致未定义的行为。 Rust 不允许这种情况发生。
您需要更改代码,以便event
(或您需要的部分)比任何一次循环迭代的寿命都长。
应用于原始代码
借用问题的黄金法则是确定谁拥有变量。编译器错误消息可以帮助您:
`message.content` 的寿命不够长
好的,所以我们需要看看message.content
要不就message
。谁拥有它?我们匹配了一个枚举并将所有权转移到一个名为的局部变量message
,所以变量message
is主人:
Ok(Event::MessageCreate(message)) => {
编译器错误消息一致,因为该错误指向其中的块message
是在范围内(实际上是match
由于技术原因而需要大括号):
^ `message.content` dropped here while still borrowed
您正在尝试获取对该字符串的引用并将该引用存储在需要比单个循环迭代更长的时间的地方。编译器已阻止您将内存不安全引入程序中。在其他语言中,您编写此代码,并且在将来的某个时候您的程序会崩溃(最好的情况)或泄漏敏感信息或允许注入代码(最坏的情况)。
相反,分配一个String
循环内。因为它有自己的分配,所以它的寿命可以比message
。您还需要更改原始值的类型prefix
并将调用更改为starts_with
:
let mut prefix = "!".to_string();
loop {
match connection.recv_event() {
Ok(Event::MessageCreate(message)) => {
if message.content.starts_with(&prefix) {
let msg: Vec<_> = message.content[prefix.len()..].split(" ").collect();
// message.content gets split into separate words and is checked for the command
match msg[0] {
"ag3nprefix" => {
prefix = msg[1].to_string();
// ^ here is the line that makes it not compile
let text = format!("AG3N's command prefix changed to: {}", prefix);
let _ = discord.send_message(message.channel_id, &text, "", false);
}
&_ => {}
}
}
}
Ok(_) => {}
Err(discord::Error::Closed(code, body)) => {
println!("Gateway closed on us with code {:?}: {}", code, body);
break;
}
Err(err) => println!("Receive error: {:?}", err),
}
}
let _ = discord.send_message(message.channel_id, &text, "", false);
不要忽略错误。如果你不想处理它,只需添加.expect("I didn't handle this error")
.