如何使用Rust类型的系统来防止输出到stdout?

时间:2018-11-09 17:04:31

标签: rust locking lifetime borrow-checker borrowing

我正在研究数据流水线节点,该应用程序从stdin连续获取数据,进行处理,然后以流方式将结果连续输出到stdout

考虑到数据交换格式是预先确定的,我需要一种方便的方法来禁止调试输出同时馈入到stdout。本质上是全局锁定。没错,我可以摆脱所有调试语句,但这更多是学术性的练习。

因此,让我们创建一个可以写入stdout并锁定stdout的函数,只要它保留在范围内,这样类型系统本身就可以防止代码中的其他位置写入{ {1}}

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()

我已经尝试了一个多小时,以解决这7行代码中的借位检查器错误序列。这是到目前为止我没有采取的步骤的详尽列表:

  • 更改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| | } | |_____^ 的生存期
  • make_push_output添加显式类型和生存期批注
  • handle声明一个变量,并使用类型和生存期进行注释
  • 向闭包添加显式类型和生命周期批注
  • 声明局部函数而不使用闭包,无法捕获环境
  • 在闭包上使用io::stdout()语义,不是最明智的举动,但我正在抓住稻草

1 个答案:

答案 0 :(得分:3)

您不能。标准输出锁定为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

没有任何类型的杂耍可以阻止同一线程重新获得对标准输出/错误的锁定并在输出的中间进行打印。


您的编译器错误的解决方法: