Bootstrap

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: 也欢迎大家评论和交流~ 更多文章也可关注微信公号:良技漫谈

;