Rust 宏

声明宏与过程宏的定位:编译期代码生成、derive、适用边界与可读性权衡。

#type / concept #status / growing #tech / dev #resource / rust

[!info] 关联笔记

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

结合场景再看三个关注点

  1. 宏在调用点展开
  2. 卫生性(hygiene)减少变量捕获坑
  3. 复杂逻辑优先函数

核心概念与准确模型

种类例子
声明宏println!vec!、自写 macro_rules
derive 宏#[derive(Debug, Serialize)]
属性宏#[tokio::main]
函数式过程宏sqlx::query!

设计动机

  • 消除重复
  • 领域语法
  • 编译期计算/校验

边界与误区

  • 错误信息难读
  • 过度 DSL
  • 编译时间上升

[!warning] 常见误区:用宏代替清晰 API 先泛型/函数,不够再宏。

工程实践

  1. 小 macro_rules 可接受
  2. 过程宏独立 crate(*_derive
  3. 文档展示展开意图
  4. 测试宏展开场景

本节总结

  • 宏 = 编译期代码生成
  • 声明宏入门,过程宏生态重
  • 克制使用

自测题

  1. println! 为何是宏不是函数?
  2. derive 解决什么样板?
参考答案
  1. 可变参数格式字符串需编译期处理。
  2. 自动生成 trait 实现(Debug/Clone/Serde…)。

延伸阅读与资料来源

资料类型支撑内容
The Book — Macros官方书
The Little Book of Rust Macros社区深入声明宏
创建于 2026/7/15 更新于 2026/7/15