我正在开发一个数据管道节点,一个应用程序从 stdin
获取持续供应的数据,对其进行处理,并将结果连续输出到 stdout
流媒体时尚。
考虑到数据交换格式是预先确定的,我需要一种方便的方法来禁止我的调试输出同时馈送到标准输出。本质上,一个全局锁。的确,我可以去掉所有的调试语句,但这更像是一种学术练习。
所以让我们创建一个可以写入 stdout
的函数,并锁定 stdout
只要它仍在范围内,这样类型系统本身就会阻止其他地方写入 stdout
的代码:
use std::io::{self, Write};
pub fn make_push_output<'a>() -> &'a impl Fn(String) -> io::Result<()> {
let handle = io::stdout().lock();
&|output: String| {
handle.write(output.to_string().as_bytes())?;
Ok(())
}
}
很酷,对 stdout
的全局锁定会一直保持到位,直到输出 push_output()
函数超出范围,但它不起作用。我得到了一个完整的借用检查器错误列表:
error[E0597]: borrowed value does not live long enough
--> src/lib.rs:4:18
|
4 | let handle = io::stdout().lock();
| ^^^^^^^^^^^^ - temporary value only lives until here
| |
| temporary value does not live long enough
|
= note: borrowed value must be valid for the static lifetime...
error[E0597]: borrowed value does not live long enough
--> src/lib.rs:6:6
|
6 | &|output: String| {
| ______^
7 | | handle.write(output.to_string().as_bytes())?;
8 | |
9 | | Ok(())
10 | | }
| |_____^ temporary value does not live long enough
11 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 3:25...
--> src/lib.rs:3:25
|
3 | pub fn make_push_output<'a>() -> &'a impl Fn(String) -> io::Result<()> {
| ^^
error[E0373]: closure may outlive the current function, but it borrows `handle`, which is owned by the current function
--> src/lib.rs:6:6
|
6 | &|output: String| {
| ^^^^^^^^^^^^^^^^ may outlive borrowed value `handle`
7 | handle.write(output.to_string().as_bytes())?;
| ------ `handle` is borrowed here
help: to force the closure to take ownership of `handle` (and any other referenced variables), use the `move` keyword
|
6 | &move |output: String| {
| ^^^^^^^^^^^^^^^^^^^^^
error[E0387]: cannot borrow data mutably in a captured outer variable in an `Fn` closure
--> src/lib.rs:7:9
|
7 | handle.write(output.to_string().as_bytes())?;
| ^^^^^^
|
help: consider changing this closure to take self by mutable reference
--> src/lib.rs:6:6
|
6 | &|output: String| {
| ______^
7 | | handle.write(output.to_string().as_bytes())?;
8 | |
9 | | Ok(())
10| | }
| |_____^
我已经尝试了一个多小时来修复这 7 行代码中的这一系列借用检查器错误。以下是我迄今为止所采取但未奏效的步骤的非详尽列表:
- 更改
make_push_output
的生命周期 - 为
句柄
添加显式类型和生命周期注解 - 为
io::stdout()
声明一个变量并用类型和生命周期进行注释 - 为闭包添加明确的类型和生命周期注释
- 声明一个本地函数而不是使用闭包,无法捕获环境
- 在闭包上使用
move
语义,不是最明智的举动,但我正在捕获救命稻草
最佳答案
你不能。标准输出锁是reentrant :
use std::io::{self, Write};
fn main() {
let out = io::stdout();
let mut handle = out.lock();
writeln!(handle, "handle: {}", 1);
println!("Debugging output");
writeln!(handle, "handle: {}", 2);
drop(handle)
}
这打印:
handle: 1
Debugging output
handle: 2
再多的类型调整也无法阻止同一个线程重新获取标准输出/错误锁并在输出中间进行打印。
您的编译器错误通过以下方式解决:
- 返回一个
& impl ...
- 尝试返回
stdout
和它的锁
关于rust - 如何使用 Rust 类型系统来防止输出到标准输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53230295/