属性 Attribute
#[]
在 Rust 中被称为 属性 (Attribute)。
可以把它想象成贴在代码上的“标签”或“便利贴”。这些标签本身不是代码逻辑的一部分,但它们会给 Rust 编译器提供额外的信息或指令,告诉编译器应该如何处理紧跟在它后面的那段代码。
# 核心思想:给编译器下达指令
属性是一种元数据 (Metadata),它们在编译时起作用,用来改变编译行为。它们可以应用于几乎所有的 Rust 代码项(item),比如:
- 函数 (
fn
) - 结构体 (
struct
) - 枚举 (
enum
) - 模块 (
mod
) - 实现块 (
impl
) - 甚至整个 crate(文件)
# 两种形式:外部属性和内部属性
属性有两种语法形式,它们的区别在于作用范围:
外部属性 (Outer Attribute):
#[...]
- 这是最常见的形式,使用
#
后面跟一个中括号。 - 它作用于紧跟在其后的代码项。
- 比喻:就像给一个文件贴上一个标签,这个标签描述的是整个文件。
// 这个 `derive` 属性作用于下面的 `Point` 结构体 #[derive(Debug)] struct Point { x: i32, y: i32, } // 这个 `test` 属性将下面的 `my_test` 函数标记为一个测试函数 #[test] fn my_test() { assert_eq!(2 + 2, 4); }
1
2
3
4
5
6
7
8
9
10
11
12- 这是最常见的形式,使用
内部属性 (Inner Attribute):
#![...]
- 注意多了一个感叹号
!
。 - 它作用于包含它的父级代码项。最常见的用法是在一个文件的开头,用来对整个模块或整个 crate(程序包)进行设置。
- 比喻:就像在文件的第一页写下的指令,这个指令适用于整个文件。
// 这行代码通常放在 main.rs 或 lib.rs 的最开头 // 它告诉编译器,在这个文件(crate)里,允许存在未使用的变量而不要发出警告 #![allow(unused_variables)] fn main() { let x = 10; // 编译器不会因为 x 未被使用而警告 }
1
2
3
4
5
6
7- 注意多了一个感叹号
# 常见用途和示例
属性非常强大,用途广泛。以下是一些最常见的例子:
#[derive(...)]
:自动派生实现- 这是最常见的属性之一。它让编译器自动为你的结构体或枚举实现一些标准的 trait(特性),省去你手动编写大量样板代码的麻烦。
#[derive(Debug)]
:允许你使用{:?}
来打印这个结构体,方便调试。#[derive(Clone, Copy)]
:让你的类型可以被简单地复制。#[derive(PartialEq, Eq)]
:让你的类型可以使用==
进行比较。
#[repr(...)]
:控制内存布局#[repr(C)]
,它指示编译器使用 C 语言兼容的内存布局,这对于 FFI 编程至关重要。- 还有
#[repr(u8)]
,#[repr(i32)]
等,可以指定枚举类型在内存中用哪种大小的整数表示。
#[test]
:标记测试函数- 告诉 Rust 的测试工具,这是一个需要运行的单元测试。
#[cfg(...)]
:条件编译- 这是个非常强大的功能。它告诉编译器只有在满足特定配置(configuration)时才编译某段代码。
- 例如,只在 Windows 系统上编译某段代码:
#[cfg(target_os = "windows")] fn do_something_on_windows() { println!("This is Windows!"); }
1
2
3
4
#[allow(...)]
,#[deny(...)]
,#[warn(...)]
:控制警告和错误- 可以精细地控制编译器对某些代码模式(称为 "lints")的反应,是让它允许、警告还是直接报错。
# 总结
#[]
是 Rust 的属性语法,它是一种向编译器提供元数据和指令的机制。它不是程序的业务逻辑,而是影响代码如何被编译、测试、检查或组织。它是 Rust 语言强大、灵活和富有表现力特性的一部分。
上次更新: 2025/08/21, 15:38:56