01. Rust 的安装和 Hello World
用 rustup 安装 Rust 是最标准的方式,它会装好编译器 rustc、包管理器 cargo、和工具链。cargo new 创建项目,cargo build 编译,cargo run 编译加运行。Rust 编译出来的二进制非常小而且没有运行时依赖,因为静态链接了所有东西。
rust
// 安装 Rust
// curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
// 创建项目
// cargo new hello_world
// cd hello_world
// cargo run
fn main() {
println!("你好,世界!");
}println! 是宏不是函数,感叹号是宏调用的标志。
02. 变量、不可变和所有权初探
Rust 最大的特色就是所有权系统。变量默认不可变,想可变要加 mut。所有权规则三句话:每个值有且只有一个所有者;值在任一时刻只能有一个可变引用或多个不可变引用;引用不能比它引用的值活得久。这套规则让 Rust 不需要垃圾回收也能保证内存安全。
rust
fn main() {
// 不可变
let x = 5;
// x = 6; // 编译错误
// 可变
let mut y = 10;
y = 20;
// 变量遮蔽(shadowing)
let z = 5;
let z = z + 1; // 新变量,可以改类型
// 所有权转移
let s1 = String::from("hello");
let s2 = s1; // s1 所有权转移到 s2,s1 不能用了
// println!("{}", s1); // 编译错误
}变量遮蔽(shadowing)和 mut 不同,shadowing 是新变量可以换类型。mut 是原变量改值不能换类型。
03. 基本数据类型
Rust 是强静态类型语言,基本类型有:整数(i8/u8 到 i128/u128,默认 i32)、浮点数(f32/f64)、布尔、字符(Unicode 4字节)。还有复合类型:元组(不同类型组合)、数组(同类型固定长度,存在栈上)。字符串有两种:&str 是借用字面量,String 是堆上可变字符串。
rust
fn main() {
let a: i32 = 42;
let b: f64 = 3.14;
let c: bool = true;
let d: char = '中'; // 注意 char 用单引号
// 元组
let tup: (i32, f64, char) = (500, 6.4, 'A');
let (x, y, z) = tup; // 解构
let first = tup.0; // 点索引
// 数组
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
// 字符串
let s: &str = "hello"; // 字面量,不可变引用
let mut owned = String::from("hello"); // 可变堆字符串
owned.push_str(" world");
}数组长度是类型的一部分,[i32; 5] 和 [i32; 3] 是不同的类型。
04. 函数和控制流
Rust 函数用 fn 声明,参数和返回值都要标注类型。最后一行不加分号就是返回值(表达式返回)。if 是表达式可以直接赋值给变量。loop 无限循环,while 条件循环,for 遍历集合。match 是超级加强版的 switch,穷尽所有可能,配合枚举威力无穷。
rust
fn add(x: i32, y: i32) -> i32 {
x + y // 不加分号,返回值
}
fn main() {
// if 是表达式
let num = if true { 5 } else { 6 };
// match 匹配
let x = 3;
match x {
1 => println!("一"),
2 | 3 => println!("二三"),
_ => println!("其他"), // _ 是通配符
}
// for 遍历
let arr = [10, 20, 30];
for elem in arr {
println!("{}", elem);
}
for i in 0..5 { // 0 到 4,不含 5
println!("{}", i);
}
}match 要求覆盖所有可能,编译器会检查是否有遗漏的分支,这是防止 bug 的利器。
05. 常用宏:println、vec、panic
Rust 的宏功能非常强大,在编译时展开成代码。println! 格式化输出,format! 格式化字符串返回,vec! 快速创建动态数组 Vec。panic! 触发不可恢复错误,程序崩溃。dbg! 打印变量值和位置,调试神器。宏的名称后面都带感叹号,很容易和函数区分。
rust
fn main() {
// 打印
let name = "小明";
println!("你好, {}!", name);
println!("{name} 今年 {age} 岁", name = "小明", age = 18);
// 格式化字符串
let s = format!("用户: {name}");
// 创建 Vec
let v = vec![1, 2, 3, 4, 5];
let zeros = vec![0; 10]; // 10个0
// 调试打印
let x = 42;
let y = dbg!(x * 2); // 输出: [src/main.rs:行号] x * 2 = 84
// panic
// panic!("出错了!");
// 断言
assert_eq!(2 + 2, 4);
}dbg! 宏会打印文件名、行号和表达式值,最后返回值的所有权,调试时比 println 方便太多。
知识测验
第 1/4 题正确 0
Rust 中变量默认是什么特性?
下一节
下一节 所有权系统