【Rust模式与匹配】Rust模式与匹配深入探索与应用实战

news2025/7/23 13:14:41

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Rust开发,Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:Rust语言通关之路
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Rust模式和匹配
    • 一、 模式匹配基础
      • 1.1 什么是模式匹配
      • 1.2 基本match表达式
      • 1.3 模式匹配的穷尽性检查
      • 1.4 let 语句
      • 1.5 函数参数
    • 二、Refutability(可反驳性): 模式是否会匹配失效
    • 三、模式匹配的各种形式
      • 3.1 字面量匹配
      • 3.2 匹配命名变量
      • 3.3 匹配多个模式
      • 3.4 变量绑定
      • 3.5 解构匹配
      • 3.6 引用匹配
      • 3.7 模式守卫
      • 3.8 if let 、while let和for循环
        • 3.8.1 if let 简洁匹配
        • 3.8.2 while let 条件循环
        • 3.8.3 for循环
    • 四、高级模式匹配技巧
      • 4.1 忽略模式中的值
        • 4.1.1 忽略模式部分
        • 4.1.2 使用 _ 忽略整个值
      • 4.2 匹配守卫与绑定
    • 五、总结

Rust模式和匹配

模式是 Rust 中特殊的语法,它用来匹配类型中的结构,无论类型是简单还是复杂。
结合使用模式和 match 表达式以及其他结构可以提供更多对程序控制流的支配权。模式由如下一些内容组合而成:
字面量
解构的数组、枚举、结构体或者元组
变量
通配符
占位符
这些部分描述了我们要处理的数据的形状,接着可以用其匹配值来决定程序是否拥有正确的数据来运行特定部分的代码。
我们通过将一些值与模式相比较来使用它。如果模式匹配这些值,我们对值部分进行相应处理。

本文是所有模式相关内容的参考。我们将涉及到使用模式的有效位置,refutable 与 irrefutable 模式的区别,和你可能会见到的不同类型的模式语法。
在最后,你将会看到如何使用模式创建强大而简洁的代码。

一、 模式匹配基础

1.1 什么是模式匹配

模式匹配是Rust语言中一种强大的控制流结构,它允许你根据数据的形状来检查数据并相应地执行代码。
与传统的if-else语句不同,模式匹配提供了更清晰、更安全的方式来处理多种可能的数据状态。

在Rust中,模式匹配主要通过match表达式和if let/while let结构来实现。这些结构不仅简洁明了,还能在编译时检查所有可能的情况,避免遗漏处理某些情形。

1.2 基本match表达式

最基本的模式匹配形式是match表达式,它类似于其他语言中的switch语句,但功能更强大。

let number = 13;

match number {
    1 => println!("One"),
    2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
    13..=19 => println!("A teen"),
    _ => println!("Ain't special"),
}

在这个例子中:
1匹配精确值1
2 | 3 | 5 | 7 | 11使用|表示"或"关系 属于多个模式匹配
13…=19匹配13到19的闭区间范围 通过 …= 匹配值的范围 …= 语法允许你匹配一个闭区间范围内的值。
_是通配符模式,匹配任何值 我们已经使用过下划线(_)作为匹配但不绑定任何值的通配符模式了。

1.3 模式匹配的穷尽性检查

Rust编译器强制要求match表达式必须覆盖所有可能的情况。这种穷尽性检查是Rust安全保证的重要组成部分。

#[allow(dead_code)]
enum Direction {
    North,
    South,
    East,
    West,
}

fn main() {
    let dir = Direction::North;

    match dir {
        Direction::North => println!("Heading north"),
        Direction::South => println!("Heading south"),
        Direction::East => println!("Heading east"),
        Direction::West => println!("Heading west"),
        // 如果注释掉任何一个分支,编译器会报错
    }
}

在这里插入图片描述

1.4 let 语句

let语句的模式是:let PATTERN = EXPRESSION;
像 let x = 5; 这样的语句中变量名位于 PATTERN 位置,变量名不过是形式特别朴素的模式。
我们将表达式与模式比较,并为任何找到的名称赋值。所以例如 let x = 5; 的情况,x 是一个表示“将匹配到的值绑定到变量 x” 的模式。
同时因为名称 x 是整个模式,这个模式实际上等于 “将任何值绑定到变量 x,不管值是什么”。
为了更清楚的理解 let 的模式匹配方面的内容,使用 let 和模式解构一个元组:
let (x, y, z) = (1, 2, 3);

这里将一个元组与模式匹配。Rust 会比较值 (1, 2, 3) 与模式 (x, y, z) 并发现此值匹配这个模式。
在这个例子中,将会把 1 绑定到 x,2 绑定到 y 并将 3 绑定到 z。你可以将这个元组模式看作是将三个独立的变量模式结合在一起。

如果模式中元素的数量不匹配元组中元素的数量,则整个类型不匹配,并会得到一个编译时错误。
例如,如下示例展示了尝试用两个变量解构三个元素的元组,这是不行的:
let (x, y) = (1, 2, 3);
在这里插入图片描述

1.5 函数参数

函数参数也可以是模式。

fn foo(x: i32) {
    // 代码
}
x 部分就是一个模式!类似于之前对 let 所做的,可以在函数参数中匹配元组。如下列表将传递给函数的元组拆分为值:
fn print_coordinates(&(x, y): &(i32, i32)) {
    println!("Current location: ({}, {})", x, y);
}

fn main() {
    let point = (3, 5);
    print_coordinates(&point);
}

在这里插入图片描述

这打印出 Current location: (3, 5)。值 &(3, 5) 会匹配模式 &(x, y),如此 x 得到了值 3,而 y得到了值 5。

因为如闭包类似于函数,也可以在闭包参数列表中使用模式。
现在我们见过了很多使用模式的方式了,不过模式在每个使用它的地方并不以相同的方式工作;在一些地方,模式必须是 irrefutable 的,意味着他们必须匹配所提供的任何值。
在另一些情况,他们则可以是 refutable 的。接下来让我们讨论这两个概念。

二、Refutability(可反驳性): 模式是否会匹配失效

模式有两种形式:refutable(可反驳的)和 irrefutable(不可反驳的)。
能匹配任何传递的可能值的模式被称为是 不可反驳的(irrefutable)。
一个例子就是 let x = 5; 语句中的 x,因为 x 可以匹配任何值所以不可能会失败。
对某些可能的值进行匹配会失败的模式被称为是 可反驳的(refutable)。
一个这样的例子便是 if let Some(x) = a_value 表达式中的 Some(x);如果变量 a_value 中的值是 None 而不是 Some,那么 Some(x) 模式不能匹配。

函数参数、 let 语句和 for 循环只能接受不可反驳的模式,因为通过不匹配的值程序无法进行有意义的工作。
if let 和 while let 表达式被限制为只能接受可反驳的模式,因为根据定义他们意在处理可能的失败:条件表达式的功能就是根据成功或失败执行不同的操作。
通常我们无需担心可反驳和不可反驳模式的区别,不过确实需要熟悉可反驳性的概念,这样当在错误信息中看到时就知道如何应对。
遇到这些情况,根据代码行为的意图,需要修改模式或者使用模式的结构。

match 匹配分支必须使用可反驳模式,除了最后一个分支需要使用能匹配任何剩余值的不可反驳模式。
Rust 允许我们在只有一个匹配分支的 match 中使用不可反驳模式,不过这么做不是特别有用,并可以被更简单的 let 语句替代。

//模式匹配中的可反驳模式和不可反驳模式

fn main() {
    //let语句、函数参数和for循环中的模式必须是不可反驳的
    let x = 5; //不可反驳模式

    let y: Option<i32> = Some(5); //不可反驳模式

    //可反驳模式不能用let来定义
    // let Some(z) = y; //可反驳模式

    //可以使用if let或者while let来处理可反驳模式
    if let Some(z) = y {
        println!("z: {}", z);
    }

    //如果if let用于处理不可反驳模式,编译器会警告
    if let x = 5 {
        println!("x: {}", x);
    }
}

在这里插入图片描述

三、模式匹配的各种形式

3.1 字面量匹配

最简单的模式是直接匹配字面量值:

let x = 1;

match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("anything"),
}

3.2 匹配命名变量

名变量是匹配任何值的不可反驳模式,这在之前已经使用过数次。
然而当其用于 match 表达式时情况会有些复杂。因为 match 会开始一个新作用域,match 表达式中作为模式的一部分声明的变量会覆盖 match 结构之外的同名变量,与所有变量一样。

fn main() {
    let x = Some(5);
    let y = 10;

    match x {
        Some(50) => println!("Got 50"),
        Some(y) => println!("Matched, y = {:?}", y),
        _ => println!("Default case, x = {:?}", x),
    }

    println!("at the end: x = {:?}, y = {:?}", x, y);
}

让我们看看当 match 语句运行的时候发生了什么。第一个匹配分支的模式并不匹配 x 中定义的值,所以代码继续执行。
第二个匹配分支中的模式引入了一个新变量 y,它会匹配任何 Some 中的值。
因为我们在 match 表达式的新作用域中,这是一个新变量,而不是开头声明为值 10 的那个 y。
这个新的 y 绑定会匹配任何 Some 中的值,在这里是 x 中的值。
因此这个 y 绑定了 x 中 Some 内部的值。这个值是 5,所以这个分支的表达式将会执行并打印出 Matched, y = 5。

如果 x 的值是 None 而不是 Some(5),头两个分支的模式不会匹配,所以会匹配下划线。
这个分支的模式中没有引入变量 x,所以此时表达式中的 x 会是外部没有被覆盖的 x。在这个假想的例子中,match 将会打印 Default case, x = None。

一旦 match 表达式执行完毕,其作用域也就结束了,同理内部 y 的作用域也结束了。最后的 println! 会打印 at the end: x = Some(5), y = 10。

为了创建能够比较外部 x 和 y 的值,而不引入覆盖变量的 match 表达式,我们需要相应地使用带有条件的匹配守卫(match guard)。
我们稍后将在 “匹配守卫提供的额外条件” 这一小节讨论匹配守卫。
在这里插入图片描述

3.3 匹配多个模式

在 match 表达式中,可以使用 | 语法匹配多个模式,它代表 或(or)的意思。
例如,如下代码将 x 的值与匹配分支相比较,第一个分支有 或 选项,意味着如果 x 的值匹配此分支的任一个值,它就会运行:

fn main() {
    let x = 1;

    match x {
        1 | 2 => println!("one or two"),
        3 => println!("three"),
        _ => println!("anything"),
    }
}

在这里插入图片描述

3.4 变量绑定

@ 绑定
at 运算符(@)允许我们在创建一个存放值的变量的同时测试其值是否匹配模式。
如下示例展示了一个例子,这里我们希望测试 Message::Hello 的 id 字段是否位于 3…=7 范围内,同时也希望能将其值绑定到 id_variable 变量中以便此分支相关联的代码可以使用它。
可以将 id_variable 命名为 id,与字段同名,不过出于示例的目的这里选择了不同的名称。
模式可以绑定变量,这使得我们可以在匹配的同时提取值:

fn main() {
    enum Message {
        Hello {
            id: i32,
        },
    }

    let msg = Message::Hello { id: 5 };

    match msg {
        //将id绑定到变量id_variable上
        //@指定匹配的范围
        Message::Hello { id: id_variable @ 3..=7 } => {
            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) }
    }
}

在这里插入图片描述

3.5 解构匹配

模式匹配最强大的功能之一是能够解构复杂的数据类型:
解构元组

fn main() {
    let pair = (0, -2);

    //解构元组
    match pair {
        (0, y) => println!("First is 0, y is {}", y),
        (x, 0) => println!("x is {}, second is 0", x),
        _ => println!("No zero"),
    }
}

在这里插入图片描述

解构结构体

fn main() {
    struct Point {
        x: i32,
        y: i32,
    }

    let point = Point { x: 0, y: 7 };

    match point {
        Point { x, y: 0 } => println!("On the x axis at {}", x),
        Point { x: 0, y } => println!("On the y axis at {}", y),
        Point { x, y } => println!("On neither axis: ({}, {})", x, y),
    }
}

在这里插入图片描述

解构枚举

#[allow(dead_code)]
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!("Quit"),
        Message::Move { x, y } => println!("Move to x: {}, y: {}", x, y),
        Message::Write(text) => println!("Text message: {}", text),
        Message::ChangeColor(r, g, b) => println!("Change color to RGB: {}, {}, {}", r, g, b),
    }
}

在这里插入图片描述

解构嵌套的结构体和枚举

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));

    //其他的我们都不关心,我们只匹配ChangeColor
    match msg {
        Message::ChangeColor(Color::Rgb(r, g, b)) => {
            println!("rgb red {}, green {}, and blue {}", r, g, b)
        }
        Message::ChangeColor(Color::Hsv(h, s, v)) => {
            println!("hsv to hue {}, saturation {}, and value {}", h, s, v)
        }
        _ => (),
    }
}

在这里插入图片描述

3.6 引用匹配

当匹配引用时,需要使用&来解构:

fn main() {
    let reference = &4;

    match reference {
        &val => println!("Got a value via destructuring: {}", val),
    }

    // 更简单的方式是使用解引用
    match *reference {
        val => println!("Got a value via dereferencing: {}", val),
    }
}

在这里插入图片描述

3.7 模式守卫

匹配守卫(match guard)是一个指定于 match 分支模式之后的额外 if 条件,它也必须被满足才能选择此分支。匹配守卫用于表达比单独的模式所能允许的更为复杂的情况。
模式守卫允许在模式匹配中添加额外的条件:

fn main() {
    let pair = (2, -2);

    match pair {
        //匹配后面跟if条件判断
        (x, y) if x == y => println!("These are twins"),
        (x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
        (x, _) if x % 2 == 1 => println!("The first one is odd"),
        _ => println!("No correlation"),
    }
}

在这里插入图片描述

3.8 if let 、while let和for循环

3.8.1 if let 简洁匹配
if let提供了一种更简洁的方式来处理只关心一种模式而忽略其他模式的情况:
fn main() {
    let some_value = Some(3);

    // 使用match
    match some_value {
        Some(3) => println!("three"),
        _ => (),
    }

    // 使用if let更简洁
    if let Some(3) = some_value {
        println!("three");
    }
}

在这里插入图片描述

3.8.2 while let 条件循环

while let使得只要模式匹配就一直循环:

fn main() {
    let mut stack = Vec::new();

    stack.push(1);
    stack.push(2);
    stack.push(3);

    //使用while let来处理Option类型
    //只要stack.pop()返回Some,就执行循环体
    while let Some(top) = stack.pop() {
        println!("{}", top);
    }
}

在这里插入图片描述

3.8.3 for循环

for 循环是 Rust 中最常见的循环结构,不过还没有讲到的是 for 可以获取一个模式。
在 for 循环中,模式是 for 关键字直接跟随的值,正如 for x in y 中的 x。

fn main() {
    let v = vec!['a', 'b', 'c'];

    //通过for循环来遍历vector生成的迭代器
    for (index, value) in v.iter().enumerate() {
        println!("{} is at index {}", value, index);
    }
}

这里使用 enumerate 方法适配一个迭代器来产生一个值和其在迭代器中的索引,他们位于一个元组中。
第一个 enumerate 调用会产生元组 (0, ‘a’)。当这个值匹配模式 (index, value),index 将会是 0 而 value 将会是 ‘a’,并打印出第一行输出。以此类推。
在这里插入图片描述

四、高级模式匹配技巧

4.1 忽略模式中的值

4.1.1 忽略模式部分

对于有多个部分的值,可以使用 … 语法来只使用部分并忽略其它值,同时避免不得不每一个忽略值列出下划线。… 模式会忽略模式中剩余的任何没有显式匹配的值部分。
可以使用_或…来忽略值的部分:

#[allow(dead_code)]
struct Point {
    x: i32,
    y: i32,
    z: i32,
}

fn main() {
    let origin = Point { x: 0, y: 0, z: 0 };

    match origin {
        //..表示忽略其他字段
        Point { x, .. } => println!("x is {}", x),
    }

    let numbers = (2, 4, 8, 16, 32);

    match numbers {
        //只需要第一个和最后一个值,其他的忽略
        (first, .., last) => {
            println!("Some numbers: {}, {}", first, last);
        }
    }
}

在这里插入图片描述

注意:使用 … 必须是无歧义的。如果期望匹配和忽略的值是不明确的,Rust 会报错。
如下示例展示了一个带有歧义的 … 例子,因此其不能编译:

fn main() {
    let numbers = (2, 4, 8, 16, 32);

    match numbers {
        (.., second, ..) => { println!("Some numbers: {}", second) }
    }
}

Rust 不可能决定在元组中匹配 second 值之前应该忽略多少个值,以及在之后忽略多少个值。
这段代码可能表明我们意在忽略 2,绑定 second 为 4,接着忽略 8、16 和 32;抑或是意在忽略 2 和 4,绑定 second 为 8,接着忽略 16 和 32,以此类推。
变量名 second 对于 Rust 来说并没有任何特殊意义,所以会得到编译错误,因为在这两个地方使用 … 是有歧义的。
在这里插入图片描述

… 在同一个匹配中只能使用一次

4.1.2 使用 _ 忽略整个值

我们已经使用过下划线(_)作为匹配但不绑定任何值的通配符模式了。
虽然 _ 模式作为 match 表达式最后的分支特别有用,也可以将其用于任意模式,包括函数参数中,

//定义一个函数,参数使用下划线来忽略
fn foo(_: i32, y: i32) {
    println!("This code only uses the y parameter: {}", y);
}

fn main() {
    //调用函数的时候,第一个参数随便写,也可以使用下划线
    foo(3, 4);
}

在这里插入图片描述

大部分情况当你不再需要特定函数参数时,最好修改签名不再包含无用的参数。
在一些情况下忽略函数参数会变得特别有用,比如实现 trait 时,当你需要特定类型签名但是函数实现并不需要某个参数时。
此时编译器就不会警告说存在未使用的函数参数,就跟使用命名参数一样。
如下:
在这里插入图片描述

使用嵌套的 _ 忽略部分值
也可以在一个模式内部使用 _ 忽略部分值,例如,当只需要测试部分值但在期望运行的代码中没有用到其他部分时。
如下示例展示了负责管理设置值的代码。业务需求是用户不允许覆盖现有的自定义设置,但是可以取消设置,也可以在当前未设置时为其提供设置。

fn main() {
    let mut setting_value = Some(5);
    let new_setting_value = Some(10);

    match (setting_value, new_setting_value) {
        //使用Some(_),Some(_)来匹配Some(5)和Some(10)
        (Some(_), Some(_)) => {
            println!("Can't overwrite an existing customized value");
        }
        _ => {
            setting_value = new_setting_value;
        }
    }

    println!("setting is {:?}", setting_value);
}

这段代码会打印出 Can’t overwrite an existing customized value 接着是 setting is Some(5)。
在第一个匹配分支,我们不需要匹配或使用任一个 Some 成员中的值;重要的部分是需要测试 setting_value 和 new_setting_value 都为 Some 成员的情况。
在这种情况,我们打印出为何不改变 setting_value,并且不会改变它。
对于所有其他情况(setting_value 或 new_setting_value 任一为 None),这由第二个分支的 _ 模式体现,这时确实希望允许 new_setting_value 变为 setting_value。
在这里插入图片描述

通过在名字前以一个下划线开头来忽略未使用的变量
如果你创建了一个变量却不在任何地方使用它, Rust 通常会给你一个警告,因为这可能会是个 bug。
但是有时创建一个还未使用的变量是有用的,比如你正在设计原型或刚刚开始一个项目。
这时你希望告诉 Rust 不要警告未使用的变量,为此可以用下划线作为变量名的开头。

fn main() {
    let _x = 5;
    let y = 10;
}

这里得到了警告说未使用变量 y,不过没有警告说未使用下划线开头的变量。

注意, 只使用 _ 和使用以下划线开头的名称有些微妙的不同:比如 _x 仍会将值绑定到变量,而 _ 则完全不会绑定。

fn main() {
    let s = Some(String::from("Hello!"));

    if let Some(_s) = s {
        println!("found a string");
    }

    println!("{:?}", s);  //报错,因为s的所有权已经转移给_s了
}

在这里插入图片描述

使用单独的下划线,变量不会绑定
在这里插入图片描述

4.2 匹配守卫与绑定

结合匹配守卫和绑定可以实现复杂的条件判断:

fn main() {
    let robot_name = Some(String::from("Bors"));

    match robot_name {
        //使用ref来获取Some的值的引用
        //避免了所有权的转移
        Some(ref name) if name == "Bors" => {
            println!("Found robot: {}", name);
        }
        Some(name) => {
            println!("Not the robot: {}", name);
        }
        None => {}
    }
}

在这里插入图片描述

五、总结

Rust的模式匹配系统是其最强大和最独特的特性之一。它提供了:

  • 清晰、表达力强的语法

  • 编译时的安全性检查

  • 高效的运行时性能

  • 对复杂数据结构的强大解构能力

通过掌握模式匹配,大家可以编写出更安全、更清晰、更易于维护的Rust代码。从简单的值匹配到复杂的解构和守卫,模式匹配几乎可以处理任何数据验证和提取需求。

Rust的模式匹配不仅仅是一个语言特性,它体现了Rust的核心哲学:在编译时捕获尽可能多的错误,同时保持运行时的效率。随着你对Rust的深入使用,你会发现模式匹配成为了你工具箱中不可或缺的一部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2393955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

electron安装报错处理

electron安装报错 解决方法&#xff1a; 修改 C:\Users\用户名.npmrc下配置文件 添加代码 electron_mirrorhttps://cdn.npmmirror.com/binaries/electron/ electron_builder_binaries_mirrorhttps://npmmirror.com/mirrors/electron-builder-binaries/最后代码 registryhtt…

NHANES指标推荐:CQI

文章题目&#xff1a;The impact of carbohydrate quality index on menopausal symptoms and quality of life in postmenopausal women 中文标题&#xff1a;碳水化合物质量指数对绝经后妇女更年期症状和生活质量的影响 发表杂志&#xff1a;BMC Womens Health 影响因子&…

【从零开始学习QT】快捷键、帮助文档、Qt窗口坐标体系

目录 Qt Creator 中的快捷键 使用帮助文档 Qt 窗口坐标体系 QT专栏&#xff1a;QT_uyeonashi的博客-CSDN博客 Qt Creator 中的快捷键 • 注释&#xff1a;ctrl / • 运行&#xff1a;ctrl R • 编译&#xff1a;ctrl B • 字体缩放&#xff1a;ctrl 鼠标滑轮 • 查找&am…

基于stm32的多旋翼无人机(Multi-rotor UAV based on stm32)

由于一直在调试本项目&#xff0c;好久没有发文章&#xff0c;最近本项目的PID调试初见成效&#xff01;开始正文前首先感谢各位粉丝的支持&#xff0c;以及对本项目技术上支持的老师以及师兄&#xff0c;谢谢你们&#xff01; 对应源码及文件&#xff1a;源码及文件下载 基于…

实验分享|基于sCMOS相机科学成像技术的耐高温航空涂层材料损伤检测实验

1实验背景 航空发动机外壳的耐高温涂层材料在长期高温、高压工况下易产生微小损伤与裂纹&#xff0c;可能导致严重安全隐患。传统光学检测手段受限于分辨率与灵敏度&#xff0c;难以捕捉微米级缺陷&#xff0c;且检测效率低下。 某高校航空材料实验室&#xff0c;采用科学相机…

RAG混合检索:倒数秩融合RRF算法

文章目录 检索增强生成 (RAG)倒数秩融合在 RAG 中的工作原理RRF 背后的数学直觉检索增强生成 (RAG) RAG 是自然语言处理中的一种强大技术,结合了基于检索的模型和生成模型的优势。 如果检索器未能从检索器中获取相关文档,则精度较低,幻觉的可能性会增加。 有些查询适合…

2011肠衣问题

1 D类竞赛题目---具体题目 D题 天然肠衣搭配问题 天然肠衣&#xff08;以下简称肠衣&#xff09;制作加工是我国的一个传统产业&#xff0c;出口量占世界首位。肠衣经过清洗整理后被分割成长度不等的小段&#xff08;原料&#xff09;&#xff0c;进入组装工序。 传统的生产…

RG3000网关构建5G LAN智慧工厂智能制造

在工业4.0与智能制造的趋势下&#xff0c;传统制造业正前后往智慧工厂转型升级。在转型过程中&#xff0c;高效、稳定、灵活的网络通信是实现设备互联互通、数据实时交互与智能决策的基础。智联物联RG3000网关&#xff0c;凭借其融合5G通信技术、WiFi6无线传输、边缘计算能力与…

webrtc初了解

1. webrtc的简介 一、WebRTC 是什么&#xff1f; Web Real-Time Communication&#xff08;网页实时通信&#xff09;&#xff0c;是浏览器原生支持的实时音视频通信技术&#xff0c;无需安装插件或客户端&#xff0c;可直接在浏览器之间实现点对点&#xff08;P2P&#xff09…

[STM32学习笔记(九)]CubeMX项目使用系统定时器SysTick的中断服务函数进行定时

有很多文章说明了由于HAL_Delay()函数的本质是系统定时器计数&#xff0c;通过全局变量uwTick的不断增加实现的比较延迟。调用HAL_Delay()函数会阻塞其他工作&#xff0c;因此在外设ISR进程调用该延迟时&#xff0c;要特别小心。 因此&#xff0c;现在考虑&#xff0c;既然系统…

将ipynb文件转换为markdown格式文件

文章目录 将ipynb文件转换为markdown格式文件nbconvert 包安装nbconvert 使用 将ipynb文件转换为markdown格式文件 有时候&#xff0c;我们需要把Jupyter notebook的.ipynb格式文件转换为markdown格式.md&#xff0c;便于使用。 那么&#xff0c;我们可以通过安装nbconvert包&a…

Vulnhub_Zico2_wp

一、信息收集 1、主机发现 arp-scan -l 2、端口扫描 nmap -sS -sV 192.168.66.144 nmap -p- -Pn -sC -sV -n 192.168.66.144 whatweb -v 192.168.66.144 这里开放了3个端口&#xff0c;先80端口拿去目录&#xff0c;然后测试下22端口有没有什么未授权之类的&#xff0c;然后…

【玩转腾讯混元大模型】腾讯混元大模型AIGC系列产品深度体验

【玩转腾讯混元大模型】腾讯混元大模型AIGC系列产品深度体验 腾讯推出的系列AI产品&#xff1a;混元大模型、大模型图像创作引擎、大模型视频创作引擎、腾讯元宝&#xff0c;共同构成了一个强大的AI生态系统&#xff1b;凭借腾讯自研的大规模预训练技术和先进的自然语言处理、计…

Attention Is All You Need论文阅读笔记

Attention is All You Need是如今机器学习研究者必读的论文&#xff0c;该文章提出的Transformer架构是如今很多机器学习项目的基础&#xff0c;说该文章极大推动了机器学习领域的研究也不为过。 但这么重要&#xff0c;也是必读的文章对初学者来说其实并不友好&#xff0c;很多…

如何制作全景VR图?

全景VR图&#xff0c;特别是720度全景VR&#xff0c;为观众提供一种沉浸式体验。 全景VR图能够捕捉场景的全貌&#xff0c;还能将多个角度的图片或视频无缝拼接成一个完整的全景视角&#xff0c;让观众在虚拟环境中自由探索。随着虚拟现实&#xff08;VR&#xff09;技术的飞速…

Flask与PostgreSQL交互教程

目录 1. 项目结构2. 环境准备2.1 安装依赖2.2 使用Docker启动PostgreSQL 3. 数据库配置3.1 环境变量配置3.2 数据库连接配置 4. 定义数据库模型5. 实现API接口5.1 创建用户5.2 获取所有用户5.3 获取单个用户5.4 更新用户5.5 删除用户 6. 运行应用7. API测试7.1 创建用户7.2 获取…

XJTU-SY轴承振动数据集的json自封装

1.最终形式的形式 不用再去翻文档找对应的故障类型&#xff0c;采样率等信息了&#xff0c;所有的信息自包含在.json文件里&#xff0c;15个测试例&#xff0c;一个测试例对应一整个.json文件。 {"dataset": {"name": "XJTU-SY_Bearing_Datasets&quo…

Spring AI 系列2: Advisors增强器简介

一、Advisors简介 1.1 Advisors定义 Advisors 是在 AI 应用程序中处理请求和响应的拦截器。我们可以使用它们为提示流程设置额外的功能。例如&#xff0c;可以建立聊天历史、排除敏感词或为每个请求添加额外的上下文。 Spring AI的Advisor&#xff0c;本质上是一个拦截…

通过Func实现飞书应用通知消息加急处理

前言 在现代企业运作中&#xff0c;及时响应告警信息对保障系统的稳定性和业务的连续性至关重要。随着业务的数字化转型&#xff0c;越来越多的企业依赖于复杂的技术架构&#xff0c;这使得故障和异常事件的及时处理变得愈发重要。传统的告警通知方式往往存在响应不及时、信息…

【目标检测】【AAAI-2022】Anchor DETR

Anchor DETR&#xff1a; Query Design for Transformer-Based Object Detection 锚点DETR&#xff1a;基于Transformer的目标检测查询设计 论文链接 代码链接 摘要 在本文中&#xff0c;我们提出了一种基于Transformer的目标检测新型查询设计。此前的Transformer检测器中&am…