为什么对 const 变量的更改不会在两次使用之间持续存在?
Why do changes to a const variable not persist between usages?
我正在尝试创建一个结构来操作文件存储,但在我更改值后它无法使用。我确定这与生命周期有关,但我不明白如何解决这个问题。
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
。
在编程时,学习如何创建Minimal, Complete, and Verifiable example是一项非常重要的技能。这是您的问题之一:
const EXAMPLE: Option<i32> = Some(42);
fn main() {
EXAMPLE.take();
println!("{:?}", EXAMPLE);
}
这将打印 Some(42)
— EXAMPLE
的值未更改。
A const
变量不能保证它有多少个实例。允许编译器拥有它的零个、一个或多个实例。每次你使用 const
,就好像你在那里创建了一个全新的值,粘贴在常量的定义中:
fn main() {
Some(42).take();
println!("{:?}", Some(42));
}
相反,您想 create a singleton。
另请参阅:
谢谢@shepmaster。我从你的回答中学到了很多。但是我改变了我的方法并使用 Mutex global static 和 lazy_static.
解决了我的问题
我还阅读了文章 https://bryce.fisher-fleig.org/blog/strategies-for-returning-references-in-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());
}
您可以在 playground 上构建它: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.rs https://github.com/fernandobatels/blitz-money/blob/9dc04742a57e6cd99742f2400a6245f210521f5d/src/backend/accounts.rs
我正在尝试创建一个结构来操作文件存储,但在我更改值后它无法使用。我确定这与生命周期有关,但我不明白如何解决这个问题。
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
。
在编程时,学习如何创建Minimal, Complete, and Verifiable example是一项非常重要的技能。这是您的问题之一:
const EXAMPLE: Option<i32> = Some(42);
fn main() {
EXAMPLE.take();
println!("{:?}", EXAMPLE);
}
这将打印 Some(42)
— EXAMPLE
的值未更改。
A const
变量不能保证它有多少个实例。允许编译器拥有它的零个、一个或多个实例。每次你使用 const
,就好像你在那里创建了一个全新的值,粘贴在常量的定义中:
fn main() {
Some(42).take();
println!("{:?}", Some(42));
}
相反,您想 create a singleton。
另请参阅:
谢谢@shepmaster。我从你的回答中学到了很多。但是我改变了我的方法并使用 Mutex global static 和 lazy_static.
解决了我的问题我还阅读了文章 https://bryce.fisher-fleig.org/blog/strategies-for-returning-references-in-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());
}
您可以在 playground 上构建它: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.rs https://github.com/fernandobatels/blitz-money/blob/9dc04742a57e6cd99742f2400a6245f210521f5d/src/backend/accounts.rs