Rust 快速上手
概述
本章通过实际的代码示例,让你快速了解 Rust 的基本语法和核心概念。我们将从 Hello World 开始,逐步构建更复杂的程序。
🚀 Hello World
第一个程序
rust
// src/main.rs
fn main() {
println!("Hello, World!");
println!("你好,Rust!");
// 格式化输出
let name = "Rust";
let year = 2023;
println!("欢迎来到 {} 世界!现在是 {} 年。", name, year);
}bash
# 运行程序
cargo run
# 输出:
# Hello, World!
# 你好,Rust!
# 欢迎来到 Rust 世界!现在是 2023 年。变量和常量
rust
fn main() {
// 不可变变量(默认)
let x = 5;
println!("x 的值是: {}", x);
// x = 6; // 编译错误!不可变变量不能重新赋值
// 可变变量
let mut y = 5;
println!("y 的值是: {}", y);
y = 6; // 可以修改
println!("现在 y 的值是: {}", y);
// 变量遮蔽(shadowing)
let x = x + 1; // 创建新变量,遮蔽之前的 x
println!("遮蔽后 x 的值是: {}", x);
// 常量
const MAX_POINTS: u32 = 100_000;
println!("最大分数: {}", MAX_POINTS);
}📊 基本数据类型
数值类型
rust
fn number_types() {
// 整数类型
let small: i8 = -128;
let big: i64 = 1_000_000;
let unsigned: u32 = 42;
// 浮点类型
let pi: f64 = 3.14159;
let e: f32 = 2.71828;
// 类型推断
let guess = 42; // 默认 i32
let float_guess = 3.14; // 默认 f64
println!("整数: {}, {}, {}", small, big, unsigned);
println!("浮点: {}, {}", pi, e);
println!("推断: {}, {}", guess, float_guess);
}布尔和字符类型
rust
fn bool_and_char() {
// 布尔类型
let is_rust_awesome = true;
let is_difficult: bool = false;
// 字符类型(Unicode)
let letter = 'A';
let emoji = '😀';
let chinese = '中';
println!("布尔值: {}, {}", is_rust_awesome, is_difficult);
println!("字符: {}, {}, {}", letter, emoji, chinese);
}复合类型
rust
fn compound_types() {
// 元组
let tuple: (i32, f64, char) = (42, 3.14, 'R');
let (x, y, z) = tuple; // 解构
println!("元组: {}, {}, {}", x, y, z);
println!("访问元组: {}", tuple.0);
// 数组
let array = [1, 2, 3, 4, 5];
let months = ["一月", "二月", "三月"];
let zeros = [0; 5]; // [0, 0, 0, 0, 0]
println!("数组: {:?}", array);
println!("第一个月: {}", months[0]);
println!("全零数组: {:?}", zeros);
}🔧 函数基础
函数定义和调用
rust
fn main() {
println!("主函数开始");
// 调用函数
greet();
let result = add(5, 3);
println!("5 + 3 = {}", result);
// 带返回值的函数
let (sum, product) = calculate(4, 6);
println!("4 + 6 = {}, 4 * 6 = {}", sum, product);
}
// 无参数无返回值
fn greet() {
println!("你好,来自函数的问候!");
}
// 有参数有返回值
fn add(a: i32, b: i32) -> i32 {
a + b // 表达式,没有分号
}
// 多个返回值(使用元组)
fn calculate(x: i32, y: i32) -> (i32, i32) {
(x + y, x * y)
}
// 带语句的函数
fn verbose_add(a: i32, b: i32) -> i32 {
println!("计算 {} + {}", a, b);
let result = a + b; // 语句
result // 表达式
}🎛️ 控制流
条件语句
rust
fn conditionals() {
let number = 6;
// if 表达式
if number % 4 == 0 {
println!("{} 能被 4 整除", number);
} else if number % 3 == 0 {
println!("{} 能被 3 整除", number);
} else if number % 2 == 0 {
println!("{} 能被 2 整除", number);
} else {
println!("{} 不能被 2、3、4 整除", number);
}
// if 表达式赋值
let condition = true;
let result = if condition { 5 } else { 6 };
println!("结果是: {}", result);
// 复杂条件
let age = 18;
let has_license = true;
if age >= 18 && has_license {
println!("可以开车");
} else {
println!("不能开车");
}
}循环
rust
fn loops() {
// loop 无限循环
let mut counter = 0;
loop {
counter += 1;
if counter == 3 {
println!("跳过 3");
continue;
}
if counter == 6 {
println!("结束循环");
break;
}
println!("计数器: {}", counter);
}
// while 条件循环
let mut number = 3;
while number != 0 {
println!("倒计时: {}", number);
number -= 1;
}
println!("发射!");
// for 迭代循环
let array = [10, 20, 30, 40, 50];
for element in array.iter() {
println!("值是: {}", element);
}
// 范围循环
for number in 1..4 {
println!("数字: {}", number);
}
// 带索引的循环
for (index, value) in array.iter().enumerate() {
println!("索引 {} 的值是 {}", index, value);
}
}📦 所有权入门
基本所有权
rust
fn ownership_basics() {
// 所有权转移
let s1 = String::from("hello");
let s2 = s1; // s1 的所有权转移给 s2
// println!("{}", s1); // 编译错误!s1 已失效
println!("{}", s2); // 正常
// 克隆
let s3 = String::from("world");
let s4 = s3.clone(); // 深拷贝
println!("s3: {}, s4: {}", s3, s4); // 都有效
// 基本类型的复制
let x = 5;
let y = x; // Copy trait,两个都有效
println!("x: {}, y: {}", x, y);
}
fn ownership_functions() {
let s = String::from("hello");
takes_ownership(s); // s 的值移动到函数里
// println!("{}", s); // 编译错误!s 已失效
let x = 5;
makes_copy(x); // i32 是 Copy 的,所以 x 仍然有效
println!("{}", x); // 正常
let s1 = gives_ownership(); // 函数返回值移动给 s1
println!("{}", s1);
let s2 = String::from("world");
let s3 = takes_and_gives_back(s2); // s2 移动到函数,返回值移动给 s3
println!("{}", s3);
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
} // some_string 离开作用域并被丢弃
fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
} // some_integer 离开作用域,没有特殊操作
fn gives_ownership() -> String {
let some_string = String::from("hello");
some_string // 返回,所有权移动到调用函数
}
fn takes_and_gives_back(a_string: String) -> String {
a_string // 返回,所有权移动到调用函数
}引用和借用
rust
fn references_and_borrowing() {
let s1 = String::from("hello");
// 不可变引用
let len = calculate_length(&s1);
println!("'{}' 的长度是 {}", s1, len); // s1 仍然有效
// 可变引用
let mut s2 = String::from("hello");
change(&mut s2);
println!("修改后: {}", s2);
// 多个不可变引用
let r1 = &s1;
let r2 = &s1;
println!("{} 和 {}", r1, r2); // 正常
// 可变引用的限制
let mut s3 = String::from("hello");
let r3 = &mut s3;
// let r4 = &mut s3; // 编译错误!同时只能有一个可变引用
println!("{}", r3);
}
fn calculate_length(s: &String) -> usize {
s.len()
} // s 离开作用域,但因为它不拥有引用值的所有权,所以什么都不会发生
fn change(some_string: &mut String) {
some_string.push_str(", world");
}🏗️ 结构体入门
定义和使用结构体
rust
// 定义结构体
#[derive(Debug)] // 允许使用 {:?} 格式化打印
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
// 元组结构体
#[derive(Debug)]
struct Point(i32, i32, i32);
fn struct_examples() {
// 创建结构体实例
let user1 = User {
email: String::from("user@example.com"),
username: String::from("someuser"),
active: true,
sign_in_count: 1,
};
println!("用户: {:?}", user1);
println!("用户名: {}", user1.username);
// 可变结构体
let mut user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername"),
active: true,
sign_in_count: 1,
};
user2.email = String::from("newemail@example.com");
println!("更新后的邮箱: {}", user2.email);
// 结构体更新语法
let user3 = User {
email: String::from("third@example.com"),
username: String::from("thirduser"),
..user1 // 其余字段与 user1 相同
};
println!("用户3: {:?}", user3);
// 元组结构体
let point = Point(1, 2, 3);
println!("点: {:?}", point);
println!("x 坐标: {}", point.0);
}
// 关联函数和方法
impl User {
// 关联函数(类似静态方法)
fn new(email: String, username: String) -> User {
User {
email,
username,
active: true,
sign_in_count: 1,
}
}
// 方法
fn is_active(&self) -> bool {
self.active
}
fn deactivate(&mut self) {
self.active = false;
}
fn activate(&mut self) {
self.active = true;
self.sign_in_count += 1;
}
}
fn struct_methods() {
// 使用关联函数
let mut user = User::new(
String::from("test@example.com"),
String::from("testuser")
);
println!("用户活跃状态: {}", user.is_active());
user.deactivate();
println!("停用后状态: {}", user.is_active());
user.activate();
println!("激活后状态: {}, 登录次数: {}", user.is_active(), user.sign_in_count);
}🎯 枚举和匹配
枚举定义
rust
#[derive(Debug)]
enum IpAddrKind {
V4,
V6,
}
#[derive(Debug)]
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
#[derive(Debug)]
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn enum_examples() {
// 基本枚举
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
println!("IP 版本: {:?}, {:?}", four, six);
// 带数据的枚举
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
println!("IP 地址: {:?}, {:?}", home, loopback);
// 复杂枚举
let messages = vec![
Message::Quit,
Message::Move { x: 10, y: 20 },
Message::Write(String::from("Hello")),
Message::ChangeColor(255, 0, 0),
];
for msg in messages {
process_message(msg);
}
}
fn process_message(msg: Message) {
match msg {
Message::Quit => println!("退出程序"),
Message::Move { x, y } => println!("移动到坐标 ({}, {})", x, y),
Message::Write(text) => println!("写入文本: {}", text),
Message::ChangeColor(r, g, b) => println!("改变颜色为 RGB({}, {}, {})", r, g, b),
}
}Option 和 Result
rust
fn option_examples() {
// Option 枚举
let some_number = Some(5);
let some_string = Some("字符串");
let absent_number: Option<i32> = None;
println!("有值: {:?}, {:?}", some_number, some_string);
println!("无值: {:?}", absent_number);
// 处理 Option
match some_number {
Some(value) => println!("找到值: {}", value),
None => println!("没有值"),
}
// if let 简化匹配
if let Some(value) = some_number {
println!("if let 找到值: {}", value);
}
// unwrap_or 提供默认值
let default_value = absent_number.unwrap_or(0);
println!("默认值: {}", default_value);
}
fn result_examples() {
// Result 用于错误处理
let good_result: Result<i32, &str> = Ok(10);
let bad_result: Result<i32, &str> = Err("出错了");
match good_result {
Ok(value) => println!("成功: {}", value),
Err(error) => println!("错误: {}", error),
}
match bad_result {
Ok(value) => println!("成功: {}", value),
Err(error) => println!("错误: {}", error),
}
// 链式操作
let result = divide(10, 2)
.and_then(|x| divide(x, 2))
.and_then(|x| divide(x, 0)); // 这里会出错
match result {
Ok(value) => println!("最终结果: {}", value),
Err(error) => println!("计算错误: {}", error),
}
}
fn divide(dividend: i32, divisor: i32) -> Result<i32, String> {
if divisor == 0 {
Err("不能除以零".to_string())
} else {
Ok(dividend / divisor)
}
}🎬 完整示例:猜数字游戏
rust
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn guessing_game() {
println!("猜数字游戏!");
let secret_number = rand::thread_rng().gen_range(1..101);
loop {
println!("请输入你的猜测(1-100):");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("读取输入失败");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => {
println!("请输入有效数字!");
continue;
}
};
println!("你猜的数字是: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("太小了!"),
Ordering::Greater => println!("太大了!"),
Ordering::Equal => {
println!("恭喜你,猜对了!");
break;
}
}
}
}
fn main() {
// 运行所有示例
println!("=== 数据类型示例 ===");
number_types();
bool_and_char();
compound_types();
println!("\n=== 条件和循环示例 ===");
conditionals();
loops();
println!("\n=== 所有权示例 ===");
ownership_basics();
ownership_functions();
references_and_borrowing();
println!("\n=== 结构体示例 ===");
struct_examples();
struct_methods();
println!("\n=== 枚举示例 ===");
enum_examples();
option_examples();
result_examples();
println!("\n=== 猜数字游戏 ===");
guessing_game();
}📝 本章小结
通过本章学习,你应该掌握了:
Rust 基础
- ✅ 变量、常量和基本数据类型
- ✅ 函数定义和调用
- ✅ 控制流(条件语句和循环)
- ✅ 所有权、借用和引用的基本概念
核心特性
- ✅ 结构体的定义和使用
- ✅ 枚举和模式匹配
- ✅ Option 和 Result 类型
- ✅ 错误处理基础
实践经验
- ✅ 完整的项目示例
- ✅ 常见编程模式
- ✅ Rust 特有的编程思维
继续学习:下一章 - Rust 基础语法