Почему изменения в переменной const не сохраняются между использованиями? - PullRequest
0 голосов
/ 23 сентября 2018

Я пытаюсь создать структуру для управления хранилищем файлов, но после изменения значения она не может быть использована.Я уверен, что речь идет о жизни, но я не понимаю, как я могу это исправить.

use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader};
use std::option::Option;
use std::path::Path;

pub struct Storage<'a> {
    path_str: &'a str,
    file: Option<File>,
}

const LOCKED_STORAGE: Storage<'static> = Storage {
    path_str: &"/tmp/bmoneytmp.bms",
    file: None,
};

pub fn get_instance() -> Storage<'static> {
    if LOCKED_STORAGE.file.is_none() {
        LOCKED_STORAGE.init();
    }

    LOCKED_STORAGE
}

impl Storage<'static> {
    // Create a file for store all data, if does not alred exists
    fn init(&mut self) {
        let path = Path::new(self.path_str);

        self.file = match OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(path)
        {
            Err(e) => panic!("Couldn't create the storage file at {}", e.description()),
            Ok(file) => Some(file),
        };

        if self.file.is_none() {
            panic!("Error on init??"); // This line is not called. Ok :)
        }
    }

    // Check if section exists
    pub fn check_section(&self, name: String) -> bool {
        if self.file.is_none() {
            panic!("Error on check??"); // This line is called. :(
        }
        true
    }
}

fn main() {
    let storage = get_instance();
    storage.check_section("accounts".to_string());
}

детская площадка

Это не удается:

thread 'main' panicked at 'Error on check??', src/main.rs:48:13

Я пытаюсь использовать метод, чтобы открыть файл и прочитать этот открытый файл, но во втором методе экземпляр файла не открывается.Используя Option<File>, я изменяю значение с помощью Same / None, но переменная остается равной None.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Спасибо @shepmaster.Я многому научился с твоим ответом.Но я изменил свой подход и исправил свою проблему, используя глобальную статическую и ленивую Mutex.

Также я прочитал статьюrust / index.html и это помогло мне понять мою ошибку.

Мой новый код:

#[macro_use]
extern crate lazy_static;

use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::option::Option;
use std::sync::Mutex;

pub struct Storage {
    path_str: String,
    file: Option<File>
}

lazy_static! {
    pub static ref LOCKED_STORAGE: Mutex<Storage> = Mutex::new(start_storage());
}

fn start_storage() -> Storage {
    let mut st = Storage { path_str: "/tmp/bmoneytmp.bms".to_string(), file: None };
    st.init();
    st
}

impl Storage {

    // Create a file for store all data, if does not alred exists
    fn init(&mut self) {

        let path = Path::new(&self.path_str);

        self.file = match OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(path)
        {
            Err(e) => panic!("Couldn't create the storage file at {}", e.description()),
            Ok(file) => Some(file),
        };
    }

    // Check if section exists
    pub fn check_section(&self, name: String) -> bool {

        let file = match &self.file {
            Some(file) => file,
            None => panic!("File of storage not opened")
        };

        for line in BufReader::new(file).lines() {
            println!("{}{:?}", name, line); // Working!!
        }

        true
    }
}

fn main() {
    // run in your bash before: echo "Row 1" >> /tmp/bmoneytmp.bms
    LOCKED_STORAGE.lock().unwrap().check_section("accounts".to_string());
}

Вы можете построить это на детской площадке: https://play.rust -lang.org/?gist=bbd47a13910e0f7cda908dc82ba290eb&version=beta&mode=debug&edition=2018

Полный код моего проекта: https://github.com/fernandobatels/blitz-money

Полный код моего исправления: https://github.com/fernandobatels/blitz-money/blob/9dc04742a57e6cd99742f2400a6245f210521f5d/src/backend/storage.rshttps://github.com/fernandobatels/blitz-money/blob/9dc04742a57e6cd99742f2400a6245f210521f5d/src/backend/accounts.rs

0 голосов
/ 24 сентября 2018

При программировании очень важно научиться создавать Минимальный, Полный и Проверяемый пример .Вот одна из ваших проблем:

const EXAMPLE: Option<i32> = Some(42);

fn main() {
    EXAMPLE.take();
    println!("{:?}", EXAMPLE);
}

Это печатает Some(42) - значение EXAMPLE не изменяется.

Переменная const не имеет гарантий относительно количества экземпляров.это будет иметь.Компилятору разрешено иметь ноль, один или несколько его экземпляров.Каждый раз, когда вы используете const, создается впечатление, что вы создали совершенно новое значение прямо здесь, вставляя в определение константы:

fn main() {
    Some(42).take();
    println!("{:?}", Some(42));
}

Вместо этого вы хотите создатьsingleton .

См. также:

...