【跟小嘉学 Rust 编程】六、枚举和模式匹配

系列文章目录

【跟小嘉学 Rust 编程】一、Rust 编程基础
【跟小嘉学 Rust 编程】二、Rust 包管理工具使用
【跟小嘉学 Rust 编程】三、Rust 的基本程序概念
【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念
【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据
【跟小嘉学 Rust 编程】六、枚举和模式匹配

文章目录

  • 系列文章目录
    • @[TOC](文章目录)
  • 前言
  • 一、定义枚举
    • 1.1、定义枚举
      • 1.1.1、枚举的定义
      • 1.1.2、枚举的值
      • 1.1.3、将数据附加到枚举的变体中
    • 1.2、可选枚举(Option)
  • 二、match 流程控制结构
    • 2.1、控制流运算符(match)
    • 2.2、模式绑定值
    • 2.3、匹配 `Option`
    • 2.4、match 匹配到时候必须穷举所有的可能性
  • 三、 带有 if let 的简明控制流
    • 3.1、 if let 使用
    • 3.2、 if let 搭配 else 使用
  • 总结

前言

本章节

主要教材参考 《The Rust Programming Language》


一、定义枚举

1.1、定义枚举

1.1.1、枚举的定义

枚举允许您通过枚举其可能的变体来定义类型。使用 enum 关键字定义枚举类型。

#[allow(unused)]
#[derive(Debug)]
enum IpAddrKind {
  V4,
  V6,
}

1.1.2、枚举的值

枚举值使用 :: 获取

#[allow(unused)]
#[derive(Debug)]
enum IpAddrKind {
  V4,
  V6,
}

fn main() {
  let ipv4 =IpAddrKind::V4;
  let ipv6 = IpAddrKind::V6;

  println!("{:?}", ipv4);
  println!("{:?}", ipv6);
}

1.1.3、将数据附加到枚举的变体中

优点:

  • 不需额外使用struct 存储;
  • 每个变体可以拥有不同的类型以及关联的数据;
#[allow(unused)]
#[derive(Debug)]
enum IpAddrKind {
  V4(u8,u8,u8, u8),
  V6(String),
}

fn main() {
  let ipv4 =IpAddrKind::V4(127,0,0,1);
  let ipv6 = IpAddrKind::V6(String::from("::1"));

  println!("{:?}", ipv4);
  println!("{:?}", ipv6);
}

1.2、可选枚举(Option)

定义与标准库,用于描述一个值可能存在或者不存在的情况。在java或C/CPP之中存在有 NULL(表示空值),一个变量可能处于两种状态:空值(nulll)、非空。

可选枚举的定义

enum Option<T>{
   Some(T),
   None
}

它定义在 Prelude (预导入模块)中,可直接使用

  • Option
  • Some(T)
  • None
fn main() {
  let some_number = Some(5);
  let some_string  = Some(String::from("hello"));
  let absent_number :Option<i32> = None;
}

当你要使用 None 来初始化变量的时候,不能省略类型。Option 要想与 T 类型数据参与运算 必须先转换为 T 类型。

二、match 流程控制结构

2.1、控制流运算符(match)

  • 允许一个值与一系列模式进行匹配,并执行匹配的模式对应的代码
  • 模式可以是字面量、变量名、通配符等等
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
        	println!("lucky penny!");
        },
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

2.2、模式绑定值

匹配的分支可以绑定到被匹配对象的部分值,因此可以从 enum 变体中提取值

#[derive(Debug)] 
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

#[allow(unused)]
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> u8 {
  match coin {
      Coin::Penny => 1,
      Coin::Nickel => 5,
      Coin::Dime => 10,
      Coin::Quarter(state) => {
          println!("State quarter from {:?}!", state);
          25
      }
  }
}

fn main() {
  let c = Coin::Quarter(UsState::Alaska);
  println!("{:?}", value_in_cents(c));

}

2.3、匹配 Option

fn plus_one(x: Option<i32>) ->  Option<i32> {
  match x {
    None => None,
    Some(i) => Some(i+1),
  }
}

fn main() {
   let six = plus_one(Some(5));
   let none = plus_one(None);

   println!("{:?}", six);
   println!("{:?}", none);
}

2.4、match 匹配到时候必须穷举所有的可能性

match 匹配到时候必须穷举所有的可能性,如果不匹配就会有错误,但是我们在使用 match 匹配的时候,会有存在的可能性比较多的情况,我们可以使用 _ 来替代其余没列出的值


fn main() {
  let x:u8= 1u8;
  match x {
    1=> println!("one"),
    2=> println!("two"),
    _=> ()
  }
}

三、 带有 if let 的简明控制流

3.1、 if let 使用

if let 控制流只关心一种匹配而忽略其他匹配的情况。

  • 更少的代码,更少的缩进,更少的模板代码;
  • 放弃来穷举的可能;
fn main() {
  let config_max = Some(3u8);
  if let Some(max) = config_max {
      println!("The maximum is configured to be {}", max);
  }
}

3.2、 if let 搭配 else 使用


fn main() {
  let config_max = Some(8u8);
  if let Some(3) = config_max {
      println!("three");
  }else {
      println!("others");
  }
}

总结

以上就是今天要讲的内容

  • 1、如何定义枚举以及枚举的使用
  • 2、match 控制流
  • 3、if let 控制流

你可能感兴趣的:(跟小嘉学,Rust,编程,rust,开发语言,后端)