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

我有一个函数可以接收一个文件:

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

fn read_some_data(f: &mut std::fs::File) {
    let mut reader = BufReader::new(f);
    read_some_other_data(&mut reader);
}

虽然这可以实现,但在将读者传递给其他功能时,应该使用哪种引用访问排列?

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

因 for each 函数都不需要拥有数据,所以我认为最好传递为&mut BufReader<&mut File>,但文档中的示例使用<File>.

什么是好的经验法则?

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

推荐答案

最惯用的方式可能是根本不引用std::io::BufReader.你真的想提到trait Read和/或BufRead

use std::io:BufRead;

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

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

这也让你完全可以自由 Select BufReader<File>BufReader<&mut File>或其他任何你需要的专业.(它甚至不必是文件,这有助于测试!)

至于是使用&mut还是移动,一般来说,标准是只要求你需要的东西.如果你(和你调用的函数)只需要一个不可变的引用(&T),那么使用它;如果你需要可变性,那么使用&mut T.

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

这就是为什么BufReader通常接受File而不是引用,以及为什么大多数高级"解析此文件"IO函数倾向于按值移动.通常情况下,您不会使用一个适配器来消耗File或读卡器的一部分,而使用另一个适配器来消耗其余部分.

事实上,这在概念上非常强大,以至于在需要切换适配器时,更常见的做法是将File移到更高级别的读取器中,并调用into_inner这样的函数来检索文件,而不是给出一个引用.

Rust相关问答推荐

通过使用光标拖动角来绕其中心旋转矩形

integer cast as pointer是什么意思

在铁 rust 中传递所有权

如何模拟/创建ReqData以测试Actix Web请求处理程序?

为什么这个变量不需要是可变的?

如何实现Serde::Ser::Error的调试

关于 map 闭合求和的问题

在什么情况下 `..._or()` 比 `..._or_else(|| {})` 更好,为什么?

在 Rust 中,在需要引用 self 的 struct 体方法中使用闭包作为 while 循环条件

如何重命名 clap_derive 中的子命令占位符?

可以在旋转循环中调用try_recv()吗?

为什么我们有两种方法来包含 serde_derive?

如何为整数切片定义一个带有额外函数的特性别名?

Rust编译器通过哪些规则来确保锁被释放?

分配给下划线模式时会发生什么?

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

在异步 Rust 中,Future 如何确保它只调用最近的 Waker?

有没有办法使用 NASM 语法进行内联汇编?

相互调用的递归异步函数:检测到循环

传递 Option<&mut T> 时何时需要 mut