有没有办法返回一个函数中创build的variables的引用?
我想写一个程序,将分两步写一个文件。 在程序运行之前文件可能不存在。 文件名是固定的。
问题是OpenOptions.new().write()
可能会失败。 在这种情况下,我想调用一个自定义函数trycreate()
。 这个想法是创build文件,而不是打开它,并返回一个句柄。 由于文件名是固定的, trycreate()
没有参数,我不能设置返回值的生命周期。
我该如何解决这个问题?
use std::io::Write; use std::fs::OpenOptions; use std::path::Path; fn trycreate() -> &OpenOptions { let f = OpenOptions::new().write(true).open("foo.txt"); let mut f = match f { Ok(file) => file, Err(_) => panic!("ERR"), }; f } fn main() { { let f = OpenOptions::new().write(true).open(b"foo.txt"); let mut f = match f { Ok(file) => file, Err(_) => trycreate("foo.txt"), }; let buf = b"test1\n"; let _ret = f.write(buf).unwrap(); } println!("50%"); { let f = OpenOptions::new().append(true).open("foo.txt"); let mut f = match f { Ok(file) => file, Err(_) => panic!("append"), }; let buf = b"test2\n"; let _ret = f.write(buf).unwrap(); } println!("Ok"); }
fjh是绝对正确的 ,但是我想更深入地评论一下,并且在你的代码中碰到一些其他的错误。
有没有办法从一个没有参数的函数返回一个引用?
技术上“是”,但为了你想要的,“不”。
一个参考指向一个现有的记忆。 在一个没有参数的函数中,唯一可以引用的是全局常量(它具有生命期&'static
)和局部variables。 现在我会忽略全局variables。
在像C或C ++这样的语言中,实际上可以引用一个局部variables并将其返回。 但是,只要函数返回,就不能保证你所引用的内存仍然是你想象的那样。 它可能会保留你期望的一段时间,但最终内存将被重用于其他的东西。 只要您的代码查看内存并尝试将用户名解释为银行帐户中剩余的金额,就会出现问题!
这就是Rust的生命周期所阻止的 – 在当前的存储位置,引用值有效的时间不能超过这个参数。
而不是试图返回一个引用,返回一个拥有的对象。 String
代替&str
, Vec<T>
而不是&[T]
, T
代替&T
等。
你的实际问题
查看OpenOptions::open
的文档:
fn open<P: AsRef<Path>>(&self, path: P) -> Result<File>
它返回一个Result<File>
,所以我不知道你会如何返回一个OpenOptions
或引用。 如果你把它改写为:
fn trycreate() -> File { OpenOptions::new().write(true).open("foo.txt").expect("Couldn't open") }
这使用Result::expect
一个有用的错误信息。 当然,在程序的内部恐慌并不是非常有用,所以build议将错误传播出去:
fn trycreate() -> io::Result<File> { OpenOptions::new().write(true).open("foo.txt") }
而Option
和Result
有很多很好的方法来处理链式错误逻辑。 在这里,你可以使用or_else
:
let f = OpenOptions::new().write(true).open("foo.txt"); let mut f = f.or_else(|_| trycreate()).expect("failed at creating");
我也创build一个返回Result
的“内部主”。 一起,包括fjh的build议:
use std::io::{self, Write}; use std::fs::OpenOptions; fn inner_main() -> io::Result<()> { let mut f = OpenOptions::new() .create(true) .write(true) .append(true) .open("foo.txt")?; f.write(b"test1\n")?; f.write(b"test2\n")?; Ok(()) } fn main() { inner_main().expect("An error occurred"); println!("Ok"); }
有没有办法从一个没有参数的函数返回一个引用?
否(除了引用静态值,但这些在这里没有帮助)。
不过,你可能想看看OpenOptions::create
。 如果你把你的第一行改main
let f = OpenOptions::new().write(true).create(true).open(b"foo.txt");
该文件将被创build,如果它不存在,这应该解决您的原始问题。