# 三.语句

前言

一个语句只是执行某个动作,但是不返还任何值

语句由关键字标识符操作符组成的表达式组成,通过不同的关键字可以分为几类

# 1.声明语句

用于声明各种语言项,包括声明变量,常量,结构体,函数等,以及通过 extern 和 use 关键字引入包和模块等

# 1.1 变量

# 1.1.1 声明

关键字let用于声明变量,声明变量的同时会确定其作用域

# 1.1.1.1 初次声明
  • 1.只声明,后面可以再赋值(类型会推导,所以不用指明)
let a;
a=1;
1
2
  • 2.声明赋值同时进行(类型会推导,所以不用指明)
let a:i32 = 1;
1
# 1.1.1.2 重新声明

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

let a = 1
let a = 1
1
2
# 1.1.2 作用域

变量的作用域是程序在其中定义的区域,作用域确定变量的可访问性(可见性)

# 1.1.2.1 块作用域

变量在其声明的块内有效

fn main() {
    // 模块作用域变量
    let module_scope = "模块作用域";
    {
        // 块作用域变量
        let block_scope = "块作用域";
        // 可以访问module_scope和block_scope
        println!("在块内: {}", block_scope);
    }
    // 可以访问module_scope,但不能访问block_scope,因为它在块作用域内并已经不再有效
    println!("在块外: {}", module_scope);
}
1
2
3
4
5
6
7
8
9
10
11
12
# 1.1.2.2 模块作用域

变量在其声明的模块内有效,除非使用 use 关键字导入

# 1.2 函数

# 1.2.1 声明

  • 关键字fn用于声明函数,不能和变量一样能重新声明
fn a() {}
1

# 1.2.2 作用域

fn声明的函数作用域在代码块{}

{                      // s 在这里无效, 它尚未声明
    let s = "hello";   // 从此处起,s 是有效的
    // 使用 s
}                      // 此作用域已结束,s 不再有效
1
2
3
4

# 1.3 模块

# 1.2.1 声明

  • 关键字mod用于声明模块
mod outer {
    pub fn public_function() -> i32 {
        5
    }
}
1
2
3
4
5

# 1.2.2 使用

  • 关键字use用于导入模块模块,::表示模块内部的函数
fn main() {
    use outer::public_function; // 导入函数,不导入变量

    let result = public_function(); // 调用outer模块中的函数
    println!("结果: {}", result);
}
1
2
3
4
5
6

# 2.赋值语句

# 2.1 基本数据类型

# 2.1.1 整型

a = 1
1

# 2.1.2 浮点数

a = 1
1

# 2.1.3 字符

a = 1
1

# 2.1.4 布尔值

a = 1
1

# 2.2 复合数据类型

# 2.2.1 数组

a = 1
1

# 2.2.2 元组

a = 1
1

# 2.2.3 切片

a = 1
1

# 2.2.4 字符串

a = 1
1

# 2.3 自定义数据类型

# 2.3.1 结构体

a = 1
1

# 2.3.2 枚举

a = 1
1

# 3.控制语句

# 3.1 条件控制

# 3.1.1.if

  • 语法格式:if <condition> { block 1 } else { block 2 }
  • 用法 1:if
let number = 3;
if number>0 {  // 条件表达式需要为bool类型
    println!("Yes");
}
1
2
3
4
  • 用法 2:if else
let num = 3;
if num >10{
    println!("条件为true")
}else {
    println!("条件为false")
}
1
2
3
4
5
6
  • 用法 3:if else if else
let a = 12;
let b;
if a > 0 {
    b = 1;
}
else if a < 0 {
    b = -1;
}
else {
    b = 0;
}
println!("b is {}", b);
1
2
3
4
5
6
7
8
9
10
11
12
  • 用法 4: 函数体表达式用法
let n = 13;
let big_n = if n < 10 && n > -10 {// if 表达式可以用来赋值
    10 * n// 分支必须返回同一个类型的值
} else {
    n / 2// 自动截取
};
assert_eq!(big_n, 6);
1
2
3
4
5
6
7

# 3.1.2.match

# 3.1.2.1 字面量模式
let number = 42;
match number {
    0 => println!("Origin"),// 模式为单个值
    1..=3 => println!("All"),// 模式为Range
    5 | 7 | 13 => println!("Bad Luck"),// 模式为 多个值
    n @ 42 => println!("Answer is {}", n),// 绑定模式,将模式中的值绑定给一个变量,供右边执行代码使用
    _ => println!("Common"),// _ 通配符处理剩余情况
}
1
2
3
4
5
6
7
8
let number = 42;
let number2 = 36;
match number.cmp(&number2) {
    std::cmp::Ordering::Less => println!("Origin"),// 模式为单个值
    std::cmp::Ordering::Greater => println!("All"),// 模式为Range
    _ => println!("Common"),// _ 通配符处理剩余情况
}
1
2
3
4
5
6
7
# 3.1.2.2 元祖模式
use std::cmp::Ordering::*;
fn main() {
    let number = 42;
    let number2 = 36;
    match (number.cmp(&number2), number.cmp(&50)) {
        (Less, Less) => println!("Origin"),
        (Greater, Greater) => println!("All"),
        _ => println!("Common"),
    }
}
1
2
3
4
5
6
7
8
9
10
# 3.1.2.3 结构体模式
struct Point {
    x: i32,
    y: i32,
}
fn main() {
    let point = Point { x: 10, y: 10 };
    match point {
        Point { x: 0, y } => println!("Origin {}", y),
        Point { x, y } => println!("All {} {}", x, y),
    }
}
1
2
3
4
5
6
7
8
9
10
11
  • ..忽略不需要的属性
struct Point {
    x: i32,
    y: i32,
    z: i32,
}
fn main() {
    let point = Point {
        x: 10,
        y: 10,
        z: 20,
    };
    match point {
        Point { x: 0, y, .. } => println!("Origin {}", y),
        Point { x, y, .. } => println!("All {} {}", x, y),
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 3.1.2.4 枚举模式
  • Option包裹
struct Point {
    x: i32,
    y: i32,
    z: i32,
}
fn main() {
    let point = Point {
        x: 10,
        y: 10,
        z: 20,
    };
    match Some(point) {
        Some(Point { x, y, .. }) => println!("Origin {}", y),
        _ => println!("All")
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 3.1.2.5 数组模式
let point = [1,2,3];
match point {
    [_,_,3] => println!("Origin"),
    _ => println!("All")
}
1
2
3
4
5
# 3.1.2.6 切片模式

由于切片是变长的,所以使用切片模式可以使用..来匹配任意长度的字符

let point = [1, 2, 3];
let slice = &point[..];
match slice {
    [] => println!("Origin"),
    [a] => println!("Origin {}", a),
    [a, .., c] => println!("Origin {} {}", a, c),
    _ => println!("All"),
}
1
2
3
4
5
6
7
8
# 3.1.2.7 引用模式
  • match表达式中,匹配一个非拷贝的值,会发生所有权转移的情况
  • ref模式用来引用部分值
  • &模式用来匹配引用
# 3.1.2.8 条件守卫
match some_value {
x if x > 10 => println!("⼤于 10 的值: {}", x),
_ => println!("其他值"),
}
1
2
3
4

# 3.2 循环控制

# 3.2.1.for

在条件语句为 true 时,可以将代码块执行指定的次数

# 3.2.2.for ... in

用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)

for n in 1..101 {
if n % 15 == 0 {
    println!("fizzbuzz");
} else if n % 3 == 0 {
    println!("fizz");
} else if n % 5 == 0 {
    println!("buzz");
} else {
    println!("{}", n);
}
}
1
2
3
4
5
6
7
8
9
10
11

# 3.2.3.loop

  • 循环
let s = ['R', 'U', 'N', 'O', 'O', 'B'];
let mut i = 0;
loop {
    let ch = s[i];
    if ch == 'O' {
        break;  // 用于跳出循环
    }
    println!("\'{}\'", ch);
    i += 1;
}
1
2
3
4
5
6
7
8
9
10

# 3.2.4.while

  • 语法格式:while <condition> { block }
let mut n = 1;
while n < 101 {
if n % 15 == 0 {
    println!("fizzbuzz");
} else if n % 3 == 0 {
    println!("fizz");
} else if n % 5 == 0 {
    println!("buzz");
} else {
    println!("{}", n);
}
n += 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3.2.5.do ... while

执行一个语句块,在条件语句为 true 时继续执行该语句块

# 4.表达式语句

特指以分号结束的表达式。

var a = 1;
a = a + 10;
1
2

表达式主要用于计算求值

Rust 编译器在解析代码时:

  • 如果遇到分号,就会继续往后面执行
  • 如果遇到语句,就会执行语句
  • 如果遇到表达式,就会对表达式求值
  • 如果分号后面什么都没有,就会补上单元值()
  • 当遇到函数时,就会将函数体的花括号识别为块表达式

# 2.1 块表达式

块表达式是由一对花括号和一系列表达式组成的,它总是返回块中最后一个表达式的值

var a = 1;
a = a + 10;
1
2

# 2.2 位置表达式

位置表达式(Place Expression)一般叫做左值,是表示内存位置的表达式,有以下几类:

  • 本地变量
  • 静态变量
  • 解引用 (* express)
  • 数组索引 (expr[expr])
  • 字段引用 (expr.field)
  • 位置表达式组合

通过位置表达式可以对某个数据单元的内存进行读写。位置表达式可以用于赋值

# 2.3 值表达式

值表达式(Value Expression)一般叫做右值,值表达式引用了某个存储单元地址中的数据。它相当于数据,只能进行读操作。

从语义角度来说,位置表达式代表了持久性数据,值表达式代表了临时数据。位置表达式一般有持久的状态,值表达式要不是字面量,要不就是表达式求值过程中创建的临时值