# 三.语句
前言
一个语句只是执行某个动作,但是不返还任何值
语句由关键字
和标识符
及操作符
组成的表达式组成,通过不同的关键字
可以分为几类
# 1.声明语句
用于声明各种语言项,包括声明变量,常量,结构体,函数等,以及通过 extern 和 use 关键字引入包和模块等
# 1.1 变量
# 1.1.1 声明
关键字let
用于声明变量
,声明变量的同时会确定其作用域
# 1.1.1.1 初次声明
- 1.只声明,后面可以再赋值(类型会推导,所以不用指明)
let a;
a=1;
1
2
2
- 2.声明赋值同时进行(类型会推导,所以不用指明)
let a:i32 = 1;
1
# 1.1.1.2 重新声明
即重影就是重新绑定的意思,重影与可变变量的赋值不是一个概念,重影是指用同一个名字重新代表另一个变量实体,其类型、可变属性和值都可以变化。但可变变量赋值仅能发生值的变化
let a = 1
let a = 1
1
2
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
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
2
3
4
# 1.3 模块
# 1.2.1 声明
- 关键字
mod
用于声明模块
mod outer {
pub fn public_function() -> i32 {
5
}
}
1
2
3
4
5
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
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
3
4
- 用法 2:
if else
let num = 3;
if num >10{
println!("条件为true")
}else {
println!("条件为false")
}
1
2
3
4
5
6
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
2
表达式主要用于计算求值
Rust 编译器在解析代码时:
- 如果遇到分号,就会继续往后面执行
- 如果遇到语句,就会执行语句
- 如果遇到表达式,就会对表达式求值
- 如果分号后面什么都没有,就会补上单元值()
- 当遇到函数时,就会将函数体的花括号识别为块表达式
# 2.1 块表达式
块表达式是由一对花括号和一系列表达式组成的,它总是返回块中最后一个表达式的值
var a = 1;
a = a + 10;
1
2
2
# 2.2 位置表达式
位置表达式(Place Expression)一般叫做左值,是表示内存位置的表达式,有以下几类:
- 本地变量
- 静态变量
- 解引用 (* express)
- 数组索引 (expr[expr])
- 字段引用 (expr.field)
- 位置表达式组合
通过位置表达式可以对某个数据单元的内存进行读写。位置表达式可以用于赋值
# 2.3 值表达式
值表达式(Value Expression)一般叫做右值,值表达式引用了某个存储单元地址中的数据。它相当于数据,只能进行读操作。
从语义角度来说,位置表达式代表了持久性数据,值表达式代表了临时数据。位置表达式一般有持久的状态,值表达式要不是字面量,要不就是表达式求值过程中创建的临时值