Rust精简核心笔记:第二波,语法精髓部分解锁
前面介绍了Rust精简比较第一波 Rust精简核心笔记:第一波,深入浅出语法精华-CSDN博客 把第二波整理如下,通过三波会把全部Rust核心、实用、最简练的语法整理出来,最高效掌握Rust。
Rust精简笔记(二)
-
Rust核心笔记第二波总结整理,第七部分: match控制流结构、第八部分: 泛型&Trait&生命周期,第九部分: 集合,第八部分也是rust语言精髓特性
-
参考The Rust Programming Language & Rust in Action
七.match控制流结构
-
前面第三部分流程控制里简单说明了match使用,结合enum来看看match的更多使用场景总结
-
基础匹配语法:
let number = 2;
match number {
1 | 2 => println!("1 or 2"), // 匹配到某一个
3..=5 => println!("3到5"), // 通过 ..= 匹配值的范围
_ => println!("invalid"), //未匹配到 _
}
match 解构结构体:
struct Point {
x: i32,
y: i32,
}
fn main() {
let p = Point { x: 0, y: 7 };
let Point { x: a, y: b } = p;
assert_eq!(0, a);
assert_eq!(7, b);
}
解构枚举:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let msg = Message::ChangeColor(0, 160, 255);
match msg {
Message::Quit => {
println!("The Quit variant has no data to destructure.")
}
Message::Move { x, y } => {
println!(
"Move in the x direction {} and in the y direction {}",
x, y
);
}
Message::Write(text) => println!("Text message: {}", text),
Message::ChangeColor(r, g, b) => println!(
"Change the color to red {}, green {}, and blue {}",
r, g, b
),
}
}
//打印结果到change the color....
解构嵌套的结构体和枚举:
enum Color {
Rgb(i32, i32, i32),
Hsv(i32, i32, i32),
}
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(Color),
}
fn main() {
let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
match msg {
Message::ChangeColor(Color::Rgb(r, g, b)) => println!(
"Change the color to red {}, green {}, and blue {}",
r, g, b
),
Message::ChangeColor(Color::Hsv(h, s, v)) => println!(
"Change the color to hue {}, saturation {}, and value {}",
h, s, v
),
_ => (),
}
}
用 .. 忽略剩余值:
//通过使用 .. 来忽略 Point 中除 x 以外的字段
fn main() {
struct Point {
x: i32,
y: i32,
z: i32,
}
let origin = Point { x: 0, y: 0, z: 0 };
match origin {
Point { x, .. } => println!("x is {}", x),
}
}
Match guards:
-
• 匹配守卫(match guard)是一个指定于 match 分支模式之后的额外 if 条件,它也必须被满足才能选择此分支
fn main() {
let num = Some(4);
match num {
Some(x) if x < 5 => println!("less than five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
}
@绑定:
-
运算符@,允许我们在创建一个存放值的变量的同时,测试其值是否匹配模式。即@ 可以在一个模式中同时测试和保存变量值。
fn main() {
enum Message {
Hello { id: i32 },
}
let msg = Message::Hello { id: 5 };
match msg {
Message::Hello {
id: id_variable @ 3..=7, //使用id_variable变量配合@,以便此分支相关联的代码可以使用它
} => println!("Found an id in range: {}", id_variable),
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
Message::Hello { id } => println!("Found some other id: {}", id),
}
}
八,泛型、Trait、生命周期
泛型:
-
函数定义中使用泛型
fn largest<T>(list: &[T]) -> T {
}
//函数 largest 有泛型类型 T。它有个参数 list,其类型是元素为 T 的 slice。largest 函数的返回值类型也是 T
//类型参数声明位于函数名称与参数列表中间的尖括号 <>
-
结构体定义中的泛型
struct Point<T> {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 };
let float = Point { x: 1.0, y: 4.0 };
}
-
枚举定义中的泛型
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
-
方法定义中的泛型
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
fn main() {
let p = Point { x: 5, y: 10 };
println!("p.x = {}", p.x());
}
Trait:
-
通过 trait 以一种抽象的方式定义共享的行为,trait 类似于其他语言中的接口,但也不完全一样.
//定义 trait Summary ,定义summarize调取->summarize_author默认方法,达到调用默认行为,区分开实现trait的的定义
pub trait Summary {
fn summarize_author(&self) -> String;
fn summarize(&self) -> String {
format!("(Read more from {}...)", self.summarize_author())
}
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
//实现 trait Summary
impl Summary for Tweet {
fn summarize_author(&self) -> String {
format!("@{}", self.username)
}
}
fn main() {
let tweet = Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
};
println!("1 new tweet: {}", tweet.summarize());
}
-
trait 作为参数:
// 方法接收是实现了 trait Summary的类型
pub fn notify(item: &impl Summary) {
println!("Breaking news! {}", item.summarize());
}
-
Trait Bound: impl Trait 适用于短小的例子。trait bound 则适用于更复杂的场景,trait bound 与泛型参数声明在一起,位于尖括号中的冒号后面。
//使用相同类型的trait可以转换成下边的更简单写法
pub fn notify(item1: &impl Summary, item2: &impl Summary) {}
// trait Bound的写法
pub fn notify<T: Summary>(item1: &T, item2: &T) {}
-
通过
+
指定多个 trait bound:
pub fn notify<T: Summary + Display>(item: &T) {}
-
通过
where
简化 trait bound:每个泛型有其自己的 trait bound,所以有多个泛型参数的函数在名称和参数列表之间会有很长的 trait bound 信息,这使得函数签名难以阅读
fn some_function<T, U>(t: &T, u: &U) -> i32
where T: Display + Clone,
U: Clone + Debug
{
}
声明周期:
-
Rust 中的每一个引用都有其 生命周期(lifetime),也就是引用保持有效的作用域,Rust 编译器有一个借用检查器(borrow checker)它比较作用域来确保所有的借用都是有效的
-
函数签名中的生命周期注解:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let string1 = String::from("abcd");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is {}", result);
}
-
参数声明周期使用方法,或者靠编译器提示添加。
&i32 // 引用, 没有生命周期参数的 i32 的引用
&'a i32 // 带有显式生命周期的引用 ,一个有叫做 'a 的生命周期参数的 i32 的引用
&'a mut i32 // 带有显式生命周期的可变引用 一个生命周期也是 'a 的 i32 的可变引用
-
结构体定义中的生命周期注解:
struct ImportantExcerpt<'a> {
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let i = ImportantExcerpt {
part: first_sentence,
};
}
-
静态生命周期:
-
生命周期能够存活于整个程序期间。所有的字符串字面值都拥有 'static 生命周期
let s: &'static str = "I have a static lifetime.";
九,集合:
vector:
-
类型是 Vec
在内存中彼此相邻地排列所有的值, vector 只能储存相同类型的值
// Vec::new 创建
let v: Vec<i32> = Vec::new();
v.push(2);
v.push(4);
let x = v.pop();
-
初始值来创建一个 Vec :
let v = vec![1, 2, 3];
-
读取 vector 的元素: 使用 &[index] 返回一个引用, 或者使用 get 方法以索引作为参数来返回一个 Option<&T>。
fn main() {
let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];
println!("The third element is {}", third);
match v.get(2) {
Some(third) => println!("The third element is {}", third),
None => println!("There is no third element."),
}
}
-
使用枚举来储存多种类型: 创建一个储存枚举值的 vector,这样最终就能够通过vector存储实际是不同类型的值了
fn main() {
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];
}
HashMap
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10); //插入
//只在键没有对应值时插入
scores.entry(String::from("Yellow")).or_insert(50);
scores.entry(String::from("Blue")).or_insert(50);
println!("{:?}", scores);
第二波先介绍到这里,后边会把第三波的整理出来,这些精简的笔记也可以做为日常学习rust回顾、知识点速查等。
PS: 也欢迎大家评论和交流~ 更多文章也可关注微信公号:良技漫谈