gpt4 book ai didi

rust - 加载.env并使用辅助函数将其转换为一般结构

转载 作者:行者123 更新时间:2023-12-03 11:40:59 28 4
gpt4 key购买 nike

我想将多个env.variables转换为静态结构。
我可以手动进行:

 Env {
is_development: env::var("IS_DEVELOPMENT")
.unwrap()
.parse::<bool>()
.unwrap(),
server: Server {
host: env::var("HOST").unwrap(),
port: env::var("PORT")
.unwrap()
.parse::<u16>()
.unwrap(),
},
}
但是,当存在多个值时,它变得肿。有没有一种方法可以使通用帮助程序函数赋予我指定的值或让我感到 panic ?这样的事情(或另一种解决方案):
    fn get_env_var<T>(env_var_name: String) -> T {
// panic is ok here
let var = env::var(env_var_name).unwrap();

T::from(var)
}



get_env_var<u16>("PORT") // here i got u16
get_env_var<bool>("IS_DEVELOPMENT") // here is my boolean
完整的例子
use crate::server::logger::log_raw;
use dotenv::dotenv;
use serde::Deserialize;
use std::env;

#[derive(Deserialize, Debug, Clone)]
pub struct Server {
pub host: String,
pub port: u16,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Env {
pub is_development: bool,
pub server: Server,
}
impl Env {
pub fn init() -> Self {
dotenv().expect(".env loading fail");

// how can i specify what type i expect?
fn get_env_var<T>(env_var_name: String) -> T {
// panic is ok here
let var = env::var(env_var_name).unwrap();

T::from(var)
}

// instead this
Env {
is_development: env::var("IS_DEVELOPMENT")
.unwrap()
.parse::<bool>()
.unwrap(),
server: Server {
host: env::var("HOST").unwrap(),
port: env::var("PORT")
.unwrap()
.parse::<u16>()
.unwrap(),
},
}

// do something like this
/*
Env {
is_development: get_env_var<bool>("IS_DEVELOPMENT"),
server: Server {
host: get_env_var<String>("HOST"),
port: get_env_var<u16>("PORT"),
},
}
*/
}
}

lazy_static! {
pub static ref ENV: Env = Env::init();
}

最佳答案

像在使用 str::parse 的手动版本中一样,您可以具有与str::parse(即 FromStr )相同的要求。因此,如果您包括T: FromStr要求,那么您将能够执行var.parse::<T>()

use std::env;
use std::fmt::Debug;
use std::str::FromStr;

fn get_env_var<T>(env_var_name: &str) -> T
where
T: FromStr,
T::Err: Debug,
{
let var = env::var(env_var_name).unwrap();
var.parse::<T>().unwrap()
}
然后,如果您通过执行 PORT=1234 IS_DEVELOPMENT=true cargo run运行以下命令。
fn main() {
println!("{}", get_env_var::<u16>("PORT"));
println!("{}", get_env_var::<bool>("IS_DEVELOPMENT"));
}
然后它将输出:
1234
true

或者,您可能希望能够处理 VarError::NotPresent 并回退到默认值。
use std::env::{self, VarError};
use std::fmt::Debug;
use std::str::FromStr;

fn get_env_var<T>(env_var_name: &str) -> Result<T, VarError>
where
T: FromStr,
T::Err: Debug,
{
let var = env::var(env_var_name)?;
Ok(var.parse().unwrap())
}
现在,如果您仅执行 PORT=1234 cargo run,那么这样做会更容易:
let is_dev = get_env_var::<bool>("IS_DEVELOPMENT")
.map_err(|err| match err {
VarError::NotPresent => Ok(false),
err => Err(err),
})
.unwrap();
println!("{:?}", is_dev);

如果要回退到 Default ,如果 VarError::NotPresent :
fn get_env_var<T>(env_var_name: &str) -> T
where
T: FromStr,
T::Err: Debug,
T: Default,
{
let var = match env::var(env_var_name) {
Err(VarError::NotPresent) => return T::default(),
res => res.unwrap(),
};

var.parse().unwrap()
}

关于rust - 加载.env并使用辅助函数将其转换为一般结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66171718/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com