当前位置: 首页 > news >正文

棒的外贸网站建设crm与scrm

棒的外贸网站建设,crm与scrm,怎么推广自己的微信号,建设网站需要懂什么上一篇#xff1a;05-使用结构体构建相关数据 在本章中#xff0c;我们将介绍枚举。枚举允许你通过枚举其可能的变体来定义一种类型。首先#xff0c;我们将定义并使用一个枚举#xff0c;以展示枚举如何与数据一起编码意义。接下来#xff0c;我们将探索一个特别有用的枚…上一篇05-使用结构体构建相关数据 在本章中我们将介绍枚举。枚举允许你通过枚举其可能的变体来定义一种类型。首先我们将定义并使用一个枚举以展示枚举如何与数据一起编码意义。接下来我们将探索一个特别有用的枚举名为 Option 它表示一个值可以是 有 或 无。然后我们将了解 match 表达式中的模式匹配如何使我们能够轻松地针对枚举的不同值运行不同的代码。最后我们将介绍 if let 结构是如何在代码中处理枚举的另一个方便简洁的方式。 1. 定义枚举 结构体提供了一种将相关字段和数据组合在一起的方法如 Rectangle 及其 width 和 height 而枚举则提供了一种表示某个值是一组可能值之一的方法。例如我们可能想说 Rectangle 是一组可能的形状之一其中还包括 Circle 和 Triangle 。为此Rust 允许我们将这些可能性编码为一个枚举。 让我们来看看我们可能想在代码中表达的一种情况看看为什么在这种情况下枚举是有用的而且比结构体更合适。假设我们需要处理 IP 地址。目前IP 地址使用两种主要标准第四版和第六版。由于我们的程序只会遇到这两种可能的 IP 地址因此我们可以枚举所有可能的变体这就是枚举名称的由来。 任何 IP 地址都可以是版本 4 或版本 6 地址但不能同时是这两种。IP 地址的这一特性使得枚举数据结构非常适合因为枚举值只能是其变体之一。从根本上说版本 4 和版本 6 地址都是 IP 地址因此在代码处理适用于任何类型 IP 地址的情况时应将它们视为同一类型。 我们可以通过定义 IpAddrKind 枚举并列出 IP 地址的可能类型 V4 和 V6 来用代码表达这一概念。这些就是枚举的变体 enum IpAddrKind {V4,V6, }IpAddrKind 现在是一种自定义数据类型我们可以在代码的其他地方使用它。 1.1 枚举值 我们可以像这样为 IpAddrKind 的两个变体分别创建实例 let four IpAddrKind::V4; let six IpAddrKind::V6;请注意枚举的变体是在其标识符下命名的我们使用双冒号分隔两者。这样做很有用因为现在 IpAddrKind::V4 和 IpAddrKind::V6 的值都属于同一类型 IpAddrKind 。例如我们可以定义一个接收任意 IpAddrKind 的函数 我们可以用任意一个变量来调用这个函数 route(IpAddrKind::V4); route(IpAddrKind::V6);使用枚举还有更多优势。再想想我们的 IP 地址类型目前我们还没有存储实际 IP 地址数据的方法我们只知道它是什么类型。鉴于您了解了结构体您可能会想使用结构体来解决这个问题如下所示 enum IpAddrKind {V4,V6, }struct IpAddr {kind: IpAddrKind,address: String, }let home IpAddr {kind: IpAddrKind::V4,address: String::from(127.0.0.1), };let loopback IpAddr {kind: IpAddrKind::V6,address: String::from(::1), };在这里我们定义了一个结构 IpAddr 它有两个字段一个是 IpAddrKind 类型的 kind 字段我们之前定义的枚举另一个是 String 类型的 address 字段。这个结构体有两个实例。第一个实例是 home 其值为 IpAddrKind::V4 kind 相关地址数据为 127.0.0.1 。第二个实例是 loopback 。它的 kind 值是 IpAddrKind 的另一个变体即 V6 并关联了地址 ::1 。我们使用结构体将 kind 和 address 的值捆绑在一起因此现在变体与值相关联。 不过使用枚举来表示相同的概念更为简洁我们可以将数据直接放入每个枚举变体中而不是将枚举放在结构体中。 IpAddr 枚举的新定义指出 V4 和 V6 变量都有相关的 String 值 enum IpAddr {V4(String),V6(String), }let home IpAddr::V4(String::from(127.0.0.1));let loopback IpAddr::V6(String::from(::1));我们直接为枚举的每个变量附加数据因此不需要额外的结构体。在这里我们还可以更容易地了解枚举的另一个工作细节我们定义的每个枚举变量的名称都会成为一个函数用来构造枚举的实例。也就是说 IpAddr::V4() 是一个函数调用它接收 String 参数并返回 IpAddr 类型的实例。在定义枚举时我们自动获得了这个构造函数。 使用枚举而不是结构体还有另一个好处每个变量可以有不同类型和数量的相关数据。四个版本的 IP 地址总是有四个数值部分数值范围在 0 到 255 之间。如果我们想将 V4 地址存储为四个 u8 值但又想将 V6 地址表示为一个 String 值那么我们就无法使用结构体。枚举可以轻松处理这种情况 enum IpAddr {V4(u8, u8, u8, u8),V6(String), }let home IpAddr::V4(127, 0, 0, 1);let loopback IpAddr::V6(String::from(::1));我们已经展示了几种不同的方法来定义数据结构以存储第四版和第六版 IP 地址。然而事实证明存储 IP 地址并对其类型进行编码的需求非常普遍标准库中也有我们可以使用的定义让我们来看看标准库是如何定义 IpAddr 的它拥有与我们定义和使用的完全相同的枚举和变体但它将地址数据以两个不同结构体的形式嵌入到变体中每个变体的定义都不同 struct Ipv4Addr {// --snip-- }struct Ipv6Addr {// --snip-- }enum IpAddr {V4(Ipv4Addr),V6(Ipv6Addr), }这段代码说明你可以在枚举变量中放入任何类型的数据例如字符串、数字类型或结构体。甚至还可以包含另一个枚举另外标准库中的类型通常不会比你想出的复杂多少。 请注意即使标准库包含 IpAddr 的定义我们仍然可以创建并使用自己的定义而不会发生冲突因为我们没有将标准库的定义引入我们的作用域。(即命名空间) 下面的枚举示例变体中嵌入了多种类型。 enum Message {Quit,Move { x: i32, y: i32 },Write(String),ChangeColor(i32, i32, i32), }该枚举有四个不同类型的变量 ①. Quit 完全没有相关数据 ②. Move 具有命名字段就像结构体一样      ③. Write 包括一个 String ④. ChangeColor 包括三个 i32类型的参数 定义枚举的变体类似于定义不同类型的结构体定义只是枚举不使用 struct 关键字而且所有变体都集中在 Message 类型下。下面的结构体可以保存与前面的枚举变体相同的数据 struct QuitMessage; // unit struct struct MoveMessage {x: i32,y: i32, } struct WriteMessage(String); // tuple struct struct ChangeColorMessage(i32, i32, i32); // tuple struct但是如果我们使用不同的结构体每个结构体都有自己的类型我们就不能像使用清Message 枚举它是一个单一类型那样轻松定义一个函数来接收这些类型的任何信息。 枚举和结构体之间还有一个相似之处正如我们可以使用 impl 在结构体上定义方法一样我们也可以在枚举上定义方法。下面是一个名为 call 的方法我们可以在 Message 枚举上定义这个方法 impl Message {fn call(self) {// method body would be defined here} }let m Message::Write(String::from(hello)); m.call();方法的主体将使用 self 来获取我们调用方法的值。在本例中我们创建了一个变量 m 其值为 Message::Write(String::from(hello)) 当 m.call() 运行时 self 将出现在 call 方法的主体中。 让我们来看看标准库中另一个非常常见和有用的枚举 Option 1.2 Option 枚举及其与空值相比的优势 本节将对 Option 进行案例研究这是标准库定义的另一个枚举。 Option 类型编码了一种非常常见的情况即一个值可能是什么也可能什么都不是。 例如如果您请求非空列表中的第一个项目您将得到一个值。如果请求空列表中的第一项则什么也得不到。用类型系统来表达这一概念意味着编译器可以检查您是否处理了所有应该处理的情况这一功能可以防止其他编程语言中极为常见的 bug。 编程语言的设计通常会考虑包含哪些功能但排除哪些功能也很重要。Rust 没有许多其他语言所具有的 null 功能。Null 是一个表示没有值的值。在有 null 的语言中变量总是处于两种状态之一null 或 not-null。 在 2009 年的演讲 null十亿美元的错误 的演讲中null 的发明者托尼-霍尔Tony Hoare这样说道 我称它为我的 十亿美元错误。当时我正在为面向对象语言中的引用设计第一个全面的类型系统。我的目标是确保所有引用的使用都绝对安全并由编译器自动进行检查。但是我无法抵制加入空引用的诱惑因为这太容易实现了。这导致了无数的错误、漏洞和系统崩溃在过去的四十年里这些错误和漏洞可能造成了数十亿美元的损失。 空值的问题在于如果试图将空值用作非空值就会出现某种错误。由于 null 或 not-null 属性普遍存在因此极易出现这种错误。 不过null 所要表达的概念仍然很有用空值是指由于某种原因当前无效或不存在的值。 问题其实不在于概念而在于特定的实现。因此Rust 没有空值但有一个枚举可以编码值存在或不存在的概念。这个枚举就是 OptionT 标准库对它的定义如下 enum OptionT {None,Some(T), }OptionT 枚举非常有用甚至已包含在前奏中您无需明确将其纳入作用域。其变体也包含在前奏中您可以直接使用 Some 和 None 而无需 Option:: 前缀。 OptionT 枚举仍然只是一个普通的枚举而 Some(T) 和 None 仍然是 OptionT 类型的变体。 T 语法是我们尚未讨论过的 Rust 特性。它是一个泛型类型参数现在你只需知道 T 意味着 Option 枚举的 Some 变体可以容纳一个任意类型的数据而每一个用来代替 T 的具体类型都会使 OptionT 整体类型成为一个不同的类型。下面是一些使用 Option 值来保存数字类型和字符串类型的示例 let some_number Some(5); let some_char Some(e);let absent_number: Optioni32 None;some_number 的类型是 Optioni32 。 some_char 的类型是 Optionchar 这是一种不同的类型。Rust 可以推断出这些类型因为我们在 Some 变体中指定了一个值。对于 absent_number Rust 要求我们注解整个 Option 的类型编译器无法仅通过查看 None 值来推断相应的 Some 变体将持有的类型。在这里我们告诉 Rust我们的意思是 absent_number 属于 Optioni32 类型。 当我们有一个 Some 值时我们知道有一个值存在并且该值被保存在 Some 中。当我们有一个 None 值时从某种意义上说它的含义与 null 相同我们没有一个有效的值。那么为什么 OptionT 会比 null 好呢 简而言之由于 OptionT 和 T 其中 T 可以是任何类型是不同的类型编译器不会让我们把 OptionT 值当作有效值来使用。例如这段代码无法编译因为它试图将 i8 添加到 Optioni8 中 let x: i8 5; let y: Optioni8 Some(5);let sum x y;如果我们运行这段代码就会得到这样一条错误信息 cargo.exe buildCompiling enum_type v0.1.0 (D:\rustProj\enum_type) error[E0277]: cannot add Optioni8 to i8-- src\main.rs:4:17| 4 | let sum x y;| ^ no implementation for i8 Optioni8| help: the trait AddOptioni8 is not implemented for i8 help: the following other types implement trait AddRhs:i8 as Addi8 as Addi8a i8 as Addi8i8 as Addi8For more information about this error, try rustc --explain E0277. error: could not compile enum_type (bin enum_type) due to previous error 强烈实际上这条错误信息意味着 Rust 不理解如何添加 i8 和 Optioni8 因为它们是不同的类型。在 Rust 中当我们有一个像 i8 这样类型的值时编译器会确保我们始终有一个有效的值。在使用该值之前我们无需检查其是否为空就可以放心地继续编译。只有当我们有一个 Optioni8 或其他任何类型的值时我们才需要担心可能没有值编译器会确保我们在使用该值前处理这种情况。 换句话说在对 OptionT 执行 T 操作之前必须先将转换为 T 。一般来说这有助于解决 null 最常见的问题之一假设某个东西不是 null而实际上它是 null。 消除错误假定非空值的风险可以让您对自己的代码更有信心。为了获得可能为空的值您必须显式地选择将该值的类型设为 OptionT 。然后在使用该值时必须明确处理该值为空的情况。只要值的类型不是 OptionT 就可以放心地认为该值不是空值。这是 Rust 故意的设计决策目的是限制 null 的普遍存在并提高 Rust 代码的安全性。 那么当您有一个 OptionT 类型的值时如何从 Some 变体中获取 T 值以便使用该值呢 OptionT 枚举拥有大量在各种情况下都非常有用的方法您可以在其文档中查看这些方法。熟悉 OptionT 上的方法将对你的 Rust 之旅大有裨益。 一般来说要使用 OptionT 值需要有代码来处理每个变量。您希望某些代码只在有 Some(T) 值的情况下运行而这些代码可以使用内部的 T 。而另一些代码只有在有 None 值时才运行且该代码没有可用的 T 值。 match 表达式是一种控制流结构当与枚举一起使用时它就能做到这一点它将根据枚举的变体运行不同的代码而这些代码可以使用匹配值内部的数据。 2. match 控制流结构 Rust 有一个非常强大的控制流结构叫做 match 它允许你将一个值与一系列模式进行比较然后根据哪种模式匹配来执行代码。模式可以由字面值、变量名、通配符和许多其他内容组成match 的威力来自于模式的表现力以及编译器确认所有可能的情况都已得到处理这一事实。 可以把 match 表达式想象成一台硬币分拣机硬币在轨道上滑动轨道上有大小不一的孔每枚硬币都从它遇到的第一个适合的孔中滑落。同样数值会穿过 match 中的每个图案在数值 适合 的第一个图案处数值会落入相关的代码块中以便在执行过程中使用。 说到硬币让我们以 match 为例我们可以编写一个函数接收一枚未知的美制硬币然后以类似于点钞机的方式确定它是哪一枚硬币并返回其价值以美分为单位如下面代码所示 enum Coin {Penny,Nickel,Dime,Quarter, }fn value_in_cents(coin: Coin) - u8 {match coin {Coin::Penny 1,Coin::Nickel 5,Coin::Dime 10,Coin::Quarter 25,} }让我们分解一下 value_in_cents 函数中的 match 。首先我们列出 match 关键字然后是一个表达式在本例中是值 coin 。这似乎与 if 中使用的条件表达式非常相似但有一个很大的区别在 if 中条件需要求值为布尔值但这里可以是任何类型。本例中 coin 的类型是我们在第一行定义的 Coin 枚举。 接下来是 match arm。arm由两部分组成一个模式和一些代码。第一个arm的模式是 Coin::Penny 然后是 运算符它将模式和要运行的代码分开。这里的代码就是 1 。每个分支之间用逗号隔开。 match 表达式执行时会依次将结果值与每个arm的模式进行比较。如果某个模式与数值匹配则执行与该模式相关的代码。如果该模式与数值不匹配则继续执行下一个arm就像硬币排序机一样。我们可以根据需要设置多个臂在上述代码中我们的 match 有三个arm。 与每个arm相关的代码都是一个表达式匹配arm中表达式的结果值就是整个 match 表达式返回的值。 如果匹配arm代码很短我们通常不使用大括号就像上述代码中那样每个匹配arm只返回一个值。如果要在一个匹配arm中运行多行代码则必须使用大括号而且匹配臂后面的逗号是可选的。例如下面的代码在每次调用 Coin::Penny 方法时都会打印 Lucky Jiao 但仍会返回代码块的最后一个值 10 fn value_in_cents(coin: Coin) - u8 {match coin {Coin::Penny {println!(Lucky penny!);1}Coin::Nickel 5,Coin::Dime 10,Coin::Quarter 25,} }2.1 绑定值的模式 匹配arm的另一个有用特性是它们可以绑定到与模式匹配的值的部分。这就是我们从枚举变体中提取值的方法。 举个例子让我们改变其中一个枚举变量在它内部保存数据。从 1999 年到 2008 年美国铸造了 50 个州一面图案各不相同的 25 分硬币。其他硬币都没有州的图案因此只有 25 美分硬币有这种额外的价值。我们可以通过修改 Quarter 变量将 UsState 值存储到 enum 中从而将此信息添加到 中具体做法如下 #[derive(Debug)] // so we can inspect the state in a minute enum UsState {Alabama,Alaska,// --snip-- }enum Coin {Penny,Nickel,Dime,Quarter(UsState), }假设一位朋友正在努力收集 50 个州的硬币。当我们按照硬币种类对零钱进行分类时我们也会喊出与每个25美分硬币相关的州名这样如果我们的朋友没有这个硬币他们就可以将其添加到自己的收藏中。 在这段代码的匹配表达式中我们在模式中添加了一个名为 state 的变量用于匹配变体 Coin::Quarter 的值。当 Coin::Quarter 匹配时 state 变量将绑定到该quarter的状态值。然后我们就可以在该arm的代码中使用 state 就像这样 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}} }如果我们调用 value_in_cents(Coin::Quarter(UsState::Alaska)) coin 就是 Coin::Quarter(UsState::Alaska) 。当我们将该值与每个匹配臂进行比较时在到达 Coin::Quarter(state) 之前没有一个匹配arm是匹配的。此时 state 的绑定值将是 UsState::Alaska 。然后我们就可以在 println! 表达式中使用该绑定从而从 Coin 枚举变体中获得 Quarter 的内部状态值。 如果我们调用 value_in_cents(Coin::Quarter(UsState::Alaska)) coin 就是 Coin::Quarter(UsState::Alaska) 。当我们将该值与每个匹配臂进行比较时在到达 Coin::Quarter(state) 之前没有一个匹配臂是匹配的。此时 state 的绑定值将是 UsState::Alaska 。然后我们就可以在 println! 表达式中使用该绑定从而从 Coin 枚举变体中获得 Quarter 的内部状态值。 #[derive(Debug)] // so we can inspect the state in a minute enum UsState {Alabama,Alaska,// --snip-- }enum Coin {Penny,Nickel,Dime,Quarter(UsState), }fn main() {let money Coin::Quarter(UsState::Alaska);value_in_cents(money); }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}} }运行结果为 cargo.exe runCompiling match_flow v0.1.0 (D:\rustProj\match_flow)Finished dev [unoptimized debuginfo] target(s) in 0.66sRunning target\debug\match_flow.exe State quarter from Alaska! 2.2 Matching with OptionT 与 OptionT 在上一节中我们希望在使用 OptionT 时从 Some 的情况下获取 T 的内部值我们也可以使用 match 来处理 OptionT 就像处理 Coin 枚举一样我们不比较硬币而是比较 OptionT 的变体但 match 表达式的工作方式保持不变。 比方说我们要编写一个函数接收 Optioni32 如果里面有一个值就在该值上加 1。如果里面没有值函数应该返回 None 而不试图执行任何操作。 由于使用了 match 该函数的编写非常简单与下面代码类似。 fn plus_one(x: Optioni32) - Optioni32 {match x {None None,Some(i) Some(i 1),} }let five Some(5); let six plus_one(five); let none plus_one(None);让我们详细研究一下 plus_one 的第一次执行。当我们调用 plus_one(five) 时 plus_one 主体中的变量 x 的值为 Some(5) 。然后我们将其与每个匹配arm进行比较 None None,Some(5) 值与模式 None 不匹配因此我们继续下一个arm Some(i) Some(i 1), Some(5) 与 Some(i) 匹配吗匹配我们有相同的变体。 i 与 Some 中的值绑定因此 i 的值为 5 。然后执行匹配arm中的代码在 i 的值上加 1并创建一个新的 Some 值其中包含我们的总 6 。 现在我们来看看plus_one 的第二次调用其中 x 就是 None 。我们输入 match 并与第一arm进行比较 None None, 匹配没有值可添加因此程序停止并返回 右侧的 None 值。由于第一个arm匹配因此不再比较其他arm。 在很多情况下将 match 与枚举结合起来是非常有用的。在 Rust 代码中你会经常看到这种模式 match 对应一个枚举将一个变量与枚举中的数据绑定然后根据枚举执行代码。一开始有点麻烦但一旦习惯了你就会希望在所有语言中都能使用它。它一直是用户的最爱。 2.3 匹配详尽 我们还需要讨论 match 的另一个方面arm的模式必须涵盖所有可能性。请看我们这个版本的 plus_one 函数它有一个错误无法编译 fn main() {let five Some(5);let six plus_one(five);let none plus_one(None); }fn plus_one(x: Optioni32) - Optioni32 {match x {Some(i) Some(i 1),} } 我们没有处理 None 的情况因此这段代码会导致错误。幸运的是Rust 知道如何捕获这个错误。如果我们尝试编译这段代码就会出现这个错误 cargo.exe runCompiling match_flow v0.1.0 (D:\rustProj\match_flow) error[E0004]: non-exhaustive patterns: None not covered-- src\main.rs:5:11| 5 | match x {| ^ pattern None not covered| note: Optioni32 defined here-- /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112\library\core\src\option.rs:569:1::: /rustc/82e1608dfa6e0b5569232559e3d385fea5a93112\library\core\src\option.rs:573:5| note: not covered note: the matched value is of type Optioni32 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown| 6 ~ Some(i) Some(i 1), 7 ~ None todo!(),|For more information about this error, try rustc --explain E0004. error: could not compile match_flow (bin match_flow) due to previous error Rust 知道我们没有涵盖所有可能的情况甚至知道我们忘记了哪种模式Rust 中的匹配是穷举性的我们必须穷举每一种可能代码才能有效。特别是在 OptionT 的情况下当 Rust 防止我们忘记显式处理 None 的情况时它保护了我们使我们不会在可能有 null 的情况下假设我们有一个值从而使前面讨论的价值十亿美元的错误不可能发生。 2.4 万能模式和 “_”占位符 使用枚举我们还可以对一些特定值采取特殊操作而对所有其他值采取默认操作。试想一下我们在实现一个游戏时如果掷骰子掷出 3玩家不会移动但会得到一顶新的花式帽子。如果掷出的骰子是 7玩家就会失去一顶华丽的帽子。对于所有其他数值玩家都会在游戏板上移动相应数量的空间。下面是实现该逻辑的 match 其中掷骰子的结果是硬编码而不是随机值所有其他逻辑都由没有主体的函数表示因为实际实现这些函数不在本例的范围之内 let dice_roll 9; match dice_roll {3 add_fancy_hat(),7 remove_fancy_hat(),other move_player(other), }fn add_fancy_hat() {} fn remove_fancy_hat() {} fn move_player(num_spaces: u8) {}对于前两个arm模式是字面值 3 和 7 。对于涵盖所有其他可能值的最后一个arm模式是我们选择命名为 other 的变量。 other分支运行代码通过将变量传递给 move_player 函数来使用该变量。 即使我们没有列出 u8 可能具有的所有值这段代码也能编译成功因为最后一个模式将匹配所有未具体列出的值。这种包罗万象的模式符合 match 必须详尽无遗的要求。需要注意的是我们必须把 catch-all arm 放在最后因为模式是按顺序评估的。如果我们把 全包 arm放在前面其他arm就不会运行所以如果我们在 全包 arm之后添加armRust 就会发出警告 Rust 还有一种模式当我们需要一个 catch-all但又不想使用 catch-all 模式中的值时可以使用 _ 是一种特殊的模式它可以匹配任何值但不会绑定到该值。这告诉 Rust 我们不会使用该值因此 Rust 不会警告我们存在未使用的变量。 让我们改变一下游戏规则现在如果掷出的不是 3 或 7就必须再掷一次。我们不再需要使用万能值因此可以修改代码使用 _ 代替名为 other 的变量 fn main() {let dice_roll 9;match dice_roll {3 add_fancy_hat(),7 remove_fancy_hat(),_ reroll(),} }fn add_fancy_hat() {} fn remove_fancy_hat() {} fn reroll() {}这个例子也符合穷举要求因为我们明确忽略了最后一arm中的所有其他值我们没有遗忘任何东西。 最后我们再改变一次游戏规则如果掷出的不是 3 或 7则在你的回合中不会发生任何其他事情。我们可以通过使用单位值我们在 元组类型 一节中提到的空元组类型作为 “_”的arm 分支代码来表达这一点 fn main() {let dice_roll 9;match dice_roll {3 add_fancy_hat(),7 remove_fancy_hat(),_ (),} }fn add_fancy_hat() {} fn remove_fancy_hat() {}在这里我们明确地告诉 Rust我们不会使用任何不符合先前臂中模式的其他值而且我们不想在这种情况下运行任何代码。 3. if let简明控制流 if let 语法使您可以将 if 和 let 结合起来以一种不那么冗长的方式来处理只匹配一种模式而忽略其他模式的值。请看如下代码示例它与 config_max 变量中的 Optionu8 值匹配但只想在该值是 Some 变体时执行代码。 let config_max Some(3u8); match config_max {Some(max) println!(The maximum is configured to be {}, max),_ (), }如果值是 Some 我们就将该值绑定到模式中的变量 max 打印出 Some 变量中的值。我们不想对 None 的值做任何处理。为了满足 match 表达式的要求我们必须在只处理一个变量后添加 _ () 而这是令人讨厌的模板代码。 相反我们可以使用 if let 以更简短的方式编写。以下代码的行为与上述中的 match 相同 let config_max Some(3u8); if let Some(max) config_max {println!(The maximum is configured to be {}, max); }语法 if let 包含一个模式和一个表达式以等号分隔。它的工作方式与 match 相同其中表达式提供给 match 而模式则是其第一arm。在本例中模式是 Some(max) 而 max 与 Some 中的值绑定。然后我们可以在 if let 块的主体中使用 max 方法与在相应的 match arm 中使用 max 相同。如果值与模式不匹配就不会运行 if let 代码块中的代码。 使用 if let 意味着更少的键入、更少的缩进和更少的模板代码。但是您将失去 match 所提供的详尽检查功能。在 match 和 if let 之间做出选择取决于您在特定情况下要做什么以及在失去详尽检查的情况下获得简洁性是否是一个适当的权衡。 换句话说你可以把 if let 看作是 match 的语法糖当值与一种模式匹配时它就会运行代码然后忽略所有其他值。 我们可以在 if let 中包含 else 。与 else 对应的代码块与 match 表达式中与 _ 对应的代码块相同后者等同于 if let 和 else 。回顾Coin 枚举定义其中 Quarter 变体还包含一个 UsState 值。如果我们想计算所看到的所有非四角硬币同时公布四角硬币的状态我们可以使用 match 表达式如下所示 let mut count 0; match coin {Coin::Quarter(state) println!(State quarter from {:?}!, state),_ count 1, }或者我们可以使用 if let 和 else 表达式就像这样 let mut count 0; if let Coin::Quarter(state) coin {println!(State quarter from {:?}!, state); } else {count 1; }如果程序中的逻辑过于冗长无法使用 match 来表达请记住 if let 也在 Rust 工具箱中。 下一篇 07-用软件包、cratres和模块管理项
http://www.dnsts.com.cn/news/92351.html

相关文章:

  • 禹城做网站的公司腾讯广告一级代理名单
  • asp网站跳转浏览器现在去长沙会被隔离吗
  • 手机端网站ui做多少像素免费查公司信息哪个软件好
  • 网站开发的作用类似wordpress的系统有哪些
  • 制作网页的模板的网站帮别人做设计图的网站
  • seo 网站标题字数VPS wordpress 教程
  • 网站开发一般用哪些语言郑州网页网站制作
  • 建设企业学习网站河北城乡和住房建设厅官方网站
  • 美团网站网站建设发展广州网站排名优化报价
  • 坪山模板网站建设公司环保企业网站建设现状
  • 网站建设流程多少钱wordpress google收录
  • 建立本地网站网站开发开发需求文档模板
  • 网站服务器查询加盟项目
  • 滨海做网站公司南通住房和城乡建设厅网站首页
  • 网站建设程序编制金华手机建站模板
  • 织梦医院网站开发乐华网络公司联系方式
  • php网站开发工程师招聘要求1688做网站多少钱
  • 中国建造师官方网站华亭网站建设
  • 特产网站建设的目的家居商城网站模板
  • 网站经营中装建设集团网站
  • 网站和域名区别吗禅城网站制作
  • 网站建设控制如何创造一个网站
  • 家禽养殖公司网站怎么做wordpress的友情链设置
  • 旅游网站的建设的意义网页美工设计流程为
  • 库尔勒网站建设推广黑色wordpress主题
  • 设计网站 问题做网站主页图片一般多少m
  • 定州网站建设电话腾讯云 配置wordpress
  • 苏州网络公司建网站南昌做网站的
  • 曲靖网站推广沈阳招聘网官网
  • 快刷网站跨境电商多平台运营