1. 变量绑定与不可变性
核心概念
- 变量绑定 : Rust使用
let
关键字将值"绑定"到变量名上 - 默认不可变性: Rust变量默认不可变,这是Rust安全理念的基石
- 可变性声明 : 使用
mut
关键字显式声明变量可变
为什么默认不可变?
不可变性帮助避免许多常见的编程错误,特别是在并发环境中。这使得代码更安全、更易于推理,也是Rust"无畏并发"承诺的基础。
rust
// 不可变变量示例
let x = 5;
// x = 10; // 编译错误: 不能对不可变变量二次赋值
// 可变变量示例
let mut y = 10;
y = 20; // 正确 - y被声明为可变的
变量遮蔽(Shadowing)
与可变性不同,变量遮蔽允许重新使用相同的变量名,但实际上创建了新变量,可以改变类型。
rust
let z = 5; // 第一个z
let z = z + 1; // 创建新的z,值为6
let z = "hello"; // 再次遮蔽,现在z是字符串类型
2. 基本数据类型
标量类型
整数类型
- 有符号:
i8
,i16
,i32
,i64
,i128
,isize
(指针大小) - 无符号:
u8
,u16
,u32
,u64
,u128
,usize
(指针大小) - 默认类型:
i32
- 通常是最快的,即使在64位系统上
整数字面量
rust
let decimal = 98_222; // 下划线作为视觉分隔符
let hex = 0xff; // 十六进制
let octal = 0o77; // 八进制
let binary = 0b1111_0000;// 二进制
let byte = b'A'; // 字节(仅用于u8)
浮点类型
f32
: 单精度浮点f64
: 双精度浮点(默认)
布尔类型
bool
: 值为true
或false
- 占用1字节空间
字符类型
char
: 表示Unicode标量值- 4字节大小,可表示超出ASCII的值
- 使用单引号(与字符串的双引号不同)
3. 复合类型
元组(Tuple)
- 固定长度的不同类型值的组合
- 一旦声明,大小不可改变
- 通过解构或索引访问元素
rust
let tup: (i32, f64, &str) = (500, 6.4, "Rust");
// 解构获取值
let (x, y, z) = tup;
// 索引访问
let first = tup.0; // 500
数组(Array)
- 固定长度的相同类型元素集合
- 分配在栈上,而非堆上
- 当需要固定数量元素时比Vec更高效
rust
// 类型标注: [类型; 长度]
let arr: [i32; 5] = [1, 2, 3, 4, 5];
// 初始化包含相同值的数组
let zeros = [0; 10]; // 十个0组成的数组
// 访问元素
let first = arr[0];
数组越界检查
Rust在访问数组元素时总是执行边界检查,这与C/C++不同,可以防止缓冲区溢出漏洞。
4. 类型推导与标注
类型推导
Rust拥有强大的类型推导系统,常常不需要显式标注类型。
类型标注语法
rust
let x: i32 = 42;
let y: (i32, f64) = (10, 3.14);
5. 实践示例:温度转换程序
下面的例子结合了变量声明、数学运算和格式化输出:
rust
fn main() {
// 摄氏度转华氏度
let celsius = 25.0; // 浮点默认为f64
let fahrenheit = celsius * 9.0 / 5.0 + 32.0;
println!("{}°C = {}°F", celsius, fahrenheit);
// 使用变量遮蔽演示华氏度转摄氏度
let fahrenheit = 77.0; // 遮蔽之前的fahrenheit变量
let celsius = (fahrenheit - 32.0) * 5.0 / 9.0;
println!("{}°F = {}°C", fahrenheit, celsius);
}
这个例子演示了:
- 浮点数计算
- 变量遮蔽的实际应用
- 使用
println!
宏的格式化输出
6. 代码实现
我们在项目中实现了一个完整的示例,展示了所有这些概念:
rust
// src/week1/day1.rs
pub fn run() {
println!("=== Rust基础学习 - 第1天:语法与变量 ===\n");
// 变量绑定与不可变性示例
println!("--- 变量绑定与不可变性 ---");
let x = 5;
println!("x的值是: {}", x);
let mut y = 10;
println!("y初始值: {}", y);
y = 20;
println!("y修改后: {}", y);
// 变量遮蔽
let z = 5;
let z = z + 1;
let z = z * 2;
println!("z经过两次遮蔽后的值: {}", z);
// 变量遮蔽允许改变类型
let spaces = " ";
let spaces = spaces.len();
println!("空格数量: {}", spaces);
// 基本数据类型示例
println!("\n--- 基本数据类型 ---");
let a: i32 = 42;
let b: u64 = 100;
let c = 256;
println!("整数: a={}, b={}, c={}", a, b, c);
// 复合类型示例
println!("\n--- 复合类型 ---");
let tup: (i32, f64, &str) = (500, 6.4, "Rust");
let (x, y, z) = tup;
println!("解构元组: x={}, y={}, z={}", x, y, z);
// 温度转换示例
println!("\n--- 温度转换示例 ---");
let celsius = 25.0;
let fahrenheit = celsius * 9.0 / 5.0 + 32.0;
println!("{}°C = {}°F", celsius, fahrenheit);
}
7. 运行结果

8. 学习要点总结
- Rust通过默认不可变性提供安全保障
- 使用
mut
显式标记可变变量 - 变量遮蔽与可变性是不同的概念
- Rust提供丰富的数值类型,包括不同大小的整数和浮点数
- 复合类型(元组和数组)有固定长度且不可增长
- Rust始终执行边界检查以防止内存安全问题
9. 思考与练习
- 尝试编写一个程序,将英寸转换为厘米(1英寸 = 2.54厘米)
- 创建一个程序,使用不同的数据类型并尝试进行类型转换
- 探索变量遮蔽的更多用例,比如处理字符串操作
1. 英寸转厘米程序
rust
fn inch_to_cm() {
println!("--- 英寸转厘米程序 ---");
let inches = 10.0;
let cm = inches * 2.54;
println!("{} 英寸 = {} 厘米", inches, cm);
// 读取用户输入的方式(需导入标准库)
/*
use std::io;
println!("请输入英寸值:");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("读取输入失败");
// 将输入字符串转换为浮点数
let inches: f64 = input.trim().parse()
.expect("请输入有效的数字");
let cm = inches * 2.54;
println!("{} 英寸 = {} 厘米", inches, cm);
*/
}

知识点:
- 浮点数计算
- 格式化输出
- 注释展示如何扩展为接受用户输入的交互式程序
- 错误处理的简单示例(使用expect)
2. 数据类型转换程序
rust
fn type_conversion() {
println!("--- 数据类型转换示例 ---");
// 整数类型间转换
let a: i32 = 42;
let b: i64 = a as i64; // 使用as关键字进行显式转换
let c: u8 = a as u8;
println!("i32 值 {} 转换为: i64={}, u8={}", a, b, c);
// 浮点数与整数间转换
let float_num: f64 = 3.99;
let int_num: i32 = float_num as i32; // 截断小数部分,不是四舍五入
println!("浮点数 {} 转换为整数: {}", float_num, int_num);
// 使用内置方法进行四舍五入等操作
let rounded = float_num.round() as i32;
let ceiling = float_num.ceil() as i32;
let floor = float_num.floor() as i32;
println!("浮点数 {} 的处理: 四舍五入={}, 向上取整={}, 向下取整={}",
float_num, rounded, ceiling, floor);
// 字符与整数间转换
let character = 'A';
let ascii_value = character as u8;
println!("字符 '{}' 的ASCII值: {}", character, ascii_value);
// 整数转换为字符
let num_value: u8 = 66;
let char_from_num = num_value as char;
println!("整数 {} 转换为字符: '{}'", num_value, char_from_num);
// 字符串与数字转换
let num_str = "42";
let parsed_num: i32 = num_str.parse().expect("解析失败");
println!("字符串 \"{}\" 解析为数字: {}", num_str, parsed_num);
// 数字转字符串
let num = 100;
let num_as_string = num.to_string();
println!("数字 {} 转换为字符串: \"{}\"", num, num_as_string);
}

知识点:
as
关键字用于基本类型转换- 截断转换的行为(浮点到整数)
- 浮点数的取整方法
- 字符与ASCII值的转换
- 字符串解析(parse方法)
- 使用to_string()将值转换为字符串
3. 变量遮蔽的字符串操作用例
rust
fn string_shadowing() {
println!("--- 变量遮蔽在字符串处理中的应用 ---");
// 案例1: 空格修剪
let input = " hello world ";
println!("原始字符串: '{}'", input);
let input = input.trim(); // 遮蔽并去除前后空格
println!("修剪后: '{}'", input);
// 案例2: 大小写转换
let input = input.to_uppercase(); // 再次遮蔽并转为大写
println!("转换为大写: '{}'", input);
let input = input.to_lowercase(); // 再次遮蔽并转为小写
println!("转换为小写: '{}'", input);
// 案例3: 替换操作
let input = input.replace("hello", "你好"); // 遮蔽并替换文本
println!("替换后: '{}'", input);
// 案例4: 字符串解析为数字,保持变量名不变
let data = "42";
println!("字符串数据: '{}'", data);
let data: i32 = data.parse().expect("无法解析为整数"); // 遮蔽并改变类型
println!("解析为整数: {}", data);
let data = data * 2; // 数学运算后再次遮蔽
println!("乘以2: {}", data);
// 案例5: 构建格式化字符串
let name = "Rust";
let year = 2010;
// 使用遮蔽构建复杂字符串
let info = format!("语言名称: {}", name);
let info = format!("{}, 发布年份: {}", info, year);
let info = format!("{}, 年龄: {} 年", info, 2023 - year);
println!("信息: {}", info);
}

知识点:
- 字符串处理方法的链式操作
- 变量遮蔽消除了创建多个临时变量的需要
- 字符串与数值类型间的转换
- 变量遮蔽允许类型转换,保持相同的变量名
- 格式化字符串的逐步构建