Rust 程序设计语言学习——基础语法

news2024/11/16 3:16:34

Rust 语言是一种高效、可靠的通用高级语言。其高效不仅限于开发效率,它的执行效率也是令人称赞的,是一种少有的兼顾开发效率和执行效率的语言。

Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月。Rust 的编译器是在 MIT License 和 Apache License 2.0 双重协议声明下的免费开源软件。

Rust 官方在线工具: https://play.rust-lang.org/。

一、Rust 语言的特点

  • 高性能:Rust 速度惊人且内存利用率极高。由于没有运行时和垃圾回收,它能够胜任对性能要求特别高的服务,可以在嵌入式设备上运行,还能轻松和其他语言集成。

  • 可靠性:Rust 丰富的类型系统和所有权模型保证了内存安全和线程安全,在编译期就能够消除各种各样的错误。

  • 生产力:Rust 拥有出色的文档、友好的编译器和清晰的错误提示信息,还集成了一流的工具 —— 包管理器和构建工具, 智能地自动补全和类型检验的多编辑器支持,以及自动格式化代码等等。

二、基础语法

第一个 Rust 程序

Rust 语言代码文件后缀名为 .rs, 如 helloworld.rs。

fn main() {
    println!("Hello World!");
}

使用 rustc 命令编译 helloworld.rs 文件:

$ rustc helloworld.rs # 编译 helloworld.rs 文件

编译后会生成 helloworld 可执行文件:

$ ./helloworld # 执行 helloworld

Hello World!

2.1 简要介绍 println!() 和 print!()

println!( “Hello World”) 中的 println 后面还有一个 ! 符号,println 不是一个函数,而是一个宏规则。

Rust 输出文字的方式主要有两种:println!()print!()。这两个"函数"都是向命令行输出字符串的方法,区别仅在于前者会在输出的最后附加输出一个换行符。当用这两个"函数"输出信息的时候,第一个参数是格式字符串,后面是一串可变参数,对应着格式字符串中的"占位符",这一点与 C 语言中的 printf 函数很相似。但是,Rust 中格式字符串中的占位符不是 “% + 字母” 的形式,而是一对 {}

fn main() {
    let a = 12;
    let b = 12.5;
    println!("a is {}, b is {}", a, b);
}

运行结果:

a is 12, b is 12.5

如果想把 a 输出两遍,那岂不是要写成:

println!("a is {}, a again is {}", a, a);

其实有更好的写法:

println!("a is {0}, a again is {0}", a);

在 {} 之间可以放一个数字,它将把之后的可变参数当作一个数组来访问,下标从 0 开始。

如果要输出 { 或 } 怎么办呢?格式字符串中通过 {{ 和 }} 分别转义代表 { 和 }。但是其他常用转义字符与 C 语言里的转义字符一样,都是反斜杠开头的形式。

fn main() { 
    println!("{{}}"); 
}

以上程序的输出结果是:

{}

2.2 变量

Rust 是强类型语言,但具有自动判断变量类型的能力。这很容易让人与弱类型语言产生混淆。如果要声明变量,需要使用 let 关键字。例如:let a = 123;,只学习过 JavaScript 的开发者对这句话很敏感,只学习过 C 语言的开发者对这句话很不理解。

在这句声明语句之后,以下三行代码都是被禁止的:

a = "abc";
a = 4.56; 
a = 456;

第一行的错误在于当声明 a 是 123 以后,a 就被确定为整型数字,不能把字符串类型的值赋给它。

第二行的错误在于自动转换数字精度有损失,Rust 语言不允许精度有损失的自动数据类型转换。

第三行的错误在于 a 不是个可变变量。

Rust 语言为了高并发安全而做的设计:在语言层面尽量少的让变量的值可以改变。所以 a 的值不可变。但这不意味着 a 不是"变量"(英文中的 variable),官方文档称 a 这种变量为不可变变量

如果我们编写的程序的一部分在假设值永远不会改变的情况下运行,而我们代码的另一部分在改变该值,那么代码的第一部分可能就不会按照设计的意图去运转。由于这种原因造成的错误很难在事后找到。这是 Rust 语言设计这种机制的原因。

当然,使变量变得"可变"(mutable)只需一个 mut 关键字。

fn main() {
    let mut a = 123;
    println!("a is {}", a);
    a = 456;
    println!("a is {}", a);
}

这个程序是正确的。

a is 123
a is 456

常量与不可变变量的区别

既然不可变变量是不可变的,那不就是常量吗?为什么叫变量?变量和常量还是有区别的。在 Rust 中,以下程序是合法的:

let a = 123;   // 可以编译,但可能有警告,因为该变量没有被使用
let a = 456;

但是如果 a 是常量就不合法:

const a: i32 = 123;
let a = 456;

报错如下:

   Compiling playground v0.0.1 (/playground)
error[E0005]: refutable pattern in local binding
 --> src/main.rs:3:9
  |
3 |     let a = 456;
  |         ^
  |         |
  |         patterns `i32::MIN..=122_i32` and `124_i32..=i32::MAX` not covered
  |         missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
  |         help: introduce a variable instead: `a_var`
  |
  = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
  = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
  = note: the matched value is of type `i32`

变量的值可以"重新绑定",但在"重新绑定"以前不能私自被改变,这样可以确保在每一次"绑定"之后的区域里编译器可以充分的推理程序逻辑。 虽然 Rust 有自动判断类型的功能,但有些情况下声明类型更加方便:

let a: u64 = 123;

这里声明了 a 为无符号 64 位整型变量,如果没有声明类型,a 将自动被判断为有符号 32 位整型变量,这对于 a 的取值范围有很大的影响。

2.3 重影(Shadowing)

重影的概念与其他面向对象语言里的"重写"(Override)或"重载"(Overload)是不一样的。重影就是所谓的重新绑定。

重影就是指变量的名称可以被重新使用的机制:

fn main() {
    let x = 5;
    let x = x + 1;
    let x = x * 2;
    println!("The value of x is: {}", x);
}

运行结果:

The value of x is: 12

再来看一个例子

fn main() {
    let x = 5; // warning: unused variable: `x`
    let x = 1.5;
    let x = x * 2.0;
    println!("The value of x is: {}", x);
}

运行结果:

The value of x is: 3

重影与可变变量的赋值不是一个概念,重影是指用同一个名字重新代表另一个变量实体,其类型、可变属性和值都可以变化。但可变变量赋值仅能发生值的变化。

let mut s = "123";
s = s.len();

这段程序会出错:不能给字符串变量赋整型值。

2.4 数据类型

Rust 语言中的基础数据类型有以下几种。

2.4.1 整型(Integer)

整数型简称整型,按照比特位长度和有无符号分为以下种类:

位长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

isize 和 usize 两种整数类型是用来衡量数据大小的,它们的位长度取决于所运行的目标平台,如果是 32 位架构的处理器将使用 32 位位长度整型。

整数的表述方法有以下几种:

进制
十进制98_222
十六进制0xff
八进制0o77
二进制0b1111_0000
字节(只能表示 u8 型)b’A’

有的整数中间存在一个下划线,这种设计可以让人们在输入一个很大的数字时更容易判断数字的值大概是多少。

例如:

fn main() {
    let x = 598_000;
    println!("The value of x is: {}", x);
}

运行结果:

The value of x is: 598000
2.4.2 浮点数型(Floating-Point)

Rust 与其它语言一样支持 32 位浮点数(f32)和 64 位浮点数(f64)。默认情况下,64.0 将表示 64 位浮点数,因为现代计算机处理器对两种浮点数计算的速度几乎相同,但 64 位浮点数精度更高。

fn main() {
    let x = 2.0; // f64
    let y: f32 = 3.0; // f32
}

数学运算

用一段程序反映数学运算:

fn main() {
    let sum = 5 + 10; // 加
    let difference = 95.5 - 4.3; // 减
    let product = 4 * 30; // 乘
    let quotient = 56.7 / 32.2; // 除
    let remainder = 43 % 5; // 求余
}

许多运算符号之后加上 = 号是自运算的意思,例如:

sum += 1 等同于 sum = sum + 1

注意:Rust 不支持 ++ 和 --,因为这两个运算符出现在变量的前后会影响代码可读性,减弱了开发者对变量改变的意识能力。

2.4.3 布尔型

布尔型用 bool 表示,值只能为 true 或 false。

2.4.4 字符型

字符型用 char 表示。Rust 的 char 类型大小为 4 个字节,代表 Unicode 标量值,这意味着它可以支持中文、日文和韩文等非英文字符,甚至表情符号和零宽度空格在 Rust 中都是有效的 char 值。

Rust 使用 char 类型表示单个字符,但对字符串或文本流使用 UTF-8 编码。因此,String 将其文本表示为一个 UTF-8 字节的序列,而不是字符的数组。Rust 的 char 类型是语言中最原生的字母类型,例如:

fn main() {
    let c = 'z';
    let z = 'ℤ';
    let heart_eyed_cat = 'ᛀ';
    println!("The value is: {} {} {}", c, z, heart_eyed_cat);
}

运行结果:

The value is: z ℤ ᛀ

Rust 还是提供了字节字面量(byte literal),即用类字符字面量表示的 u8 值:b’X’ 表示 ASCII 编码的字符 X,它是一个 u8 值。比如,由于字符 A 的 ASCII 编码是 65,因此 b’A’ 等于 65u8。字节字面量中只能出现 ASCII 编码的字符。

注意:由于中文文字编码有两种(GBK 和 UTF-8),所以编程中使用中文字符串有可能导致乱码的出现,这是因为源程序与命令行的文字编码不一致,所以在 Rust 中字符串和字符都必须使用 UTF-8 编码,否则编译器会报错。

2.4.5 复合类型

元组是用一对 ( ) 包括的一组数据,可以包含不同种类的数据:

let tup: (i32, f64, u8) = (500, 6.4, 1);
// tup.0 等于 500
// tup.1 等于 6.4
// tup.2 等于 1
let (x, y, z) = tup;
// y 等于 6.4

程序首先创建了一个元组并绑定到 tup 变量上。接着使用了 let 和一个模式将 tup 分成了三个不同的变量 x、y 和 z。这叫做解构(destructuring),因为它将一个元组拆成了三个部分。

我们也可以使用点号(.)后跟值的索引来直接访问它们。例如:

fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
}

这个程序创建了一个元组 x,然后使用其各自的索引访问元组中的每个元素。跟大多数编程语言一样,元组的第一个索引值是 0。

不带任何值的元组有个特殊的名称,叫做单元(unit) 元组。这种值以及对应的类型都写作 (),表示空值或空的返回类型。如果表达式不返回任何其他值,则会隐式返回单元值。

数组用一对 [ ] 包括的同类型数据。

let a = [1, 2, 3, 4, 5]; // a 是一个长度为 5 的整型数组
let b = ["January", "February", "March"]; // b 是一个长度为 3 的字符串数组
let c: [i32; 5] = [1, 2, 3, 4, 5]; // c 是一个长度为 5 的 i32 数组
let d = [3; 5]; // 等同于 let d = [3, 3, 3, 3, 3];

let first = a[0]; // 数组访问
let second = a[1];

a[0] = 123; // 错误:数组 a 不可变
let mut a = [1, 2, 3];
a[0] = 4; // 正确

2.5 注释

Rust 中的注释方式与其它语言(C、Java)一样,双斜杠的注释方式前面已经接触过,实际上支持三种注释方式:

// 这是第一种注释方式

/* 这是第二种注释方式 */

/*
 * 多行注释
 * 多行注释
 * 多行注释
 */

在 Rust 中使用 // 可以使其之后到第一个换行符的内容变成注释。

在这种规则下,三个正斜杠 /// 依然是合法的注释开始。所以 Rust 可以用 /// 作为说明文档注释的开头:

/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let x = add(1, 2);
///
/// ```

fn add(a: i32, b: i32) -> i32 {
    return a + b;
}
   
fn main() {
    println!("{}",add(2, 3));
}

IDE 中加载的效果如下:

在这里插入图片描述

2.6 函数

函数实际上前面已经有所了解,运行示例一直在使用 main 函数。Rust 函数的基本形式:

fn <函数名> ( <参数> ) -> <返回值类型> <函数体>

其中 Rust 函数名称的命名风格是小写字母以下划线分割:

fn main() {
    println!("Hello, world!");
    another_fn();
}

fn another_fn() {
    println!("Hello, another_fn!");
}

2.6.1 函数参数

Rust 中定义函数如果需要具备参数必须声明参数名称和类型:

fn main() {
    another_fn(100, 6);
}

fn another_fn(x: i32, y: i32) {
    println!("The value of x is {}. The value of y is {}", x, y);
}

运行结果:

The value of x is 100. The value of y is 6

2.6.2 函数体表达式

Rust 中可以在一个用 {} 包括的块里编写一个较为复杂的表达式:

fn main() {
    let x = 100;

    let y = {
        let x = 20;
        x + 1
    };

    println!("The value of x is {}. The value of y is {}", x, y);
}

运行结果:

The value of x is 100. The value of y is 21

很显然,这段程序中包含了一个表达式块:

let y = {
    let x = 20;
    x + 1
};

而且在块中可以使用函数语句,最后一个步骤是表达式,此表达式的结果值是整个表达式块所代表的值。这种表达式块叫做函数体表达式。

注意:x + 1 之后没有分号,否则它将变成一条语句!

这种表达式块是一个合法的函数体。而且在 Rust 中,函数定义可以嵌套:

fn main() {
    fn five() -> i32 {
        5
    }
    
    println!("The value of five() is {}.", five());
}

运行结果:

The value of five() is 5.

2.6.3 函数返回值

Rust 函数声明返回值类型的方式为在参数声明之后用 -> 来声明函数返回值的类型。在函数体中,随时都可以以 return 关键字结束函数运行并返回一个类型合适的值。这也是最接近大多数开发者经验的做法:

fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

但是 Rust 不支持自动返回值类型判断!如果没有明确声明函数返回值的类型,函数将被认为是"纯过程",不允许产生返回值,return 后面不能有返回值表达式。

注意:函数体表达式并不能等同于函数体,它不能使用 return 关键字。

2.7 条件语句

在 Rust 语言中的条件语句是这种格式的:

fn main() {
    let number = 3;
    if number < 5 {
        println!("true");
    } else {
        println!("false");
    }
}

在上述程序中有条件 if 语句,这个语法在很多其它语言中很常见,但也有一些区别:首先,条件表达式 number < 5 不需要用小括号包括(注意,不需要不是不允许);但是 Rust 中的 if 不存在单语句不用加 {} 的规则,不允许使用一个语句代替一个块。尽管如此,Rust 还是支持传统 else-if 语法的:

fn main() {
    let x = 100;
    let y;
    if x > 0 {
        y = 1;
    }  
    else if (x < 0) { // warning: unnecessary parentheses around `if` condition
        y = -1;
    }  
    else {
        y = 0;
    }
    println!("The value of y is {}", y);
}

以上第二个判断条件 else if (x < 0) 加了圆括号,编译运行的时候会有相关警告。

运行结果:

The value of y is 1

Rust 中的条件表达式必须是 bool 类型,例如下面的程序是错误的:

fn main() {
    let number = 100;
    if number {   // error[E0308]: mismatched types,expected `bool`, found integer
        println!("true");
    }
}

虽然 C/C++ 语言中的条件表达式用整数表示,非 0 即真,但这个规则在很多注重代码安全性的语言中是被禁止的。

在 Rust 中我们可以使用 if-else 结构实现类似于三元条件运算表达式 (A ? B : C) 的效果:

fn main() {
    let x = 100;
    let y = if x > 0 { 1 } else { -1 };
    println!("The value of y is {}", y);
}

运行结果:

The value of y is 1

注意:两个函数体表达式的类型必须一样,且必须有一个 else 及其后的表达式块。

2.8 循环

Rust 除了灵活的条件语句以外,循环结构的设计也十分成熟。

2.8.1 while 循环

while 循环是最典型的条件语句循环:

fn main() {
    let mut number = 0;
    while number != 5 {
        println!("{}", number);
        number += 1;
    }
    println!("EXIT");
}

运行结果:

0
1
2
3
4
EXIT

Rust 语言到目前还没有 do-while 的用法,但是 do 被规定为保留字,也许以后的版本中会用到。

fn main() {
    let mut number = 0;
    do {
        println!("{}", number);
        number += 1;
    } while number != 5;
    println!("EXIT");
}

以上代码编译会报错:error: expected expression, found reserved keyword do

在 C 语言中 for 循环使用三元语句控制循环:

int i;
for (i = 0; i < 10; i++) {
    // 循环体
}

但是 Rust 中没有这种用法,需要用 while 循环来代替:

let mut i = 0;
while i < 10 {
    // 循环体
    i += 1;
}

2.8.2 for 循环

for 循环是最常用的循环结构。比如 for 循环遍历数组:

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;
    for value in a.iter() {
        println!("The value of a[{}] is {}", index, value);
        index += 1;
    }
}

运行结果:

The value of a[0] is 10
The value of a[1] is 20
The value of a[2] is 30
The value of a[3] is 40
The value of a[4] is 50

这个程序中的 for 循环完成了对数组 a 的遍历。a.iter() 代表 a 的迭代器(iterator),实际上,for 循环其实是可以通过下标来访问数组的:

fn main() {
    let a = [10, 20, 30, 40, 50];
    for index in 0..5 {
        println!("The value of a[{}] is {}", index, a[index]);
    }
}

运行结果和上面是一样的。注意此处 0…5 这个范围使用时包含了 0,却未包含 5。

2.8.3 loop 循环

Rust 语言有原生的无限循环结构 —— loop:

fn main() {
    let s = ['L', 'O', 'O', 'P', 'E', 'R'];
    let mut i = 0;
    loop {
        let ch = s[i];
        if ch == 'E' {
            break;
        }
        println!("The value of s[{}] is {}", i, ch);
        i += 1;
    }
}

运行结果:

The value of s[0] is L
The value of s[1] is O
The value of s[2] is O
The value of s[3] is P

loop 循环可以通过 break 关键字类似于 return 一样使整个循环退出并给予外部一个返回值。这是一个十分巧妙的设计,因为 loop 这样的循环常被用来当作查找工具使用,如果找到了某个东西当然要将这个结果交出去:

fn main() {
    let s = ['L', 'O', 'O', 'P', 'E', 'R'];
    let mut i = 0;
    let location = loop {
        let ch = s[i];
        if ch == 'E' {
            break i;
        }
        println!("The value of s[{}] is {}", i, ch);
        i += 1;
    };
    
    println!("The index of \'E\' is {}", location);
}

运行结果:

The value of s[0] is L
The value of s[1] is O
The value of s[2] is O
The value of s[3] is P
The index of 'E' is 4

2.8.4 循环标签

如果存在嵌套循环,breakcontinue 应用于此时最内层的循环。选择在一个循环上指定一个循环标签(loop label),然后将标签与 breakcontinue 一起使用,使这些关键字应用于已标记的循环而不是最内层的循环。

fn main() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {count}");
        let mut remaining = 10;

        loop {
            println!("remaining = {remaining}");
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;
            }
            remaining -= 1;
        }

        count += 1;
    }
    println!("End count = {count}");
}

外层循环有一个标签 counting_up,它将从 0 数到 2。没有标签的内部循环从 10 向下数到 9。第一个没有指定标签的 break 将只退出内层循环。break 'counting_up; 语句将退出外层循环。

运行结果:

count = 0
remaining = 10
remaining = 9
count = 1
remaining = 10
remaining = 9
count = 2
remaining = 10
End count = 2

参考链接

  1. Rust 官方网站:https://www.rust-lang.org/zh-CN
  2. Rust 官方文档:https://doc.rust-lang.org/
  3. Rust Play:https://play.rust-lang.org/

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

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

相关文章

【好用的AI工具】推荐测试人在用的Kimi Chat

一、功能介绍 发网址链接文章解析PDF文件分析&#xff0c;可以整理分析文章丢简历、给出面试问题聊天等 Kimi Chat 二、对于测试人带来的帮助 2.1 面试问题总结 问题一&#xff1a;Session和Cookie的区别 seeion 和 cookie 是两种不同的数据存储机制&#xff0c;它们在Web开…

【C语言深度剖析——第四节(关键字4)】《C语言深度解剖》+蛋哥分析+个人理解

追求本质&#xff0c;不断进步 本文由睡觉待开机原创&#xff0c;转载请注明出处。 本内容在csdn网站首发 欢迎各位点赞—评论—收藏 如果存在不足之处请评论留言&#xff0c;共同进步&#xff01; 这里写目录标题 一、空间的申请1.变量定义1.1变量定义的概念&#xff1a;1.2变…

基本控件(一)

目录 控件的定义&#xff1a;使用控件的好处&#xff1a; setupUiwidget.hwidget.cppmain.cpp 控件的定义&#xff1a; QT控件是在QT框架下实现的一组用户界面元素&#xff0c;包括按钮、标签、输入框、列表框、滚动条、菜单等等&#xff0c;它们用于快速构建各种应用程序的图…

工业相机与镜头参数及选型

文章目录 1、相机成像系统模型1.1 视场1.2 成像简化模型 2、工业相机参数2.1 分辨率2.2 靶面尺寸2.3 像元尺寸2.4 帧率/行频2.5 像素深度2.6 动态范围2.7 信噪比2.8 曝光时间2.9 相机接口 3、工业镜头参数3.1 焦距3.2 光圈3.3 景深3.4 镜头分辨率3.5 工作距离&#xff08;Worki…

大模型笔记【3】 gem5 运行模型框架LLama

一 LLama.cpp LLama.cpp 支持x86&#xff0c;arm&#xff0c;gpu的编译。 1. github 下载llama.cpp https://github.com/ggerganov/llama.cpp.git 2. gem5支持arm架构比较好&#xff0c;所以我们使用编译LLama.cpp。 以下是我对Makefile的修改 开始编译&#xff1a; make UNAME…

详解SpringCloud微服务技术栈:DockerCompose部署微服务集群

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;Gateway网关&#xff08;断言、过滤器、跨域问题&#xff09; &#x1f4da;订阅专栏&…

【.NET Core】多线程之线程池(ThreadPool)详解(二)

【.NET Core】多线程之线程池&#xff08;ThreadPool&#xff09;详解&#xff08;二&#xff09; 在上一篇《【.NET Core】多线程之线程池&#xff08;ThreadPool&#xff09;详解&#xff08;一&#xff09;》中我们详细讲解了&#xff0c;线程池概念&#xff0c;如何应用及…

测试C#调用OpenCvSharp和ViewFaceCore从摄像头中识别人脸

学习了基于OpenCvSharp获取摄像头数据&#xff0c;同时学习了基于ViewFaceCore的人脸识别用法&#xff0c;将这两者结合即是从摄像头中识别人脸。本文测试测试C#调用OpenCvSharp和ViewFaceCore从摄像头中识别人脸&#xff0c;并进行人脸红框标记。   新建Winform项目&#xf…

白盒测试?看这一篇就够了

白盒测试&#xff1f;看这一篇就够了 什么是白盒测试&#xff1a;白盒测试流程白盒测试技术白色测试分 2 个步骤进行白盒测试的特点白盒测试的优点白盒测试的缺点 五星上将麦克阿瑟曾经说过“在白盒测试面前&#xff0c;黑盒测试就是弟弟“ 什么是白盒测试&#xff1a; 白盒测…

10篇深度学习时间序列预测综述汇总!含金融、医疗、气象等领域应用!

在当今数据驱动的时代&#xff0c;时间序列预测在金融、医疗和气象等领域发挥着关键作用&#xff0c;而深度学习作为人工智能领域的重要分支&#xff0c;为解决时间序列预测问题提供了强大的工具。 为了帮助大家深入理解深度学习时间序列预测&#xff0c;这里整理了10篇深度学习…

springboot配置项动态刷新

文章目录 一&#xff0c;序言二&#xff0c;准备工作1. pom.xml引入组件2. 配置文件示例 三&#xff0c;自定义配置项动态刷新编码实现1. 定义自定义配置项对象2. 添加注解实现启动时自动注入3. 实现yml文件监听以及文件变化处理 四&#xff0c;yaml文件转换为java对象1. 无法使…

Oracle认证 | 甲骨文Oracle认证含金量高吗?

“考证”在各行各业中一直都是热度不减的话题&#xff0c;IT领域也不例外。 对于在校学生来说&#xff0c;并没有太多实践经验&#xff0c;证书在一定程度上就是找工作时的“敲门砖”&#xff0c;多张证书多条路&#xff1b; 对于职场人士来说&#xff0c;证书在升职加薪、跳…

基于springboot+vue的网上购物商城(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

【设计模式】张一鸣笔记:责任链接模式怎么用?

我将通过一个贴近现实的故事——请假审批流程&#xff0c;带你了解和掌握责任链模式。 什么是责任链模式&#xff1f; 责任链模式是一种行为设计模式&#xff0c;它让你可以避免将请求的发送者与接收者耦合在一起&#xff0c;让多个对象都有处理请求的机会将这个对象连成一条…

【架构师专题】架构师如何做好业务架构?

作为一个优秀的架构师&#xff0c;必须要先训练自己的业务架构技能&#xff0c;但是要训练之前&#xff0c;一定要先理解“业务架构”的定义。 业务架构 那么什么是业务架构呢&#xff1f;这里我给大家梳理了一个比较准确的定义。 “业务架构”是一个企业或组织在运营过程中…

大模型日报-20240122

清华、小米、华为、 vivo、理想等多机构联合综述&#xff0c;首提个人LLM智能体、划分5级智能水平 https://mp.weixin.qq.com/s/JYB4BzsXhWF8pEUUkvn_GQ 想必这些唤醒词中至少有一个曾被你的嘴发出并成功呼唤出了一个能给你导航、讲笑话、添加日程、设置闹钟、拨打电话的智能个…

gradle构建spring-framework源码

5.3.22版本构建 通过启动的jvm参数配置代理下载 Could not download jruby-stdlib-9.2.20.1.jar (org.jruby:jruby-stdlib:9.2.20.1) Could not get resource https://repo.maven.apache.org/maven2/org/jruby/jruby-stdlib/9.2.20.1/jruby-stdlib-9.2.20.1.jar. Could not GE…

Vue3组件库开发 之Button(2) 未完待续

Vue3组件库开发 之Button(1) 中新建项目&#xff0c;但未安装成功ESLINT 安装ESLINT npm install eslint vite-plugin-eslint --save-dev 安装eslint后&#xff0c;组件文件出现错误提示 添加第三方macros &#xff0c;虽然不是官网但很多开发者都是vue3开发人员 安装macros…

SAP CDS VIEW实现行列转换

需求&#xff1a; 销售订单上的业务伙伴数据都在VBPA存储&#xff0c;根据PARVW来区分是售达方或者是送达方等等&#xff0c;有时候一些报表取数时有一些条件&#xff0c;比如售达方等于xxxxx并且送达方等于xxxxx&#xff0c;这时候就不是简单的一条sql就能搞定的事了&#xf…

基于扩散模型语音驱动人物头像说话模型:DreamTalk

1 DreamTalk介绍 DreamTalk&#xff1a;由清华大学、阿里巴巴和华中科大共同开发的一个基于扩散模型让人物头像说话的框架。 能够根据音频让人物头像照片说话、唱歌并保持嘴唇的同步和模仿表情变化。这一框架具有以下特点: DreamTalk能够生成高质量的动画&#xff0c;使人物脸…