Rust 中的属性

1,834 阅读2分钟

属性是什么

属性(Attribute)是一种通用的自由格式的元数据,Rust 中的属性以ECMA-335中的为模型,其语法则来自ECMA-334(C#)。

属性的用途

属性只能应用于 Rust 中的项(Item),属性的主要用途如下:

  • 条件编译
  • 设置 Crate 名称,版本和类型(binary 或 library)
  • 自动生成代码
  • 控制 Linter 的行为
  • 启用编译器的一些特性
  • 链接外部的 library
  • 标记单元测试函数

属性的语法

属性的语法借鉴了 C#,内部属性(Inner attributes)以 #! 开头,外部属性(Outer attributes)则以 # 开头。内部属性应用于它所在的项(Item),外部属性应用于紧跟在它之后的项(Item)。

属性中的参数支持不同的语法形式,比如:

#[no_std]
#[doc = "example"]
#[allow(unused, clippy::inline_always)]
#[macro_use(foo, bar)]
#[link(name = "CoreFoundation", kind = "framework")]

属性的分类

属性可以被分为以下四类:

常用的属性

Test

test 属性用来把一个函数标记为单元测试函数,这些函数只有在测试模式下(cargo testrustc --test)才会被编译。测试函数没有参数,并且返回值类型必须是以下两种:

  • ()
  • Result<(), E> where E: Error

示例

#[test]
fn test_the_thing() -> io::Result<()> {
    let state = setup_the_thing()?;
    do_the_thing(&state)?;
    Ok(())
}

Derive

derive 属性一般用来为数据类型生成 Trait 实现。

示例

#[derive(PartialEq, Clone)]
struct Foo<T> {
    a: i32,
    b: T,
}

编译器会自动为 Foo 生成 PartialEq 的实现:

impl<T: PartialEq> PartialEq for Foo<T> {
    fn eq(&self, other: &Foo<T>) -> bool {
        self.a == other.a && self.b == other.b
    }

    fn ne(&self, other: &Foo<T>) -> bool {
        self.a != other.a || self.b != other.b
    }
}

目前 derive 仅支持标准库中部分的 Trait,我们也可以通过 procedural macros 来为自己的 Trait 实现 derive。其实,标准库里也是通过这种方式实现的,比如:Debug

相关资料

Attributes - The Rust Reference

Attributes - Rust By Example

属性 · RustPrimer