Rust 如何在构造函数中调用struct方法?

Rust 如何在构造函数中调用struct方法?,rust,Rust,我相对来说还不太熟悉Rust,并且在如何用另一种语言编写构造函数的问题上遇到了一种怪癖。我有一个结构,S3Logger,它创建了一个临时磁盘文件,当一定量的数据写入该文件时,该文件将上载到S3并旋转到另一个文件 我希望我的new函数在类gen_new_file上使用一个方法,该类将在写入位置以正确的名称打开一个新文件。但是,为了使其成为一种方法,我必须已经有一个S3Logger要传入,而在new功能期间,我还没有这个工具。在下面的例子中,我展示了如何在另一种语言中实现这一点,在使用对象方法完成构

我相对来说还不太熟悉Rust,并且在如何用另一种语言编写构造函数的问题上遇到了一种怪癖。我有一个结构,
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;
}