Skip to main content

Chapter3 Common Programming Concepts

Variables and Mutability

默认情况下, 定义的变量时不可变的. 如果要定义可变变量, 则使用 mut.

常量实际时值绑定到一个名字, 并且不允许中编译后修改, 使用 const 定义.

const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 *3;

Rust 编译器能够对有限的操作进行值计算, 详见官方文档.

常量的生命期是整个 APP 运行期间.

关于变量的名字覆盖, 可以在相同/不同作用域下覆盖变量, 但不能进行改变类型的覆盖.

// !! 这种改变类型的覆盖是不允许的.
let mut spaces = " ";
spaces = spaces.len();

Data Types

Rust 中每个值都有确定的类型, 有两大类数据类型:

  • 原子类型(Scalar)
  • 组合类型(Compound)

Scalar Types

有如下四类原子类型:

  • 整型(Integers): i8/u8/i16/u16/i32/u32/i64/u64/i128/u128/isize/usize
    • Integer 常量写法: 98_222(Decimal), 0xff(Hex), 0o77(Octal), 0b111_000(Binary), b'A'(Byte u8 only)
    • Rust 在 Release 编译时不会进行整型溢出检测, 意味着当溢出发生时, Rust 会进行归位(比如 u8 在 256 时溢出后会变成 0, 257 时溢出变为 1, 以此类推), 而在 Debug 编译时溢出会引起 panic.
    • Rust 在整数运算时的行为时整除.
  • 浮点类型(Floating-Point Numbers): f32/f64, 类型推断时默认浮点类型时 f64.
  • 布尔类型(Booleans): true/false
  • 字符型(Characters): 'a', 'A' 等, 字符型是 UTF-8 编码的, 即它每一个都是 4 字节大小.
    • Unicode 字符取值范围是: [U+0000, U+D7FF] 以及 [U+E000, U+10FFFF].

Compound Types

组合类型时一系列值的集合, Rust 有两种基本组合类型:

  • Tuple
  • Array

Tuple Type

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

let (x, y, z) = tup; // destruction

let e = tup.0;

Array Type

fn main() {
let a1 = [1,2, 3, 4, 5];
let months = ["apple", "bird", "cat", "dog"];
let a2: [u8; 5] = [6, 7, 8, 9, 10]
let a3 = [3; 5]; // [5, 5, 5]
let first_elem = a1[0];
}

Rust 会进行数组越界检查.

函数

fn add(a: u8, b: u8) -> u8 {
a + b
}

Expressions

fn main() {
let y = {
let x = 3;
x + 1
} // y equals 4
}

Control Flow

fn main() {
let num = 3;
if num > 5 {
println!("condition was false");
} else {
println!("condition was true");
}
// if 可以用在 let 表达式右侧, 类似三元操作符 ?: 的作用
let num = if xxx { 5 } else { 6 };
}

循环

可以使用 loop 进行无限循环.

fn main() {
let mut counter = 0;
// 可以从循环中获取结果值
let result = loop { // result equals 10
counter += 1;
if counter > 10 {
break counter;
}
};

while counter != 0 {
counter -= 1;
}

let a1 = [1, 2, 3, 4, 5];
for elem in a1 { // 1, 2, 3, 4, 5
// ...
}

for num in (1..4).rev() {// 3, 2, 1
// ...
}

loop { // infinite loop
println!("hello");
}
}

可以为 loop 设置标签, 这样比较方便地就可以 break 对应循环(嵌套循环的情况下):

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

使用 while 进行有条件的循环:

fn main() {
let mut number = 3;

while number != 0 {

println!("{number}!");
number -= 1;
}

println!("LIFTOFF!!!");
}

使用 for 循环遍历集合:

fn main() {
for number in (1..4).rev() {
println!("{number}!");
}

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

for element in a {
println!("the value is: {element}");
}
}