Rust 如何在构造函数中调用struct方法?
我相对来说还不太熟悉Rust,并且在如何用另一种语言编写构造函数的问题上遇到了一种怪癖。我有一个结构,Rust 如何在构造函数中调用struct方法?,rust,Rust,我相对来说还不太熟悉Rust,并且在如何用另一种语言编写构造函数的问题上遇到了一种怪癖。我有一个结构,S3Logger,它创建了一个临时磁盘文件,当一定量的数据写入该文件时,该文件将上载到S3并旋转到另一个文件 我希望我的new函数在类gen_new_file上使用一个方法,该类将在写入位置以正确的名称打开一个新文件。但是,为了使其成为一种方法,我必须已经有一个S3Logger要传入,而在new功能期间,我还没有这个工具。在下面的例子中,我展示了如何在另一种语言中实现这一点,在使用对象方法完成构
S3Logger
,它创建了一个临时磁盘文件,当一定量的数据写入该文件时,该文件将上载到S3并旋转到另一个文件
我希望我的new
函数在类gen_new_file
上使用一个方法,该类将在写入位置以正确的名称打开一个新文件。但是,为了使其成为一种方法,我必须已经有一个S3Logger
要传入,而在new
功能期间,我还没有这个工具。在下面的例子中,我展示了如何在另一种语言中实现这一点,在使用对象方法完成构建之前,先部分构建对象;然而,这显然在生锈的情况下不起作用
我可以为当前的日志文件使用选项
,但这感觉有点恶心。我想强制执行不变量,如果我有一个S3Logger
,我知道它有一个打开的文件
对于此类问题,防锈的最佳做法是什么
pub struct S3Logger {
local_folder: PathBuf,
destination_path: String,
max_log_size: usize,
current_log_file: File,
current_logged_data: usize
}
impl S3Logger {
pub fn new<P: AsRef<Path>>(
local_folder: P,
destination_path: &str,
max_log_size: usize
) -> Self {
std::fs::create_dir_all(&local_folder).unwrap();
let mut ret = Self {
local_folder: local_folder.as_ref().to_path_buf(),
destination_path: destination_path.to_string(),
max_log_size: max_log_size,
current_logged_data: 0
};
// fails ^^^^ missing `current_log_file
ret.gen_new_file();
return ret
}
fn gen_new_file(&mut self) -> () {
let time = Utc::now().to_rfc3339();
let file_name = format!("{}.log", time);
let file_path = self.local_folder.join(file_name);
self.current_log_file = File::create(&file_path).unwrap();
}
}
pub结构记录器{
本地_文件夹:PathBuf,
目的地路径:字符串,
最大日志大小:usize,
当前日志文件:文件,
当前\u记录的\u数据:使用
}
嵌入式S3记录器{
新店(
本地_文件夹:P,
目标路径:&str,
最大日志大小:usize
)->自我{
std::fs::create_dir_all(&local_文件夹).unwrap();
让mut-ret=Self{
local_folder:local_folder.as_ref().to_path_buf(),
目标路径:目标路径。到字符串(),
最大日志大小:最大日志大小,
当前\u记录的\u数据:0
};
//失败^^^^缺少“当前日志”文件
ret.gen_new_file();
回程网
}
fn gen\u新文件(&mut self)->(){
让时间=Utc::now()to_rfc3339();
让file_name=format!(“{}.log”,time);
让file\u path=self.local\u folder.join(文件名);
self.current_log_file=file::create(&file_path).unwrap();
}
}
正如您所注意到的,一种方法确实是将字段设置为可选
您还可以将结构分为两部分
struct S3LoggerInternal{
发布本地文件夹:PathBuf,
发布目的地路径:字符串,
发布最大日志大小:usize,
}
发布结构S3Logger{
内部:S3LoggerInternal,
当前日志文件:文件,
当前记录的数据:使用,
}
嵌入式S3记录器{
发布fn新(…)->结果{
设internal=S3LoggerInternal{…};
让file=internal.open_file()?;
Self{internal,current_log_file:file,current_logged_data:0}
}
}
impl S3LoggerInternal{
fn打开\u文件(&self)->结果{
//…gen_new_file函数中的代码
}
}
最简单的方法是将gen_new_文件
置于本地文件夹:p
而不是&mut self
,从那里返回文件
,并在构造函数中调用该文件:
use std::fs::File;
use std::path::{Path, PathBuf};
use chrono::Utc;
pub struct S3Logger {
local_folder: PathBuf,
destination_path: String,
max_log_size: usize,
current_log_file: File,
current_logged_data: usize
}
impl S3Logger {
pub fn new<P: AsRef<Path>>(
local_folder: P,
destination_path: &str,
max_log_size: usize
) -> Self {
std::fs::create_dir_all(&local_folder).unwrap();
let current_log_file = Self::gen_new_file(&local_folder);
Self {
local_folder: local_folder.as_ref().to_path_buf(),
destination_path: destination_path.to_string(),
max_log_size: max_log_size,
current_logged_data: 0,
current_log_file,
}
}
fn gen_new_file<P: AsRef<Path>>(local_folder: P) -> File {
let time = Utc::now().to_rfc3339();
let file_name = format!("{}.log", time);
let file_path = local_folder.as_ref().join(file_name);
File::create(&file_path).unwrap()
}
}
谢谢,这就是我最后要做的。我希望能够隐藏这一点,让gen_new_文件突变成为一个自我论证,但我想看看人们在这种情况下是否有一个通用模式。谢谢,这看起来像是我将来可以使用的模式。
fn replace_log_file<P: AsRef<Path>>(&mut self, new_path: P) {
let new_file = Self::gen_new_file(&new_path);
self.current_log_file = new_file;
}