Macro
Macro和function的区别 Rust提供了一个功能非常强大的宏体系,通过这些宏,我们可以很方便的进行元编程。Rust 中的宏有点类似于函数。它们跟函数还是有很大的区别的:
1.宏以感叹号 (!) 结尾。
2.宏在编译时并不会生成一个函数调用,而是直接对宏的源代码进行展开(代替我们手工输入这部分代码)。这个和C语言中宏是一样的。从某些方面说,我们可以将宏理解为函数的加强版。
3.function必须声明函数参数的数量和类型。宏可以接受数量可变的参数:我们可以用一个参数或println!(“hello {}”, name)带有两个参数。此外,宏在编译器解释代码的含义之前被展开,因此,例如,宏可以在给定类型上实现特征。函数不能,因为它是在运行时调用的,而trait需要在编译时实现。
4.实现宏而不是函数的缺点是,宏定义比函数定义更复杂,因为您正在编写“编写Rust代码的Rust代码”。由于这种间接性,宏定义通常比函数定义更难阅读、理解和维护。
5.宏和函数之间的另一个重要区别是,在文件中调用宏之前,必须定义宏或将它们引入作用域,而函数可以在任何地方定义和调用。
micro println!() 中括号 {} 是占位符,在标准输出里面插入值。其他的特殊字符的转义跟C一样,都是使用反斜杠开头的。参数的格式化占位符:简单类型使用{}.
- {} 实现fmt::Display: Uses the {} marker. Format text in a more elegant, user friendly fashion.
fn main() {
let a = 12;
println!("a is {}", a);
}
let x = &1i8;
println!("{}",x);
println!("a is {}, a again is {}", x, x);
println!("a is {0}, a again is {0}", x);
println!("{{}}, {{ , }}"); // 输出中括号
println!("{:p}",x); // 内存地址
println!("{:.2}%", 12.345); // 保留两位小数
- {:?} && {:#?} 实现fmt::Debug: Uses the {:?} marker. Format text for debugging purposes.
#[derive(Debug)]
enum Book {
Papery,
Electronic,
}
fn main() {
let book = Book::Papery;
println!("{:?}",book);
}
-
多个占位符的情况 println!(“{1:?} {0:?} is the {actor:?} name.”, “Slater”, “Christian”, actor=“actor’s”);
-
{:p} 实现stdfmtPointer; 类型的变量,打印其内存地址。
micro panic!() 不可恢复的错误一定会导致程序受到致命的打击而终止运行。
fn main() {
panic!("error occured");
println!("Hello, Rust");
}
使用环境变量 RUST_BACKTRACE 在Winodws环境中默认使用的终端命令行是 Powershell $env:RUST_BACKTRACE=1 ; cargo run 如果你使用的是 Linux 或 macOS 等 UNIX 系统,一般情况下默认使用的是 bash 命令行,请使用以下命令: RUST_BACKTRACE=1 cargo run 回溯是不可恢复错误的另一种处理方式,它会展开运行的栈并输出所有的信息,然后程序依然会退出。 RUST_BACKTRACE=full micro todo!() 占位符,可以让方法暂时通过编译,后期再补内部代码。
fn get_book(book: &Book) -> Option<String> {
todo!() // todo means "I will do it later, please be quiet"
}
fn delete_book(book: Book) -> Result<(), String> {
todo!()
}
micro format!()
// 格式化
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
// 拼接字符串
let both = format!("{}:{}", ip, port)
micro Display
// 使用 use 关键字引入包,让他可以被访问
use std::fmt;
// 定义一个 tuple struct
struct Structure(i32);
// 手动实现 fmt 这个方法
impl fmt::Display for Structure {
// &self 是对自己的引用。
// f 是可变化的输出流。
// 返回 fmt::Result ,表示操作是成功还是失败。
// 请注意,write! 的语法与 println! 非常相似。
fn fmt(&self, f: &mut fmt==Formatter) -> fmt==Result {
write!(f, "{}", self.0)
}
}
fn main() {
println!("{}",Structure(100));
}
micro Debug 调试中,完整地显示出一个结构体实例是非常有用的。但如果我们手动的书写一个格式会非常的不方便。所以 Rust 提供了一个方便地输出一整个结构体的方法:
/// 导入调试库 #[derive(Debug)]
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
/// 在 println 和 print 宏中就可以用 {:?} 占位符输出一整个结构体
println!("rect1 is {:?}", rect1);
/// 属性较多的话可以使用另一个占位符 {:#?} 。
println!("rect1 is {:#?}", rect1);
}
stdcollectionHashMap use stdcollectionsHashMap;
fn main() { let mut map = HashMap::new(); // 插入值,存在会覆盖 map.insert(“color”,“yellow”); map.insert(“size”,“100”);
// 插入值,存在就跳过
map.entry("color").or_insert("red");
// get 返回的是Option,注意panic
println!("{}",map.get("color").unwrap());
// iterator 返回的是tuple
for p in map.iter(){
println!("{:?}",p)
}
// 在确定存在某 key 的情况下修改其值
if let Some(x) = map.get_mut("color") {
*x = "blue";
}
}