#[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();
}