Rust 为什么需要可变和额外的作用域
我想打印出传递给FastCGI应用程序的参数:Rust 为什么需要可变和额外的作用域,rust,Rust,我想打印出传递给FastCGI应用程序的参数: extern crate fastcgi; // 1.0.0 use std::io::Write; fn main() { fastcgi::run(|mut req| { let mut output = String::from("Content-Type: text/plain\n\n"); { let mut params = req.params(
extern crate fastcgi; // 1.0.0
use std::io::Write;
fn main() {
fastcgi::run(|mut req| {
let mut output = String::from("Content-Type: text/plain\n\n");
{
let mut params = req.params();
loop {
let param = params.next();
match param {
Some(t) => output.push_str(&format!("{:?}", t)),
None => break,
}
}
}
write!(&mut req.stdout(), "{}", &output).unwrap_or(());
});
}
我的代码可以工作,但我不明白为什么我需要这样做。我的直觉是我可以写这个不工作的代码:
extern板条箱fastcgi;//1.0.0
使用std::io::Write;
fn main(){
fastcgi::run(| mut req |{
让mut output=String::from(“内容类型:text/plain\n\n”);
设mut params=req.params();
环路{
设param=params.next();
匹配参数{
Some(t)=>output.push_str(&format!(“{:?}”,t)),
无=>中断,
}
}
write!(&mut-req.stdout(),“{}”和&output);
});
}
编译器输出:
error[E0502]:无法将'req'作为可变项借用,因为它也是作为不可变项借用的
-->src/main.rs:16:21
|
8 |设mut params=req.params();
|---此处发生不可变借用
...
16 |写!(&mut-req.stdout(),“{}”和&output);
|^^^^^^^^^^^^^^^^此处发生可变借用
17 | });
|-当删除'params'并运行'std::boxed::Box'类型的析构函数时,此处可能会使用不可变借用`
我通过谷歌搜索和遵循编译器的建议找到了解决方案,但我不明白为什么有必要这样做。如果你看一下它的定义,它的定义是:
pub fn params(&self) -> Params
这看起来很简单,因为Params
具有隐藏的生存期。实际上,它是为了:
pub fn params<'s>(&'s self) -> Params<'s>
pub fn stdout<'s>(&'s mut self) -> Stdout<'s>
此方法借用对象可变,您可能知道,不能同时可变和不可变借用同一对象
编写额外的作用域会限制params
的使用寿命,并在调用stdout
之前释放借用,因此它们的使用寿命不会重叠,代码也会编译
如果您不喜欢额外的缩进级别,也可以编写:
drop(params);
循环结束后,手动完成params
的生命周期
您可能认为
params()
和stdout()
在内部没有任何共同之处,您应该能够同时可变地使用它们。您可能是对的,但编译器并不在意,它只看到这些函数是如何定义的,而不是它们在内部做什么。如果您查看它的定义,它的定义是:
pub fn params(&self) -> Params
这看起来很简单,因为Params
具有隐藏的生存期。实际上,它是为了:
pub fn params<'s>(&'s self) -> Params<'s>
pub fn stdout<'s>(&'s mut self) -> Stdout<'s>
此方法借用对象可变,您可能知道,不能同时可变和不可变借用同一对象
编写额外的作用域会限制params
的使用寿命,并在调用stdout
之前释放借用,因此它们的使用寿命不会重叠,代码也会编译
如果您不喜欢额外的缩进级别,也可以编写:
drop(params);
循环结束后,手动完成params
的生命周期
您可能认为
params()
和stdout()
在内部没有任何共同之处,您应该能够同时可变地使用它们。您可能是对的,但编译器并不在意,它只看到这些函数是如何定义的,而不知道它们在内部做什么。当删除params
并运行类型的析构函数时,这里可能会使用不可变借用-似乎编译器已经在向您解释问题了您可能想要在req.params()中对t使用{output.push_str(&format!(“{:?}”,t));}
我必须做什么,如果我使用&
它仍然不起作用,参数将不会被删除。这里可能使用不可变的借用,当删除params
并运行类型的析构函数时-似乎编译器已经在向您解释问题了您可能希望在req.params(){output.push_str(&format!(“{:?}”,t));}
我必须做什么,如果我使用&
它仍然不起作用,参数
不会被删除。可能是fastcgi机箱过于保守Params
,这意味着(1)它实现了Drop
,(2)Drop
实现可能使用'a
。如果Params
,它也会编译,因为&str
不是Drop
,而在Vec
中的Drop
实现T
是.[may\u dangle]
@trentcl:很好的解释,Drop checker总是很难理解。当然,如果你想要一个向量机,那么fastcgi机箱可能过于保守Params
,这意味着(1)它实现了Drop
,(2)Drop
实现可能使用'a
。如果Params
,它也会编译,因为&str
不是Drop
,而在Vec
中的Drop
实现T
是.[may\u dangle]
@trentcl:很好的解释,Drop checker总是很难理解。当然,如果你想要一个Vec