rust - 有没有一种方法可以在构造函数中使用锁定的标准输入和输出,使其与您正在构造的结构一样长?

标签 rust stdout stdin lifetime

我正在构建一个 PromptSet可以连续提出一系列问题。出于测试原因,它允许您传递读取器和写入器,而不是直接使用标准输入和标准输出。

因为 stdin 和 stdout 是常见的用例,我想创建一个默认的“构造函数”,允许用户生成 PromptSet<StdinLock, StdoutLock>无需任何参数。到目前为止,这是代码:

use std::io::{self, BufRead, StdinLock, StdoutLock, Write};

pub struct PromptSet<R, W>
where
    R: BufRead,
    W: Write,
{
    pub reader: R,
    pub writer: W,
}

impl<R, W> PromptSet<R, W>
where
    R: BufRead,
    W: Write,
{
    pub fn new(reader: R, writer: W) -> PromptSet<R, W> {
        return PromptSet {
            reader: reader,
            writer: writer,
        };
    }

    pub fn default<'a>() -> PromptSet<StdinLock<'a>, StdoutLock<'a>> {
        let stdin = io::stdin();
        let stdout = io::stdout();

        return PromptSet {
            reader: stdin.lock(),
            writer: stdout.lock(),
        };
    }

    pub fn prompt(&mut self, question: &str) -> String {
        let mut input = String::new();

        write!(self.writer, "{}: ", question).unwrap();
        self.writer.flush().unwrap();
        self.reader.read_line(&mut input).unwrap();

        return input.trim().to_string();
    }
}

fn main() {}

StdinLockStdoutLock两者都需要声明一个生命周期。更复杂的是,我认为原来的stdin()/stdout() Handlebars 至少要和锁一样长。我想要引用 StdinLockStdoutLock和我一样长寿PromptSet确实如此,但无论我尝试什么,我都无法让它工作。这是我不断收到的错误:

error[E0597]: `stdin` does not live long enough
  --> src/main.rs:30:21
   |
30 |             reader: stdin.lock(),
   |                     ^^^^^ borrowed value does not live long enough
...
33 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the method body at 25:5...
  --> src/main.rs:25:5
   |
25 | /     pub fn default<'a>() -> PromptSet<StdinLock<'a>, StdoutLock<'a>> {
26 | |         let stdin = io::stdin();
27 | |         let stdout = io::stdout();
28 | |
...  |
32 | |         };
33 | |     }
   | |_____^

error[E0597]: `stdout` does not live long enough
  --> src/main.rs:31:21
   |
31 |             writer: stdout.lock(),
   |                     ^^^^^^ borrowed value does not live long enough
32 |         };
33 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the method body at 25:5...
  --> src/main.rs:25:5
   |
25 | /     pub fn default<'a>() -> PromptSet<StdinLock<'a>, StdoutLock<'a>> {
26 | |         let stdin = io::stdin();
27 | |         let stdout = io::stdout();
28 | |
...  |
32 | |         };
33 | |     }
   | |_____^

我完全有可能不理解生命周期的概念或其他 super 基础的概念。

最佳答案

lock方法的签名是 fn lock(&self) -> StdinLock ,当使用生命周期注释完全扩展时,它是 fn lock<'a>(&'a self) -> StdinLock<'a> .因此 StdinLock只能活到lock的值方法被调用。由于您定义了 stdin在这个函数中,StdinLock不能超过功能。这与 returning a reference to a local value 相同.你也can't return the reference and the referred-to value together .

您不能这样做,也无法解决它。唯一的解决办法是拥有 default方法采取 Stdin和一个 Stdout对象作为参数。

就是说,您可以解决它。是的,我知道,我刚刚说的恰恰相反,但它更像是“除了我以外没有人会使用标准输入/标准输出”(又名,println! 将不再有效!)

在 Rust 1.26 中,您可以使用 Box::leak 泄漏 Stdin&'static Stdin ,这将产生一个 StdinLock<'static> .在 Rust 1.26 之前,您可以使用 leak crate :

pub fn default() -> PromptSet<StdinLock<'static>, StdoutLock<'static>> {
    let stdin = Box::leak(Box::new(io::stdin()));
    let stdout = Box::leak(Box::new(io::stdout()));

    PromptSet {
        reader: stdin.lock(),
        writer: stdout.lock(),
    }
}

关于rust - 有没有一种方法可以在构造函数中使用锁定的标准输入和输出,使其与您正在构造的结构一样长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41549516/

相关文章:

Rust & Rocket.rs - 构建布局系统

rust - 如何从字符串中解析 i64?

rust - 将 pcap 数据包写入没有文件头的文件

java - 如何在 Android 中打印单元测试的标准输出?

java - 获取进程 STDOUT - Mac OS X

c++ - stderr 和 stdout 的行为不同

bash - 将当前目录中的文件名列表作为单个字符串发送到 Docker 容器的 STDIN

c - 写入另一个程序的标准输入/从 c 中另一个程序的标准输出读取

c++ - 通过输入重定向读取二进制文件 C++ 的最佳方法

rust - 如何在自定义序列化和反序列化中使用 "flatten"之类的东西