Rust 为什么需要可变和额外的作用域

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(

我想打印出传递给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();

            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