好的,我们来系统地梳理一下 Rust 的这些核心基础概念。这对于初学者建立坚实的知识框架至关重要。
![图片[1]_Rust的基础数据类型、变量系统、类型转换以及实战应用_知途无界](https://zhituwujie.com/wp-content/uploads/2026/02/d2b5ca33bd20260201102558.png)
1. Rust 基础数据类型
Rust 是静态强类型语言,所有变量的类型必须在编译期确定。Rust 的数据类型主要分为两大类:标量类型 和 复合类型。
A. 标量类型
代表一个单独的值。
- 整数
- 有符号整数(正或负):
i8,i16,i32,i64,i128,isize(指针宽度) - 无符号整数(只能是正或零):
u8,u16,u32,u64,u128,usize(指针宽度) isize和usize的长度取决于程序运行的计算机架构(32位或64位)。- 整数字面量可以用
_作为分隔符,例如1_000_000。 - 默认类型是
i32。
- 有符号整数(正或负):
- 浮点数
f32:32位,单精度浮点数。f64:64位,双精度浮点数。默认类型。
- 布尔型
bool:只有两个值,true和false。
- 字符
char:用单引号'定义,代表一个 Unicode 标量值(如'a','中','🦀')。它占4个字节。
B. 复合类型
将多个值组合成一个类型。
- 元组
- 将不同类型的值组合在一起。
- 定义:
let tup: (i32, f64, u8) = (500, 6.4, 1); - 访问元素:
- 解构:
let (x, y, z) = tup; - 使用
.加索引:let five_hundred = tup.0;
- 解构:
- 数组
- 将相同类型的值存储在连续的内存块中。
- 定义:
let arr: [i32; 5] = [1, 2, 3, 4, 5]; - 初始化重复值:
let zeros = [0; 10];// 长度为10,全是0的数组。 - 访问元素:
arr[0]。越界访问会在运行时 panic!(这是 Rust 内存安全的重要体现)。
2. Rust 变量系统
Rust 的变量系统围绕着 所有权 展开,但其基础是可变性。
A. 声明与可变性
- 不可变变量:默认情况下,变量是不可变的。
let x = 5; // x = 6; // 错误:不能给不可变变量赋值 - 可变变量:使用
mut关键字使其可变。let mut y = 5; y = 6; // 正确 println!("The value of y is: {}", y); // 输出:6
B. 变量遮蔽
可以使用相同的变量名来“遮蔽”之前的变量,甚至可以改变其类型。
let z = 5;
let z = z + 1; // 遮蔽前一个z,现在z是6
{
let z = z * 2; // 在这个作用域内,z被遮蔽为12
println!("The value of z in the inner scope is: {}", z);
}
println!("The value of z is: {}", z); // 外部的z仍然是6
C. 常量
使用 const 关键字,并且必须注明值的类型。
const MAX_POINTS: u32 = 100_000;
常量在整个程序生命周期内有效,通常用于全局配置。
3. Rust 类型转换
Rust 不像其他语言(如 C/C++)那样支持隐式类型转换(“类型提升”)。必须使用显式转换。
A. 使用 as 关键字
这是最简单直接的转换方式,主要用于数值类型之间的转换。
let a = 10_i32;
let b = a as u32; // i32 -> u32
let c = 100_u8;
let d = c as i16; // u8 -> i16
let e = 3.14_f32;
let f = e as i32; // f32 -> i32,小数部分被截断 -> 3
注意:as 转换在某些边界情况下可能不会报错(例如将一个大的 u64 转换为 i8),而是产生溢出结果,使用时需小心。
B. 使用 From 和 Into Traits
这是更推荐的方式,因为它更安全、更灵活。From 和 Into 是标准库中定义的 trait。
From:定义在目标类型上。如果你为自己的类型实现了From<T>,那么就可以轻松地将T转换为你的类型。Into:定义在源类型上。调用者可以调用.into()来转换类型。通常,如果你实现了From,Rust 会自动为你提供Into的实现。
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
// 为 Number 实现 From<i32>
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let num = Number::from(30);
println!("num is {:?}", num);
let int = 5;
// 因为实现了 From<i32>,所以可以自动获得 Into<Number>
let num2: Number = int.into();
println!("num2 is {:?}", num2);
}
C. 使用 TryFrom 和 TryInto Traits
当转换可能失败时(例如,字符串转数字),应该使用 TryFrom/TryInto,它们返回一个 Result。
use std::convert::TryFrom;
fn main() {
let s = "100";
let num: i32 = match i32::try_from(s) {
Ok(n) => n,
Err(e) => {
eprintln!("Conversion failed: {}", e);
return;
}
};
println!("The number is: {}", num);
let invalid_s = "hello";
let result = i32::try_from(invalid_s);
assert!(result.is_err());
}
4. 实战应用:一个简单的命令行计算器
让我们结合以上知识,编写一个简单的计算器,它可以处理两个整数的加法和减法。
use std::io;
// 定义一个枚举来表示支持的运算
enum Operation {
Add,
Subtract,
}
fn main() {
println!("Simple Calculator");
println!("Enter an operation (add or subtract):");
let mut operation_input = String::new();
io::stdin()
.read_line(&mut operation_input)
.expect("Failed to read line");
let operation = if operation_input.trim() == "add" {
Operation::Add
} else if operation_input.trim() == "subtract" {
Operation::Subtract
} else {
println!("Unsupported operation.");
return;
};
println!("Enter first number:");
let num1 = get_number_from_input();
println!("Enter second number:");
let num2 = get_number_from_input();
// 使用 match 根据枚举进行分支处理
let result = match operation {
Operation::Add => add(num1, num2),
Operation::Subtract => subtract(num1, num2),
};
println!("Result: {}", result);
}
// 从用户输入中获取数字,演示类型转换 (String -> i32)
fn get_number_from_input() -> i32 {
loop {
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read line");
// 使用 try_into 进行可能失败的类型转换
match input.trim().parse::<i32>() {
Ok(num) => return num,
Err(_) => {
println!("Please enter a valid integer!");
continue;
}
};
}
}
// 函数演示了基本的运算和类型使用
fn add(a: i32, b: i32) -> i32 {
a + b // Rust 不需要 return 关键字,最后一个表达式就是返回值
}
fn subtract(a: i32, b: i32) -> i32 {
let diff = a - b;
diff // 也可以显式地写成一行,加上分号就变成语句,需要 return
}
代码解析:
- 数据类型:我们使用了
i32作为数字的默认类型,使用了String来处理用户输入。 - 变量系统:
operation_input,input,num1,num2都是可变变量 (mut),因为我们后续需要修改它们的内容(通过read_line)。 - 类型转换:
get_number_from_input函数中,input.trim().parse::<i32>()是关键。它将字符串切片 (&str) 解析 为i32。parse方法返回一个Result,我们使用match优雅地处理了成功和失败的情况,这是 Rust 惯用的错误处理方式。Operation枚举本身也是一种类型安全和表达力强的构造,避免了使用魔法数字或字符串来表示操作。
- 实战要点:
- 所有权:
String::new()创建的字符串拥有其数据,read_line获取用户输入后,数据就转移到了这个字符串中。 - 错误处理:使用
expect处理必然成功的操作(如read_line返回的Result我们这里假设不会出错),使用match处理可能失败的操作(如parse)。 - 模式匹配:
match是 Rust 中极其强大的工具,我们用它来处理枚举、处理Result和Option。
- 所有权:
通过这个小例子,你可以看到 Rust 的基础概念是如何协同工作,构建出安全、清晰且健壮的应用程序的。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
























暂无评论内容