Ответ 1
fjh абсолютно корректен, но я хочу более подробно прокомментировать и затронуть некоторые другие ошибки с вашим кодом.
Есть ли способ вернуть ссылку из функции без аргументов?
Технически "да", но для чего вы хотите "нет".
Ссылка указывает на существующую часть памяти. В функции без аргументов единственными вещами, на которые можно ссылаться, являются глобальные константы (которые имеют время жизни &'static
) и локальные переменные. Сейчас я буду игнорировать глобальные переменные.
На языке, подобном C или С++, вы можете фактически ссылаться на локальную переменную и возвращать ее. Однако, как только функция вернется, не гарантирует, что память, на которую вы ссылаетесь, по-прежнему остается тем, что вы считали. Он может остаться тем, что вы ожидаете какое-то время, но в конечном итоге память будет использоваться повторно для чего-то другого. Как только ваш код просматривает память и пытается интерпретировать имя пользователя как сумму денег, оставшуюся на банковском счете, возникают проблемы!
Это то, что предотвращает время жизни 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
для паники с полезным сообщением об ошибке. Конечно, паника в кишках вашей программы не очень полезна, поэтому рекомендуется распространять ваши ошибки:
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");
Я также создаю "внутреннюю основную", которая возвращает Result
. Все вместе, включая предложения fjh:
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");
}