如何为Rust声明式宏的默认参数设置‘私有’属性
实现Rust声明式log!宏,默认隐藏未标记public!的参数
要实现你需要的效果,不用复杂的函数式宏,通过声明式宏的模式匹配就能搞定核心逻辑:让log!宏自动把所有未用public!包裹的参数替换为<private>,private!包裹的参数也统一处理为<private>。
完整实现代码
macro_rules! log { // 匹配格式字符串 + 逗号分隔的参数列表(支持末尾可选逗号) ($fmt:expr, $($args:tt),* $(,)?) => { let log_str = format!($fmt, $(process_arg!($args)),*); println!("{}", log_str); }; } // 辅助宏:处理单个参数,判断是否为public!标记 macro_rules! process_arg { // 匹配public!(x)的形式,返回原始值 (public!($arg:tt)) => { $arg }; // 匹配所有其他情况(包括private!(x)或普通值),返回<private> ($_arg:tt) => { "<private>" }; } // 保留原有的private!宏(可选,因为process_arg会自动处理它) macro_rules! private { ($arg:tt) => { "<private>" }; } fn main() { log!("{} {} {}", private!(1), public!(2), 3); // 输出:<private> 2 <private> }
核心逻辑说明
log!宏的参数分解:
宏首先匹配格式字符串$fmt:expr,以及后续逗号分隔的所有参数$($args:tt),*,$(,)?是为了兼容参数列表末尾加逗号的写法(Rust常用语法糖)。辅助宏process_arg!的分支匹配:
- 第一个分支专门捕获
public!($arg)的调用,直接返回内部的原始参数值; - 第二个分支匹配所有其他情况:不管是
private!($arg)还是普通的字面量/变量,都统一替换为<private>字符串。
- 第一个分支专门捕获
原问题的解决点:
你之前的代码直接把参数传给format!,导致未标记的参数(比如示例中的3)直接输出原值。现在通过process_arg!对每个参数提前处理,就能实现“默认私有,仅public!标记的参数可见”的需求。
内容的提问来源于stack exchange,提问作者bu haha
相关产品推荐
相关产品推荐

