Rust编程宏教程:几行代码搞定重复逻辑

ref="/tag/2030/" style="color:#B2A89E;font-weight:bold;">Rust 时总在重复写类似的 match 分支、结构体字段初始化、日志打印?别硬扛,宏就是干这个的。

宏不是函数,是代码生成器

比如你经常要给某个类型加调试输出:

println!("User {{ name: {}, age: {} }}", user.name, user.age);

每次改字段名都得手动敲,还容易漏。不如写个宏:

macro_rules! debug_print {
($obj:expr, $($field:ident),+ $(,)?) => {{
let s = format!("{{ {} }}",
concat!($(stringify!($field), " = {:?}, ")+)
.trim_end_matches(", ")
);
println!(s, $($obj.$field),+);
}};
}

用起来就清爽多了:

let u = User { name: "小李", age: 28 };
debug_print!(u, name, age);
// 输出:{ name = "小李", age = 28 }

系统设置里也能用宏?真能

“系统设置”栏目不是只讲 Windows 控制面板——Rust 写的配置工具(比如终端下管理 dotfiles、自动同步 config.toml)经常要用宏简化重复操作。比如批量注册配置项:

macro_rules! config_keys {
($($key:literal => $ty:ty),+ $(,)?) => {
$(pub const $key: &str = stringify!($key);)+
pub fn parse_value(key: &str, val: &str) -> Result<$ty, String> {
match key {
$($key => val.parse().map_err(|e| e.to_string()),)+
_ => Err(format!("未知配置项: {}", key)),
}
}
};
}

config_keys! {
"timeout" => u64,
"auto_save" => bool,
"theme" => String,
}

编译时自动生成常量和解析逻辑,不用手写 match,也不怕漏项。

小心!宏报错信息很“硬核”

宏展开出错时,Rust 编译器会显示展开后的中间代码,看着吓人。遇到红字先别慌,把宏调用改成普通函数试一遍逻辑,确认是宏语法问题再查 $var:ty 这类匹配规则。本地测试建议用 rustc --pretty=expanded 看实际展开结果。

宏不是银弹,但对系统级工具、CLI 配置管理这类“写一次、用十次”的场景,它真能省下大把时间。