Rust 应用配置:config 和 dotenv 库
任何现代应用都需要灵活的配置系统:数据库设置、API 密钥、服务器端口、日志级别和其他参数。在 Rust 生态系统中,有强大的工具——config 和 dotenv crate。它们允许将来自不同来源(文件、环境变量、命令行参数)的设置合并到一个类型安全的结构中。
为什么需要单独的库?
Rust 是一种强静态类型语言。简单地从 std::env::var() 读取字符串会导致大量手动检查和转换。config 库自动化了这一过程:
- 支持格式:YAML、JSON、TOML、HJSON、INI、RON
- 支持覆盖的层次化设置结构
- 通过
serde自动反序列化为用户自定义结构 - 合并多个具有优先级的来源(文件 < env < CLI)
安装
在 Cargo.toml 中添加:
[dependencies]config = "0.14"serde = { version = "1.0", features = ["derive"] }dotenv = "0.15"基本示例:从文件和 env 读取
创建一个应用配置结构:
use serde::Deserialize;use config::Config;
#[derive(Debug, Deserialize)]struct AppConfig { server: ServerConfig, database: DatabaseConfig,}
#[derive(Debug, Deserialize)]struct ServerConfig { host: String, port: u16, workers: u8,}
#[derive(Debug, Deserialize)]struct DatabaseConfig { url: String, pool_size: u32,}
fn main() -> Result<(), config::ConfigError> { // 加载配置 let config = Config::builder() .add_source(config::File::with_name("config/default")) .add_source(config::Environment::with_prefix("APP")) .build()?;
let app_config: AppConfig = config.try_deserialize()?; println!("{:#?}", app_config); Ok(())}config/default.toml 文件:
[server]host = "127.0.0.1"port = 8080workers = 4
[database]url = "postgres://localhost/mydb"pool_size = 10带有前缀 APP_ 的环境变量会覆盖文件中的值。例如,APP_DATABASE__URL 将更改数据库 URL。
使用 dotenv
为了方便开发,通常使用 .env 文件。dotenv crate 在初始化 config 之前将其加载到环境变量中:
use dotenv::dotenv;
fn main() { dotenv().ok(); // 加载 .env // 然后像上面的示例一样初始化 config}.env 文件内容:
APP_SERVER__PORT=3000APP_DATABASE__POOL_SIZE=20高级场景:多个来源
实际项目需要组合来自不同位置的设置。config 允许设置具有优先级的来源链:
let config = Config::builder() // 基本设置(低优先级) .add_source(config::File::with_name("config/default")) // 特定环境的覆盖 .add_source(config::File::with_name(&format!("config/{}", env::var("APP_ENV").unwrap_or("development")))) // 环境变量(中等优先级) .add_source(config::Environment::with_prefix("APP")) // 命令行参数(高优先级) .add_source(config::File::from(std::env::args().nth(1).unwrap_or_default())) .build()?;最佳实践
- 为环境变量使用前缀,以避免与系统变量冲突