什么是在函数之间传递时惯用的方式引用BufReader/BufWriter?

ide*_*n42 8 io rust

在阅读了std :: io :: BufReader文档之后,我不确定如何最好地在std::io::BufReader两个函数之间传递.允许多个排列,但哪个最好?

我有一个带文件的函数:

use std::{fs::File, io::BufReader};

fn write_some_data(f: &mut std::fs::File) {
    let mut reader = BufReader::new(f);
    write_some_other_data(&mut reader);
}
Run Code Online (Sandbox Code Playgroud)

虽然这可以使用,但在将阅读器传递给其他功能时应该使用哪种参考访问的排列?

  • BufReader
  • &mut BufReader<&mut File>
  • BufReader<&mut File>
  • &mut BufReader<File>

由于不需要每个函数拥有数据,我认为最好传递as BufReader<File>,但文档中的示例使用&mut BufReader<&mut File>.

这是一个很好的经验法则吗?

虽然这个例子使用<File>,但我认为同样的答案也适用BufReader.

Lin*_*ope 15

最惯用的方式可能根本就没有参考std::io::BufReader.你实际上想要引用特征Read和/或BufRead

use std::io:BufRead;

// Could also take by move if needed
fn read_data<R: BufRead>(r: &mut R);
Run Code Online (Sandbox Code Playgroud)

该函数通常并不真正关心读者是否具体是类型std::io::BufReader,只是它具有相同的功能.

这也使您可以自由选择BufReader<File>,BufReader<&mut File>或者您需要的其他专业.(它甚至不必是一个文件,它可以帮助测试!)

至于是否使用&mut与移动,通常在Rust中,它是标准,仅请求您需要的内容.如果你(以及你调用的函数)只需要一个不可变的引用,那么使用它,如果你需要可变性,请使用&mut.

Move更灵活一些,因为虽然它可以简单地根据你是否需要使用一个按值获取某些东西的函数来使用,但它也经常被用来断言该函数将以某种方式"消耗"数据.

这就是为什么&T通常采用a &mut T而不是引用,以及为什么大多数高级"解析此文件"IO函数倾向于按值移动.通常情况下,您不使用一个适配器来使用文件或读取器的一部分,而将其余部分与另一个适配器一起使用.

实际上,这在概念上非常强大,而不是提供引用,只需将文件移动到更高级别的读取器并调用函数就像BufReader在需要切换适配器时检索文件一样.

  • 我对 Rust 很陌生,但是 fn read_data&lt;R: Read&gt;(r: &amp;mut R) 不是更好的解决方案吗? (2认同)
  • @PhilipRidout 这完全取决于您是否使用 `BufRead` 方法。像“split”或“lines”这样的确实很常见。 (2认同)