我是你的光 發表於 2025-3-13 09:08:14

深入理解 Rust 中的模式匹配语法(最新推荐)

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、匹配字面量</li><li>二、匹配命名变量</li><li>三、多模式匹配</li><li>四、匹配范围(..=)</li><li>五、解构:将复杂数据拆分为单独的部分</li><ul class="second_class_ul"><li>1. 解构结构体</li><li>2. 解构枚举</li><li>3. 嵌套解构</li><li>4. 结构体与元组混合解构</li></ul><li>六、忽略值的模式</li><ul class="second_class_ul"><li>1. 使用 _ 忽略整个值</li><li>2. 嵌套中使用 _ 忽略部分值</li><li>3. 命名以 _ 开头的变量</li><li>4. 使用 .. 忽略剩余部分</li></ul><li>七、使用匹配守卫添加额外条件</li><ul class="second_class_ul"></ul><li>八、@ 绑定:匹配的同时进行绑定</li><ul class="second_class_ul"></ul><li>九、总结</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>一、匹配字面量</h2>
<p>在 Rust 中,可以直接对具体的字面量进行匹配。例如:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let x = 1;
    match x {
      1 =&gt; println!("匹配到字面量 1"),
      _ =&gt; println!("其他值"),
    }
}</pre></div>
<p>当 <code>x</code> 的值为 <code>1</code> 时,匹配成功并打印出对应的信息。对于需要对特定具体值进行处理的场景,这种写法非常直观有效。</p>
<p class="maodian"></p><h2>二、匹配命名变量</h2>
<p>在模式匹配中,使用命名变量可以将匹配到的值绑定到一个变量上。需要注意的是,在 <code>match</code>、<code>if let</code>、<code>while let</code> 等表达式中,模式内部声明的变量会<strong>遮蔽</strong>(shadow)外部同名变量。例如:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let x = Some(5);
    let y = 10;
    match x {
      None =&gt; println!("x 是 None"),
      Some(y) =&gt; println!("匹配到 Some,其中内部 y 为: {}", y),
    }
    println!("外部的 y: {}", y);
}</pre></div>
<p>上述代码中,<code>match</code> 分支中出现的 <code>y</code> 是一个全新的变量,绑定了 <code>Some</code> 内部的值 <code>5</code>,而外部的 <code>y</code> 依然保持着原来的值 <code>10</code>。如果需要在匹配时引用外部变量,可以借助匹配守卫(见后文)。</p>
<p class="maodian"></p><h2>三、多模式匹配</h2>
<p>有时一个匹配分支需要针对多个值做出处理,可以使用管道符 <code>|</code> 来表示&ldquo;或&rdquo;的关系。例如:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let x = 2;
    match x {
      1 | 2 =&gt; println!("匹配到 1 或 2"),
      _ =&gt; println!("其他值"),
    }
}</pre></div>
<p>如果 <code>x</code> 的值为 <code>1</code> 或 <code>2</code>,则执行对应分支的代码,这种写法使代码更加简洁。</p>
<p class="maodian"></p><h2>四、匹配范围(..=)</h2>
<p>当要匹配一系列连续的值时,使用 <code>..=</code> 操作符可以大大简化代码,而不用列出每个具体的值。例如:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let x = 3;
    match x {
      1..=5 =&gt; println!("x 在 1 到 5 的范围内"),
      _ =&gt; println!("x 超出范围"),
    }
}</pre></div>
<p>同样,Rust 也支持对字符(<code>char</code>)使用范围匹配,但范围必须保证非空,否则编译器会报错。</p>
<p class="maodian"></p><h2>五、解构:将复杂数据拆分为单独的部分</h2>
<p>Rust 的模式匹配不仅仅用于简单的值匹配,还可以用于解构(destructuring)复杂数据类型,如结构体、枚举、元组等。</p>
<p class="maodian"></p><h3>1. 解构结构体</h3>
<p>利用 <code>let</code> 语句,可以轻松将结构体中的字段拆分到不同变量中:</p>
<div class="jb51code"><pre class="brush:plain;">struct Point {
    x: i32,
    y: i32,
}
fn main() {
    let p = Point { x: 10, y: 20 };
    // 显式命名
    let Point { x: a, y: b } = p;
    println!("a: {}, b: {}", a, b);
    // 结构体字段的简写(变量名与字段名相同)
    let Point { x, y } = p;
    println!("x: {}, y: {}", x, y);
}</pre></div>
<p>这种解构方式使得我们可以方便地操作结构体中的数据。</p>
<p class="maodian"></p><h3>2. 解构枚举</h3>
<p>枚举的每个变体可能包含不同的数据,解构时需要根据枚举的定义来匹配相应的结构。例如:</p>
<div class="jb51code"><pre class="brush:plain;">enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}
fn main() {
    let msg = Message::ChangeColor(255, 160, 0);
    match msg {
      Message::Quit =&gt; println!("Quit!"),
      Message::Move { x, y } =&gt; println!("Move to ({}, {})", x, y),
      Message::Write(text) =&gt; println!("Text message: {}", text),
      Message::ChangeColor(r, g, b) =&gt; println!("Change color to red: {}, green: {}, blue: {}", r, g, b),
    }
}</pre></div>
<p>通过对枚举变体的解构,可以直接使用其内部数据进行进一步处理。</p>
<p class="maodian"></p><h3>3. 嵌套解构</h3>
<p>在实际应用中,数据结构可能嵌套得很深,我们同样可以使用模式匹配对嵌套的数据进行解构。例如:</p>
<div class="jb51code"><pre class="brush:plain;">enum Color {
    Rgb(i32, i32, i32),
    Hsv(i32, i32, i32),
}
enum Message {
    ChangeColor(Color),
    // 其他变体...
}
fn main() {
    let msg = Message::ChangeColor(Color::Rgb(0, 160, 255));
    match msg {
      Message::ChangeColor(Color::Rgb(r, g, b)) =&gt;
            println!("Change the color to red: {}, green: {}, blue: {}", r, g, b),
      Message::ChangeColor(Color::Hsv(h, s, v)) =&gt;
            println!("Change the color using HSV: {}, {}, {}", h, s, v),
      _ =&gt; (),
    }
}</pre></div>
<p>这种方式让我们能够在一个 <code>match</code> 表达式中同时处理多个嵌套数据。</p>
<p class="maodian"></p><h3>4. 结构体与元组混合解构</h3>
<p>Rust 还支持对结构体和元组的混合解构,能够将复杂的数据类型拆分为单个的原始值进行处理。这种灵活性是 Rust 在数据处理上的一大优势。</p>
<p class="maodian"></p><h2>六、忽略值的模式</h2>
<p>在很多情况下,我们并不需要使用匹配到的所有数据,Rust 提供了多种方式来忽略不必要的部分:</p>
<p class="maodian"></p><h3>1. 使用 _ 忽略整个值</h3>
<p>在匹配时,如果某个分支不关心具体的值,可以直接用 <code>_</code> 表示:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let x = 3;
    match x {
      _ =&gt; println!("忽略具体值"),
    }
}</pre></div>
<p>此外,在函数参数中也可以使用 <code>_</code> 来避免未使用变量的警告。</p>
<p class="maodian"></p><h3>2. 嵌套中使用 _ 忽略部分值</h3>
<p>如果只关心结构体或枚举中的部分字段,可以在模式中只对需要的部分命名,而用 <code>_</code> 忽略其他部分。例如:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let setting_value = Some(5);
    let new_setting_value = Some(5);
    match (setting_value, new_setting_value) {
      (Some(_), Some(_)) =&gt; println!("不能覆盖已有的自定义值"),
      _ =&gt; println!("允许更新设置"),
    }
}</pre></div>
<p class="maodian"></p><h3>3. 命名以 _ 开头的变量</h3>
<p>如果需要绑定一个变量但又暂时不使用,可以在变量名前加上 <code>_</code>,这样 Rust 就不会产生未使用变量的警告。不过要注意,加下划线并不会阻止变量取得所有权,只是标示这个变量当前不被使用。</p>
<p class="maodian"></p><h3>4. 使用 .. 忽略剩余部分</h3>
<p>对于包含大量字段或元素的数据结构,如果只关注其中一部分,可以使用 <code>..</code> 来忽略剩余部分。例如,对于结构体:</p>
<div class="jb51code"><pre class="brush:plain;">struct Point3D {
    x: i32,
    y: i32,
    z: i32,
}
fn main() {
    let point = Point3D { x: 10, y: 20, z: 30 };
    match point {
      Point3D { x, .. } =&gt; println!("只关心 x 的值: {}", x),
    }
}</pre></div>
<p>在元组中也可以类似地使用 <code>..</code> 来匹配头尾部分,而忽略中间所有元素。但需要注意,<code>..</code> 的使用必须没有歧义,否则编译器会报错。</p>
<p class="maodian"></p><h2>七、使用匹配守卫添加额外条件</h2>
<p>有时单靠模式匹配无法满足复杂条件,比如既要匹配某个模式,还要进一步判断值是否满足特定条件。此时可以使用匹配守卫(match guard),在模式后面添加 <code>if</code> 条件:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let num = Some(4);
    match num {
      Some(x) if x % 2 == 0 =&gt; println!("数字 {} 是偶数", x),
      Some(_) =&gt; println!("匹配到 Some,但不满足守卫条件"),
      None =&gt; println!("匹配到 None"),
    }
}</pre></div>
<p>匹配守卫可以使用模式中绑定的变量,并且可以和多模式匹配组合使用,但需要注意守卫条件会影响到编译器的穷尽性检查。</p>
<p class="maodian"></p><h2>八、@ 绑定:匹配的同时进行绑定</h2>
<p><code>@</code> 操作符可以在匹配时对值进行绑定,同时检验其是否满足某个模式。例如,当需要匹配一个范围内的值并且希望获得该值时,可以使用 <code>@</code> 绑定:</p>
<div class="jb51code"><pre class="brush:plain;">fn main() {
    let id = 5;
    match id {
      id_variable @ 3..=7 =&gt; println!("找到了范围内的 id: {}", id_variable),
      _ =&gt; println!("id 不在 3 到 7 的范围内"),
    }
}</pre></div>
<p>在上面的代码中,如果 <code>id</code> 的值在 <code>3..=7</code> 范围内,就会同时将该值绑定给 <code>id_variable</code>,方便后续使用。</p>
<p class="maodian"></p><h2>九、总结</h2>
<p>Rust 的模式匹配语法不仅仅是用于简单的分支判断,它通过丰富的语法特性让我们能够:</p>
<ul><li>精确匹配字面量与范围,</li><li>通过命名变量和解构获取复杂数据中的各个部分,</li><li>灵活忽略不关心的数据,</li><li>通过匹配守卫增加额外条件限制,</li><li>以及使用&nbsp;<code>@</code>&nbsp;绑定实现边匹配边保存数据。</li></ul>
<p>这些特性大大提升了代码的表达能力和安全性,使得 Rust 能够在编译期捕获更多错误并保证程序行为的正确性。希望本文能帮助你更好地理解和应用 Rust 中的模式匹配,为编写更加优雅和健壮的代码提供助力!</p>
<p>到此这篇关于深入理解 Rust 中的模式匹配语法(最新推荐)的文章就介绍到这了,更多相关Rust模式匹配语法内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Rust之模式与模式匹配的实现</li><li>深入了解Rust中的枚举和模式匹配</li><li>Rust&nbsp;枚举和模式匹配的实现</li><li>Rust&nbsp;模式匹配示例详解</li><li>Rust指南枚举类与模式匹配详解</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 深入理解 Rust 中的模式匹配语法(最新推荐)