Rust 基础语法
本章将介绍 Rust 的基础语法,包括变量、数据类型和函数。
变量和可变性
变量声明
在 Rust 中,使用 let 关键字声明变量:
fn main() {
// 声明变量(默认不可变)
let x = 5;
println!("x 的值是: {}", x);
// 重新绑定变量(变量遮蔽)
let x = x + 1;
println!("x 的值是: {}", x);
// 可以改变类型
let x = "现在 x 是字符串";
println!("{}", x);
}
解释:
- Rust 变量默认是不可变的(immutable)
- 变量遮蔽(shadowing)允许用同一个名字声明新变量
- 遮蔽时可以改变类型
可变变量
使用 mut 关键字声明可变变量:
fn main() {
let mut x = 5;
println!("x 的值是: {}", x);
x = 6; // 修改值
println!("x 的值是: {}", x);
// x = "string"; // 错误!不能改变类型
}
常量
使用 const 声明常量:
// 常量必须注明类型,且必须在编译时就能确定值
const MAX_POINTS: u32 = 100_000;
fn main() {
println!("最大分数: {}", MAX_POINTS);
}
常量与变量的区别:
| 特性 | 常量 (const) | 不可变变量 (let) |
|---|---|---|
| 可变性 | 永远不可变 | 可以遮蔽 |
| 类型注解 | 必须 | 可推断 |
| 作用域 | 可以是全局 | 块级作用域 |
| 值的来源 | 编译时确定 | 运行时确定 |
变量遮蔽 vs 可变变量
fn main() {
// 使用 mut
let mut spaces = " ";
// spaces = spaces.len(); // 错误!不能改变类型
// 使用遮蔽
let spaces = " ";
let spaces = spaces.len(); // 正确!可以改变类型
println!("空格数量: {}", spaces);
}
数据类型
Rust 是静态类型语言,编译时必须知道所有变量的类型。
标量类型
整数类型
| 长度 | 有符号 | 无符号 |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
fn main() {
// 十进制
let decimal = 98_222;
// 十六进制
let hex = 0xff;
// 八进制
let octal = 0o77;
// 二进制
let binary = 0b1111_0000;
// 字节(仅限 u8)
let byte = b'A';
println!("十进制: {}, 十六进制: {}, 八进制: {}, 二进制: {}, 字节: {}",
decimal, hex, octal, binary, byte);
}
解释:
isize和usize的大小取决于计算机架构(64位系统上是64位)- 使用
_作为分隔符提高可读性 - 整数溢出在 debug 模式会导致 panic,在 release 模式会回绕
浮点类型
fn main() {
let x = 2.0; // f64(默认)
let y: f32 = 3.0; // f32
// 浮点数运算
let sum = x + 2.5;
let product = x * 3.0;
println!("和: {}, 积: {}", sum, product);
}
布尔类型
fn main() {
let t = true;
let f: bool = false;
// 布尔值主要用于条件判断
if t {
println!("t 是 true");
}
}
字符类型
fn main() {
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
let chinese = '中';
// char 是 4 字节,代表一个 Unicode 标量值
println!("字符: {} {} {} {}", c, z, heart_eyed_cat, chinese);
}
复合类型
元组
fn main() {
// 创建元组
let tup: (i32, f64, u8) = (500, 6.4, 1);
// 解构
let (x, y, z) = tup;
println!("x: {}, y: {}, z: {}", x, y, z);
// 索引访问
let five_hundred = tup.0;
let six_point_four = tup.1;
let one = tup.2;
println!("值: {}, {}, {}", five_hundred, six_point_four, one);
// 单元素元组需要逗号
let single = (5,);
// 空元组(单元类型)
let unit = ();
}
数组
fn main() {
// 创建数组
let a = [1, 2, 3, 4, 5];
// 指定类型和长度
let b: [i32; 5] = [1, 2, 3, 4, 5];
// 重复元素初始化
let c = [3; 5]; // 等同于 [3, 3, 3, 3, 3]
// 访问元素
let first = a[0];
let second = a[1];
println!("第一个: {}, 第二个: {}", first, second);
// 越界访问会导致 panic
// let invalid = a[10]; // 运行时错误
// 数组是固定大小的
println!("数组长度: {}", a.len());
// 数组是栈分配的
println!("数组占用空间: {} 字节", std::mem::size_of_val(&a));
}
解释:
- 数组大小固定,在栈上分配
- 越界访问会在运行时导致 panic
- 使用
std::mem::size_of_val可以查看大小
函数
函数定义
fn main() {
println!("Hello, world!");
another_function();
print_labeled_measurement(5, 'h');
}
// 无参数函数
fn another_function() {
println!("另一个函数");
}
// 带参数函数
fn print_labeled_measurement(value: i32, unit_label: char) {
println!("测量值: {}{}", value, unit_label);
}
语句和表达式
Rust 是基于表达式的语言,区分语句和表达式:
fn main() {
// 语句:执行操作但不返回值
let x = 5; // 这是一个语句
// 表达式:计算并返回值
// 代码块是表达式
let y = {
let x = 3;
x + 1 // 表达式,没有分号!
};
println!("y 的值是: {}", y); // y = 4
// 表达式可以返回值
let sum = add(5, 10);
println!("和: {}", sum);
}
fn add(a: i32, b: i32) -> i32 {
a + b // 返回值,没有分号!
// 等同于 return a + b;
}
解释:
- 语句执行操作但不返回值,以分号结尾
- 表达式计算并返回值,不以分号结尾
- 代码块
{}是表达式 - 函数返回值可以用
return或直接写表达式
返回值
fn main() {
let x = plus_five(5);
println!("x = {}", x);
// 提前返回
let result = check_number(-1);
println!("结果: {}", result);
}
// 返回 i32 类型
fn plus_five(x: i32) -> i32 {
x + 5 // 隐式返回
}
// 使用 return 提前返回
fn check_number(x: i32) -> &'static str {
if x < 0 {
return "负数"; // 提前返回
}
"正数或零" // 隐式返回
}
// 返回单元类型 ()
fn do_nothing() {
// 没有返回值,相当于返回 ()
}
注释
fn main() {
// 单行注释
/*
多行注释
可以跨越多行
*/
/// 文档注释(支持 Markdown)
/// 用于生成文档
///
/// # Examples
/// ```
/// let x = add(1, 2);
/// ```
fn add(a: i32, b: i32) -> i32 {
a + b
}
// 代码中也可以有注释
let x = 5; // 行尾注释
}
控制流
if 表达式
fn main() {
let number = 6;
// 基本用法
if number % 4 == 0 {
println!("number 能被 4 整除");
} else if number % 3 == 0 {
println!("number 能被 3 整除");
} else {
println!("number 不能被 4 或 3 整除");
}
// if 是表达式,可以用在 let 语句中
let condition = true;
let number = if condition { 5 } else { 6 };
println!("number 的值是: {}", number);
// 分支必须返回相同类型
// let number = if condition { 5 } else { "six" }; // 错误!
}
循环
loop 循环
fn main() {
let mut count = 0;
// 无限循环
let result = loop {
count += 1;
if count == 10 {
break count * 2; // break 可以返回值
}
};
println!("结果: {}", result);
// 循环标签
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;
}
}
while 循环
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("发射!");
// 遍历数组
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("值: {}", a[index]);
index += 1;
}
}
for 循环
fn main() {
// 遍历数组(推荐方式)
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("值: {}", element);
}
// Range
for number in (1..4).rev() {
println!("{}!", number);
}
println!("发射!");
// 遍历索引
for i in 0..a.len() {
println!("索引 {}: {}", i, a[i]);
}
}
match 表达式
fn main() {
let number = 13;
// 基本匹配
match number {
1 => println!("一"),
2 | 3 | 5 | 7 | 11 => println!("这是质数"),
13..=19 => println!("十几岁"),
_ => println!("其他数字"), // 默认分支
}
// match 是表达式
let boolean = true;
let binary = match boolean {
false => 0,
true => 1,
};
println!("{} => {}", boolean, binary);
// 匹配元组
let pair = (2, -2);
match pair {
(0, y) => println!("x 是零,y 是 {}", y),
(x, 0) => println!("x 是 {},y 是零", x),
_ => println!("其他情况"),
}
}
if let 语法
fn main() {
let some_value = Some(3);
// 使用 match
match some_value {
Some(3) => println!("三"),
_ => (),
}
// 使用 if let(更简洁)
if let Some(3) = some_value {
println!("三");
}
// 可以加 else
if let Some(x) = some_value {
println!("值是 {}", x);
} else {
println!("没有值");
}
}
while let 语法
fn main() {
let mut optional = Some(0);
// 当匹配成功时继续循环
while let Some(i) = optional {
if i > 5 {
println!("大于 5,退出");
optional = None;
} else {
println!("i 是 {}", i);
optional = Some(i + 1);
}
}
}
小结
本章我们学习了:
- 变量:
let、mut、常量、变量遮蔽 - 数据类型:整数、浮点数、布尔、字符、元组、数组
- 函数:定义、参数、返回值、表达式
- 控制流:
if、loop、while、for、match、if let
练习
- 声明一个可变变量并修改它的值
- 创建一个包含不同类型元素的元组并解构
- 编写一个函数,计算两个数的最大公约数
- 使用 for 循环打印斐波那契数列的前 10 个数
- 使用 match 表达式实现一个简单的计算器