Skip to main content

Rust 宏使用方法以及属性说明

Rust
KIGA
Author
KIGA
This is a personal blog, intended for sharing.
Table of Contents

#[derive(Debug)] 是一个 Rust 内置的属性,用于为结构体或枚举类型自动生成 Debug trait 的实现。

#[derive(Clone)] 是 Rust 的一个属性,它可以自动生成一个结构体或枚举的 Clone trait 实现。

#[cfg(test)] 是一个 Rust 内置的属性,用于指定只在运行测试时才编译和执行代码。 当 Rust 编译器遇到 #[cfg(test)] 属性时,它会检查当前是否正在运行测试,如果是,则编译和执行代码,否则忽略代码。这个属性通常用于测试代码中,以避免测试代码对生产环境造成影响。

#[test] 是一个 Rust 内置的属性,用于标记一个测试函数。 当 Rust 编译器遇到 #[test] 属性时,它会将该函数作为一个测试函数编译和执行。测试函数通常用于测试代码中,以验证代码的正确性。

#[should_panic]是一个属性(Attribute),用于测试函数中的断言。当测试函数中的代码块抛出了一个异常时,#[should_panic]可以用来指示测试框架该测试函数是否应该通过。

#[cfg(test)]
mod my_module {
    #[test]
    #[should_panic]
    fn t(){
        let a = 12;
        assert_eq!(a , 13);        
    }
}
// rustc --test test.rs && ./test
/*
running 1 test
test my_module::t - should panic ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
*/

#![allow(unused)] 是 Rust 中的一个编译器指令,它告诉编译器忽略未使用的变量或未使用的代码的警告。 如果有一个未使用的变量,但是不想看到编译器的警告,可以在代码的顶部添加 #![allow(unused)] 指令。 这样编译器就不会再提示未使用变量的警告了。

mod tests 定义了一个名为 tests 的模块,其中包含一个测试函数 test_add,它使用 assert_eq! 宏来验证 2 + 2 是否等于 4。

#[cfg(test)]
mod tests {
    #[test]
    fn test_add() {
        assert_eq!(2 + 2, 4);
    }
}
use super::*;

可以用来导入当前模块的父模块中的所有公共项,以便在当前模块中直接使用这些项,而不需要使用完整的路径。

#[warn(unused_imports)] 是 Rust 中的一个编译器指令,它告诉编译器在编译时检查未使用的导入并发出警告。如果你在代码中导入了一个模块,但是没有使用它,编译器就会发出警告。

trait 代码示例
#

// Clone trait
#[derive(Clone)]
struct Person {
    name: String,
    age: u32,
}

let person1 = Person {
    name: String::from("Alice"),
    age: 30,
};

let person2 = person1.clone();

assert_eq!(person1.name, person2.name);
assert_eq!(person1.age, person2.age);

// Debug trait
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

let rect = Rectangle { width: 30, height: 50 };
println!("{:?}", rect);

// Default trait
#[derive(Default)]
struct Point {
    x: i32,
    y: i32,
}

let point = Point::default();
assert_eq!(point.x, 0);
assert_eq!(point.y, 0);

// Display trait
use std::fmt;

struct Person {
    name: String,
    age: u32,
}

impl fmt::Display for Person {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} ({})", self.name, self.age)
    }
}

let person = Person { name: String::from("Alice"), age: 30 };
println!("{}", person);

// Iterator trait
let v = vec![1, 2, 3];

for i in v.iter() {
    println!("{}", i);
}

// PartialEq trait
#[derive(PartialEq)]
struct Person {
    name: String,
    age: u32,
}

let person1 = Person { name: String::from("Alice"), age: 30 };
let person2 = Person { name: String::from("Alice"), age: 30 };

assert_eq!(person1, person2);

// TryFrom trait
use std::convert::TryFrom;

#[derive(Debug, PartialEq)]
enum Error {
    InvalidValue,
}

impl TryFrom<u32> for Person {
    type Error = Error;

    fn try_from(value: u32) -> Result<Self, Self::Error> {
        if value > 100 {
            Ok(Person { name: String::from("Alice"), age: value })
        } else {
            Err(Error::InvalidValue)
        }
    }
}

let person = Person::try_from(101).unwrap();
assert_eq!(person, Person { name: String::from("Alice"), age: 101 });

String and &str
#

String 是一个可变的字符串类型,它是由标准库提供的,可以用来存储和操作 UTF-8 编码的字符串。String 类型的数据在堆上分配,可以动态地增加或减少其长度。

&str 是一个不可变的字符串类型,它是一个指向 UTF-8 编码字符串的引用。&str 类型的数据通常是从 String 类型的数据中获取的,或者是字符串字面量(例如 “hello”)。

因为 &str 是一个引用类型,所以它的生命周期必须与其引用的数据相同。而 String 类型的数据可以在堆上分配,因此它的生命周期可以比其引用的数据更长。

在 Rust 中,通常使用 String 类型来处理需要动态分配内存的字符串,而使用 &str 类型来处理不需要动态分配内存的字符串。

fn string_slice(arg: &str) {
    println!("{}", arg);
}
fn string(arg: String) {
    println!("{}", arg);
}

fn main() {
    string_slice("blue");
    string_slice(&String::from("abc")[0..1]);
    string_slice("  hello there ".trim());

    string("red".to_string());
    string(String::from("hi"));
    string("rust is fun!".to_owned());
    string("nice weather".into());
    string(format!("Interpolation {}", "Station"));
    string("Happy Monday!".to_string().replace("Mon", "Tues"));
    string("mY sHiFt KeY iS sTiCkY".to_lowercase());
}

mod
#

mod 关键字用于定义模块。模块是 Rust 中的命名空间,它可以包含函数、结构体、枚举、常量等项。模块可以嵌套,形成层次结构。

在一个 Rust 程序中,通常会将相关的项放在同一个模块中,以便更好地组织代码。模块可以定义在文件中,也可以定义在代码块中

// 定义一个名为 my_module 的模块
mod my_module {
    // 在 my_module 模块中定义一个函数
    pub fn my_function() {
        println!("Hello from my_function!");
    }
}

fn main() {
    // 调用 my_module 模块中的函数
    my_module::my_function();
}