因此,我已经看到了这个问题,该问题解释了如何serde_json既可以通过引用获取读者/作家,又可以选择拥有他们的所有权。很公平。
但是我不知道它是如何工作的Write-所有Write方法都需要一个&mut self,所以我认为如果我传递一个仅知道其参数是对某事物的引用的方法,Write那么它将无法对其进行任何操作。但是,即使我将非mut引用传递给以某种方式最终写入被引用文件的方法,该示例也可以编译并正常工作:
extern crate serde_json;
use std::fs::OpenOptions;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open("/tmp/serde.json")?;
// why does this work?
serde_json::to_writer(&file, &10)?;
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
我传递了&File-如预期的那样,如果我要直接在上调用任何Write的方法,将File无法正常工作:
use std::io::{self, Write};
use std::fs::OpenOptions;
fn main() -> io::Result<()> {
let file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open("/tmp/wtf")?;
let file_ref = &file;
// this complains about not having a mutable ref as expected
file_ref.write(&[1,2,3])?;
Ok(())
}
Run Code Online (Sandbox Code Playgroud)
error[E0596]: cannot borrow `file_ref` as mutable, as it is not declared as mutable
--> test.rs:12:5
|
10 | let file_ref = &file;
| -------- help: consider changing this to be mutable: `mut file_ref`
11 | // this complains about not having a mutable ref as expected
12 | file_ref.write(&[1,2,3])?;
| ^^^^^^^^ cannot borrow as mutable
Run Code Online (Sandbox Code Playgroud)
那有什么呢?是否serde_json以某种方式破坏了类型系统,或者这是类型系统的故意特征?如果是后者,它如何工作以及为什么这样工作?
serde_json::to_writer的第一个参数接受任何实现的类型Write。这样的值之一是&File。
这可能令人惊讶,但是的docs File明确声明对文件的引用的可变性与文件是否会更改无关:
需要注意的是,虽然读写方法需要
&mut File,因为对接口Read和Write,的持有人&File仍可以修改该文件,无论是通过采取的方法&File或通过检索底层操作系统对象,并修改文件的方式。此外,许多操作系统允许通过不同的进程同时修改文件。避免假设持有某个&File文件不会更改。
您可能会问-等一下,我认为采用的方法Write是&mut self?他们做到了!但是在这种情况下,Write是为实现的&File,因此传递给Write它的类型有些混乱&mut &File(对不可变引用的可变引用)。
这就解释了为什么您的第二个示例无法编译-您需要能够对进行可变引用&file,并且在绑定不可变的情况下不能这样做。这是重要的认识-绑定的可变性和绑定值的可变性不一定相同。
当您运行代码时,错误消息中对此进行了提示:
error[E0596]: cannot borrow `file_ref` as mutable, as it is not declared as mutable
--> src/lib.rs:11:5
|
10 | let file_ref = &file;
| -------- help: consider changing this to be mutable: `mut file_ref`
11 | file_ref.write(&[1,2,3])?;
| ^^^^^^^^ cannot borrow as mutable
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
如果更改let file_ref = &file;为let mut file_ref = &file;,则代码将编译。
| 归档时间: |
|
| 查看次数: |
113 次 |
| 最近记录: |