Rust 宏
声明宏与过程宏的定位:编译期代码生成、derive、适用边界与可读性权衡。
#type / concept
#status / growing
#tech / dev
#resource / rust
[!info] 关联笔记
- 所属 MOC:进阶与 unsafe · 学习路线
- 前置概念:Trait、函数
- 后续概念:Serde derive、属性宏
- 容易混淆:普通函数抽象
Rust 宏
这个概念为什么出现
需要在编译期生成样板:测试矩阵、DSL、derive 实现。
宏在 AST/token 层面变换代码。
[!abstract] 一句话理解
macro_rules!做声明宏匹配;过程宏(derive/attribute/function-like)用 Rust 写编译期插件;优先函数/泛型,宏用于真需要语法层扩展时。
最小可运行示例
场景:快速生成命名日志宏
// 业务意图:统一前缀日志。
// 教学点:macro_rules 基础。
macro_rules! audit {
($($arg:tt)*) => {
println!("[audit] {}", format!($($arg)*));
};
}
fn main() {
let user = 7;
audit!("login user={user}");
}
建议运行:cargo run
期望:[audit] login user=7
结合场景再看三个关注点
- 宏在调用点展开
- 卫生性(hygiene)减少变量捕获坑
- 复杂逻辑优先函数
核心概念与准确模型
| 种类 | 例子 |
|---|---|
| 声明宏 | println!、vec!、自写 macro_rules |
| derive 宏 | #[derive(Debug, Serialize)] |
| 属性宏 | #[tokio::main] |
| 函数式过程宏 | sqlx::query! |
设计动机
- 消除重复
- 领域语法
- 编译期计算/校验
边界与误区
- 错误信息难读
- 过度 DSL
- 编译时间上升
[!warning] 常见误区:用宏代替清晰 API 先泛型/函数,不够再宏。
工程实践
- 小 macro_rules 可接受
- 过程宏独立 crate(
*_derive) - 文档展示展开意图
- 测试宏展开场景
本节总结
- 宏 = 编译期代码生成
- 声明宏入门,过程宏生态重
- 克制使用
自测题
println!为何是宏不是函数?- derive 解决什么样板?
参考答案
- 可变参数格式字符串需编译期处理。
- 自动生成 trait 实现(Debug/Clone/Serde…)。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| The Book — Macros | 官方书 | 宏 |
| The Little Book of Rust Macros | 社区 | 深入声明宏 |