Skip to main content

3通用编程范式

[1][Rust语言入门视频教程,Rust编程入门视频教程(视频)](https://www.bilibili.com/video/BV1hp4y1k7SV)

[2][Rust 程序设计语言 简体中文版(文档)](https://kaisery.github.io/trpl-zh-cn/ch07-05-separating-modules-into-different-files.html)

3 通用编程范式

  • 3.1 - 变量与可变性
  • 3.2 - 数据类型:标量类型
  • 3.3 - 数据类型:复合类型
  • 3.4 - 函数和注释
  • 3.5 - 控制流

3.1 - 变量与可变性

变量

变量默认是不可改变的(immutable),这是 Rust 提供给你的众多优势之一。

fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
=>> ❌

报错:x = 6; | ^^^^^ cannot assign twice to immutable variable

fn main() {
let mut x = 5;
x = 6;
}

=>> ✅
常量

示例

const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
隐藏

我们可以定义一个与之前变量同名的新变量,编译器将看到第二个变量,第二个变量 “隐藏” 了第一个变量。

示例

fn main() {
let x = 5;

let x = x + 1;

{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}

println!("The value of x is: {x}");
}

=>>
The value of x in the inner scope is: 12
The value of x is: 6

隐藏于mut的区别:

  • 重新赋值如果不是mut,则会报错;而且隐藏后还是不可变类型
  • 隐藏可以改变数据类型
let spaces = "   ";                 // 字符串类型
let spaces = spaces.len(); // 数字类型

3.2 - 数据类型:标量类型

rust是 静态类型statically typed)语言,也就是说在编译时就必须知道所有变量的类型。

标量类型
类型
整数类型
浮点类型
布尔类型
字符类型

表格 3-1: Rust 中的整型

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize
  • 有符号数字范围:-(2n - 1) 到 2n - 1 - 1
  • 无符号数字范围:0 到 2n - 1
  • isizeusize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的, 32 位架构上它们是 32 位的,使用场景是对某种集合进行索引操作
数字字面值

表格 3-2: Rust 中的整型字面值

数字字面值例子
Decimal (十进制)98_222
Hex (十六进制)0xff
Octal (八进制)0o77
Binary (二进制)0b1111_0000
Byte (单字节字符)(仅限于u8)b'A'
整型溢出

溢出会有两种情况:

  • debug 模式编译时,Rust 检查这类问题并使程序 panic
  • 在 release 构建中,Rust 不检测溢出,相反会进行一种被称为二进制补码包装(环绕),即值 256 变成 0,值 257 变成 1,依此类推
浮点类型

rust中,浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数(默认)。

Rust 中的所有数字类型都支持基本数学运算:加法、减法、乘法、除法和取余。整数除法会 向下舍入 到最接近的整数。

字符类型

占四个字节大小,用单引号声明

let c = 'z';
let z: char = 'ℤ'; // with explicit type annotation
let heart_eyed_cat = '😻';

3.3 - 数据类型:复合类型

Rust 有两个原生的复合类型:元组(tuple)和数组(array)。

元组类型

将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定:一旦声明,其长度不会增大或缩小。

let tup: (i32, f64, u8) = (500, 6.4, 1);

元组解构

let tup = (500, 6.4, 1);
let (x, y, z) = tup;

点号访问

let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
=>> 500
数组类型

与元组不同,数组中的每个元素的 类型必须相同

let a = [1, 2, 3, 4, 5];

类型声明

let a: [i32; 5] = [1, 2, 3, 4, 5];
// 5个元素,都是i32类型

let a = [3; 5];
// 5个元素,值都是3

3.4 - 函数和注释

Rust 代码中的函数和变量名使用 snake case 规范风格

fn main() {
another_function(5);
}

fn another_function(x: i32) {
println!("The value of x is: {x}");
}
  • 在函数签名中,必须 声明每个参数的类型
  • 函数体由一系列的语句和一个可选的结尾表达式构成
语句和表达式

Rust 是一门基于表达式(expression-based)的语言,这是一个需要理解的(不同于其他语言)重要区别

名称例子错误例子❌
语句Statements)是执行一些操作但不返回值的指令let y = 6;x = y = 6,因为y=6在rust中没有返回值
表达式Expressions)计算并产生一个值,可以被赋值函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块作用域也是一个表达式
let y = {
let x = 3;
x + 1
};

=>> y is 3

表达式的结尾没有分号。如果在表达式的结尾加上分号,它就变成了语句,而语句不会返回值

注释
单行注释文档注释
/////

3.5 - 控制流

if 表达式
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else {
println!("number is not divisible by 4, 3, or 2");
}

注意,代码中的条件 必须bool 值,否则会到一个错误

let 语句中使用 if

因为 if 是一个表达式,我们可以在 let 语句的右侧使用它

let number = if condition { 5 } else { 6 };
循环

Rust 有三种循环:loopwhilefor

loop重复循环

loop {
println!("again!");
}

从循环返回值

let result = loop {
counter += 1;

if counter == 10 {
break counter * 2;
}
};

循环标签:在多个循环之间消除歧义

注意标签是一个单引号

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

while条件循环

while number != 0 {
println!("{number}!");

number -= 1;
}

使用 for 遍历集合

let a = [10, 20, 30, 40, 50];

for element in a {
println!("the value is: {element}");
}
for number in (1..4).rev() {
println!("{number}!");
}
  • (1...4) 表示产生随机数1~4(左闭右开)

  • rev表示反转