Rust中如何获取代码的文档注释字符串以消除重复代码
问题解答
首先明确核心结论:
- 编译阶段编写过程宏时,可以读取到代码上标注的
#[doc]属性(包括///语法糖形式的文档注释,本质和#[doc = "xxx"]完全等价)。 - 运行时无法直接读取这些文档注释:doc注释默认只被rustdoc工具消费用于生成文档,不会被编译进最终二进制,标准库没有提供运行时读取的API。
针对你遇到的「同一段描述既要写在文档注释、又要写在Display实现里导致重复」的问题,不需要强行运行时读注释,用以下零重复、零运行时开销的方案即可解决:
方案1:声明宏统一生成(零依赖推荐)
用声明宏把「枚举变体、描述文本」做绑定,一次性生成枚举定义、文档注释、Display trait实现,全程只需要写一次描述文本:
macro_rules! define_status_code { ( $( $variant:ident => $desc:literal ),* $(,)? ) => { /// 接口响应状态码定义 pub enum CodeDefinition { $( #[doc = $desc] $variant, )* } impl std::fmt::Display for CodeDefinition { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { $( Self::$variant => write!(f, $desc), )* } } } } } // 只需要在这里写一次变体和对应描述即可,无需重复维护 define_status_code! { Unknown => "Internal error. Please contact the administrator", NotFound => "Requested resource not found", BadRequest => "Invalid request parameters" }
使用这个方案后,生成的枚举文档和手动写///的效果完全一致,Display输出也和描述文本完全同步,不会出现两边改漏的问题,没有任何额外运行时开销。
方案2:过程宏自动提取doc注释
如果不想改变枚举的编写习惯,还是想正常写///文档注释,可以写一个派生宏(Derive Macro),在编译期自动扫描每个枚举变体上的#[doc]属性内容,自动生成Display实现,不需要手动在fmt方法里重复写字符串。
这个方案的核心逻辑是在过程宏的TokenStream处理阶段,读取变体上的所有doc属性,拼接成描述字符串,再生成对应的match分支即可,同样没有运行时开销。
注意:不要尝试通过运行时解析调试信息、读取自身二进制的方式拿doc注释,这种方案依赖编译开关、跨平台兼容性差,生产环境禁止使用。
内容的提问来源于stack exchange,提问作者XiaoXiao
相关产品推荐
相关产品推荐

