应用配置在应用中是比较基础的机制,本文以示例的方式,讲解在Rust语言中,如果实现一个可扩展的配置类。
- 1、定义结构体
首先我们需要定义一个配置类结构体,用于描述应用中需要配置的配置项。
#[derive(Debug, Clone)]
pub struct Config<Flags>{
pub host:String,
pub port:u32,
pub flags:Flags,
}
Flags用于定义后续可能的扩展配置,host和port为示例,根据应用适用场景定义的基础的配置项。
- 2、定义默认配置
为了降低配置工作,让配置类实现Default trait,为应用提供默认配置。
impl<Flags> Default for Config<Flags> where Flags:Default{
fn default() -> Self {
Self {
host: Default::default(),
port: Default::default(),
flags: Default::default()
}
}
}
实现Defualt trait时,需要对Flags进行约束,指定为Flags是实现Default trait的类型。Config实现了Default trait,同时要求
它的子项也实现Default trait。在rust中,该要求比较常见,例如:Debug和Clone trait等,都有类似要求。
当不需要对Config进行扩展时,Flags可以指定为(),如下:
let config = Config::<()>::default();
- 3、通过扩展配置项创建配置
通过配置项,创建Config实例
impl<Flags> Config<Flags>{
pub fn from_flags(flags:Flags)->Self{
let default = Config::<()>::default();
Self {
flags,
host:default.host,
port:default.port,
}
}
}
- 4、完整代码及测试
#[derive(Debug, Clone)]
pub struct Config<Flags>{
pub host:String,
pub port:u32,
pub flags:Flags,
}
impl<Flags> Config<Flags>{
pub fn from_flags(flags:Flags)->Self{
let default = Config::<()>::default();
Self {
flags,
host:default.host,
port:default.port,
}
}
}
impl<Flags> Default for Config<Flags> where Flags:Default{
fn default() -> Self {
Self { host: Default::default(), port: Default::default(), flags: Default::default() }
}
}
#[test]
fn test_default_config(){
let config = Config::<()>::default();
println!("The config is {:?}", config);
}
#[test]
fn test_from_flags(){
#[derive(Debug, Clone)]
struct Attrs{
id:u32,
name:String,
}
let attrs = Attrs{id:12, name:"bob".to_string()};
let config = Config::from_flags(attrs);
println!("The config is {:?}", config);
println!("The id in config is {:?}", config.flags.id);
println!("The name in config is {:?}", config.flags.name);
}