Rust 教程
什么是 Rust?
Rust 是一门系统编程语言,由 Mozilla 研究院开发,专注于安全、速度和并发。它的设计思想是:在保证内存安全的同时,不牺牲性能。
Rust 的特点:
- 零成本抽象
- 移动语义
- 保证内存安全
- 线程无数据竞争
- 基于 trait 的泛型
- 模式匹配
- 类型推断
- 最小运行时
- 高效 C 绑定
// 第一个 Rust 程序
fn main() {
println!("Hello, World!");
}
Rust 环境搭建
安装 Rust
Windows 安装:
- 下载 rustup-init.exe
- 运行安装程序,按默认选项安装
- 重启命令行工具
Linux/macOS 安装:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
验证安装
rustc --version
cargo --version
开发工具配置
推荐使用 VS Code:
- 安装 VS Code
- 安装 rust-analyzer 扩展
- 安装 CodeLLDB 扩展(用于调试)
Cargo 教程
Cargo 是什么?
Cargo 是 Rust 的构建系统和包管理器,用于管理 Rust 项目。
创建新项目
cargo new hello_world
cd hello_world
项目结构:
hello_world/
├── Cargo.toml
└── src/
└── main.rs
Cargo.toml 文件
[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"
[dependencies]
# 在这里添加依赖
常用 Cargo 命令
cargo build # 编译项目
cargo run # 编译并运行
cargo check # 检查代码但不编译
cargo test # 运行测试
cargo doc # 生成文档
cargo fmt # 格式化代码
cargo clippy # 代码检查
Rust 输出到命令行
使用 println! 宏
fn main() {
// 基本输出
println!("Hello, World!");
// 格式化输出
let name = "Alice";
let age = 25;
println!("姓名: {}, 年龄: {}", name, age);
// 位置参数
println!("{0} 喜欢 {1}, {1} 也喜欢 {0}", "Alice", "Bob");
// 命名参数
println!("{name} 今年 {age} 岁", name = "Charlie", age = 30);
// 格式化数字
let pi = 3.14159;
println!("π 的值是 {:.2}", pi); // 保留两位小数
// 调试输出
let array = [1, 2, 3];
println!("数组: {:?}", array);
// 美化调试输出
println!("漂亮格式: {:#?}", array);
}
使用 print! 和 eprint!
fn main() {
// 不换行输出
print!("正在加载...");
print!("完成!");
// 错误输出
eprintln!("这是一个错误信息!");
}
Rust 基础语法
变量和常量
fn main() {
// 不可变变量(默认)
let x = 5;
println!("x = {}", x);
// 可变变量
let mut y = 10;
y = 15;
println!("y = {}", y);
// 常量
const MAX_POINTS: u32 = 100_000;
println!("最大点数: {}", MAX_POINTS);
// 变量遮蔽
let spaces = " ";
let spaces = spaces.len();
println!("空格数量: {}", spaces);
}
语句和表达式
fn main() {
// 语句:执行操作但不返回值
let x = 6; // 这是一个语句
// 表达式:会计算出一个值
let y = {
let x = 3;
x + 1 // 没有分号,这是一个表达式
};
println!("y = {}", y);
}
Rust 运算符
算术运算符
fn main() {
let a = 10;
let b = 3;
println!("a + b = {}", a + b); // 13
println!("a - b = {}", a - b); // 7
println!("a * b = {}", a * b); // 30
println!("a / b = {}", a / b); // 3
println!("a % b = {}", a % b); // 1
// 浮点数运算
let c = 10.0;
let d = 3.0;
println!("c / d = {}", c / d); // 3.333...
}
比较运算符
fn main() {
let a = 5;
let b = 10;
println!("a == b: {}", a == b); // false
println!("a != b: {}", a != b); // true
println!("a < b: {}", a < b); // true
println!("a > b: {}", a > b); // false
println!("a <= b: {}", a <= b); // true
println!("a >= b: {}", a >= b); // false
}
逻辑运算符
fn main() {
let a = true;
let b = false;
println!("a && b: {}", a && b); // false
println!("a || b: {}", a || b); // true
println!("!a: {}", !a); // false
}
赋值运算符
fn main() {
let mut a = 5;
a += 3; // a = a + 3
println!("a = {}", a); // 8
a -= 2; // a = a - 2
println!("a = {}", a); // 6
a *= 2; // a = a * 2
println!("a = {}", a); // 12
a /= 3; // a = a / 3
println!("a = {}", a); // 4
}
Rust 数据类型
标量类型
fn main() {
// 整数类型
let a: i8 = -128; // 8位有符号整数
let b: u8 = 255; // 8位无符号整数
let c: i32 = 1_000_000; // 32位有符号整数
let d: u64 = 100; // 64位无符号整数
// 浮点类型
let e: f32 = 3.14; // 32位浮点数
let f: f64 = 2.71828; // 64位浮点数
// 布尔类型
let g: bool = true;
let h: bool = false;
// 字符类型
let i: char = 'A';
let j: char = '😊';
println!("字符: {}, {}", i, j);
}
复合类型
fn main() {
// 元组
let tup: (i32, f64, char) = (500, 6.4, 'A');
let (x, y, z) = tup; // 解构
println!("元组: {}, {}, {}", x, y, z);
// 通过索引访问
println!("第一个元素: {}", tup.0);
// 数组
let arr = [1, 2, 3, 4, 5];
let first = arr[0];
let second = arr[1];
println!("数组: {}, {}", first, second);
// 指定类型和大小的数组
let arr2: [i32; 5] = [1, 2, 3, 4, 5];
// 初始化相同值的数组
let arr3 = [3; 5]; // [3, 3, 3, 3, 3]
}
Rust 注释
单行注释
fn main() {
// 这是一个单行注释
let x = 5; // 声明变量 x
println!("x = {}", x);
}
多行注释
fn main() {
/*
这是一个多行注释
可以跨越多行
*/
let x = 5;
println!("x = {}", x);
}
文档注释
/// 这个函数用于计算两个数的和
///
/// # 参数
/// - `a`: 第一个加数
/// - `b`: 第二个加数
///
/// # 返回值
/// 返回两个数的和
///
/// # 示例
/// ```
/// let result = add(2, 3);
/// assert_eq!(result, 5);
/// ```
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = add(10, 20);
println!("10 + 20 = {}", result);
}
Rust 函数
函数定义
// 无参数无返回值的函数
fn say_hello() {
println!("Hello!");
}
// 有参数的函数
fn greet(name: &str) {
println!("Hello, {}!", name);
}
// 有返回值的函数
fn add(a: i32, b: i32) -> i32 {
a + b // 注意:没有分号,这是一个表达式
}
// 使用 return 关键字
fn subtract(a: i32, b: i32) -> i32 {
return a - b;
}
fn main() {
say_hello();
greet("Alice");
let sum = add(5, 3);
println!("5 + 3 = {}", sum);
let difference = subtract(10, 4);
println!("10 - 4 = {}", difference);
}
函数参数和返回值
// 多个参数
fn calculate(x: i32, y: i32) -> (i32, i32, i32, i32) {
let sum = x + y;
let difference = x - y;
let product = x * y;
let quotient = x / y;
(sum, difference, product, quotient)
}
fn main() {
let (a, b, c, d) = calculate(10, 2);
println!("和: {}", a);
println!("差: {}", b);
println!("积: {}", c);
println!("商: {}", d);
}
Rust 条件语句
if 语句
fn main() {
let number = 7;
if number < 5 {
println!("条件为真");
} else {
println!("条件为假");
}
// 多条件判断
if number % 4 == 0 {
println!("能被4整除");
} else if number % 3 == 0 {
println!("能被3整除");
} else if number % 2 == 0 {
println!("能被2整除");
} else {
println!("不能被2、3、4整除");
}
// if 是表达式,可以有返回值
let result = if number > 5 {
"大于5"
} else {
"小于等于5"
};
println!("结果: {}", result);
}
match 语句
fn main() {
let number = 3;
match number {
1 => println!("一"),
2 => println!("二"),
3 => println!("三"),
4 => println!("四"),
5 => println!("五"),
_ => println!("其他数字"), // 通配模式
}
// match 也是表达式
let description = match number {
1 => "很小",
2 | 3 => "小", // 匹配多个值
4..=6 => "中等", // 匹配范围
7..=10 => "大",
_ => "超出范围",
};
println!("这个数字 {} 是 {}", number, description);
}
Rust 循环
loop 循环
fn main() {
let mut count = 0;
// 无限循环
loop {
count += 1;
println!("计数: {}", count);
if count == 5 {
break; // 退出循环
}
}
// 从循环返回值
let result = loop {
count += 1;
if count == 10 {
break count * 2; // 返回 count * 2
}
};
println!("循环结果: {}", result);
}
while 循环
fn main() {
let mut number = 3;
while number != 0 {
println!("{}!", number);
number -= 1;
}
println!("发射!");
// 遍历数组
let arr = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("元素值: {}", arr[index]);
index += 1;
}
}
for 循环
fn main() {
// 遍历数组
let arr = [10, 20, 30, 40, 50];
for element in arr.iter() {
println!("元素值: {}", element);
}
// 遍历范围
for number in 1..4 { // 1, 2, 3
println!("{}!", number);
}
// 包含上界的范围
for number in 1..=4 { // 1, 2, 3, 4
println!("{}!", number);
}
// 反转范围
for number in (1..4).rev() {
println!("{}!", number);
}
}
Rust 迭代器
基本迭代器使用
fn main() {
let v = vec![1, 2, 3, 4, 5];
// 创建迭代器
let mut iter = v.iter();
// 逐个访问元素
println!("第一个元素: {:?}", iter.next());
println!("第二个元素: {:?}", iter.next());
// 遍历迭代器
for num in v.iter() {
println!("数字: {}", num);
}
// 迭代器适配器
let doubled: Vec<i32> = v.iter()
.map(|x| x * 2)
.collect();
println!("加倍后: {:?}", doubled);
// 过滤器
let evens: Vec<&i32> = v.iter()
.filter(|x| *x % 2 == 0)
.collect();
println!("偶数: {:?}", evens);
// 求和
let sum: i32 = v.iter().sum();
println!("总和: {}", sum);
}
常用迭代器方法
fn main() {
let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// map - 转换每个元素
let squares: Vec<i32> = numbers.iter()
.map(|x| x * x)
.collect();
println!("平方: {:?}", squares);
// filter - 过滤元素
let evens: Vec<&i32> = numbers.iter()
.filter(|x| *x % 2 == 0)
.collect();
println!("偶数: {:?}", evens);
// fold - 累积计算
let product = numbers.iter()
.fold(1, |a***, x| a*** * x);
println!("乘积: {}", product);
// chain - 连接迭代器
let more_numbers = vec![11, 12, 13];
let all_numbers: Vec<&i32> = numbers.iter()
.chain(more_numbers.iter())
.collect();
println!("所有数字: {:?}", all_numbers);
// zip - 合并两个迭代器
let names = vec!["Alice", "Bob", "Charlie"];
let zipped: Vec<(&str, &i32)> = names.iter()
.zip(numbers.iter())
.collect();
println!("合并: {:?}", zipped);
}
Rust 闭包
基本闭包语法
fn main() {
// 简单的闭包
let add_one = |x| x + 1;
println!("5 + 1 = {}", add_one(5));
// 带类型的闭包
let add_numbers = |x: i32, y: i32| -> i32 {
x + y
};
println!("3 + 7 = {}", add_numbers(3, 7));
// 捕获环境变量
let factor = 2;
let multiply = |x| x * factor;
println!("4 * 2 = {}", multiply(4));
// 闭包作为参数
let numbers = vec![1, 2, 3, 4, 5];
let doubled: Vec<i32> = numbers.iter()
.map(|x| x * 2)
.collect();
println!("加倍: {:?}", doubled);
}
闭包类型
fn main() {
let s = String::from("hello");
// Fn - 不可变借用
let print_len = |x: &String| println!("长度: {}", x.len());
print_len(&s);
// FnMut - 可变借用
let mut count = 0;
let mut increment = || {
count += 1;
println!("计数: {}", count);
};
increment();
increment();
// FnOnce - 获取所有权
let consume = || {
let _owned = s;
// s 的所有权被移动了
};
consume();
// println!("{}", s); // 错误!s 的所有权已被移动
}
Rust 所有权
所有权规则
fn main() {
// 规则1: 每个值都有一个所有者
let s1 = String::from("hello");
// 规则2: 一次只能有一个所有者
let s2 = s1; // s1 的所有权移动到 s2
// println!("{}", s1); // 错误!s1 不再有效
// 规则3: 当所有者离开作用域,值会被丢弃
{
let s3 = String::from("world");
println!("{}", s3);
} // s3 离开作用域,内存被释放
// println!("{}", s3); // 错误!s3 已不存在
}
所有权和函数
fn take_ownership(s: String) {
println!("获得所有权: {}", s);
} // s 离开作用域,drop 被调用
fn make_copy(x: i32) {
println!("复制值: {}", x);
} // x 离开作用域,没什么特别发生
fn give_ownership() -> String {
let s = String::from("hello");
s // 返回 s,所有权转移给调用者
}
fn main() {
let s1 = String::from("hello");
take_ownership(s1); // s1 的所有权移动到函数内
// println!("{}", s1); // 错误!s1 不再有效
let x = 5;
make_copy(x); // x 会移动进函数里,但 i32 是 Copy 的
println!("x 仍然有效: {}", x); // 所以后面可继续使用 x
let s2 = give_ownership(); // 函数返回值所有权转移给 s2
println!("s2 = {}", s2);
}
Rust Slice(切片)类型
字符串切片
fn main() {
let s = String::from("hello world");
// 字符串切片
let hello = &s[0..5];
let world = &s[6..11];
println!("{} {}", hello, world);
// 简写语法
let slice1 = &s[..5]; // 从开始到索引4
let slice2 = &s[6..]; // 从索引6到结束
let slice3 = &s[..]; // 整个字符串
println!("{}, {}, {}", slice1, slice2, slice3);
// 函数使用切片
let first_word = get_first_word(&s);
println!("第一个单词: {}", first_word);
}
fn get_first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
数组切片
fn main() {
let arr = [1, 2, 3, 4, 5];
let slice = &arr[1..4]; // 类型是 &[i32]
for element in slice.iter() {
println!("{}", element);
}
println!("切片长度: {}", slice.len());
println!("第一个元素: {}", slice[0]);
}
Rust 结构体
定义和实例化结构体
// 定义结构体
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn build_user(email: String, username: String) -> User {
User {
email, // 字段初始化简写语法
username, // 参数名与字段名相同时可省略
active: true,
sign_in_count: 1,
}
}
fn main() {
// 创建结构体实例
let mut user1 = User {
email: String::from("someone@example.***"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
// 访问字段
user1.email = String::from("anotheremail@example.***");
// 结构体更新语法
let user2 = User {
email: String::from("another@example.***"),
username: String::from("anotherusername567"),
..user1 // 使用 user1 的剩余字段
};
println!("用户邮箱: {}", user2.email);
}
结构体方法
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
// 关联函数(类似于静态方法)
fn square(size: u32) -> Rectangle {
Rectangle {
width: size,
height: size,
}
}
// 方法
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
let rect2 = Rectangle {
width: 10,
height: 40,
};
println!("rect1 的面积是: {}", rect1.area());
println!("rect1 能容纳 rect2: {}", rect1.can_hold(&rect2));
// 使用关联函数创建正方形
let sq = Rectangle::square(3);
println!("正方形的面积: {}", sq.area());
}
Rust 枚举类
基本枚举
enum IpAddrKind {
V4,
V6,
}
enum IpAddr {
V4(String),
V6(String),
}
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
route(four);
route(six);
}
fn route(ip_kind: IpAddrKind) {
// 处理 IP 类型
}
Option 枚举
fn main() {
// Option<T> 枚举
let some_number = Some(5);
let some_string = Some("a string");
let absent_number: Option<i32> = None;
// 使用 match 处理 Option
match some_number {
Some(n) => println!("数字是: {}", n),
None => println!("没有数字"),
}
// if let 语法糖
if let Some(5) = some_number {
println!("数字是5!");
}
// 使用 unwrap(谨慎使用)
let x = some_number.unwrap();
println!("x = {}", x);
}
Rust 组织管理
模块系统
// 声明模块
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
// 使用绝对路径
pub fn eat_at_restaurant() {
crate::front_of_house::hosting::add_to_waitlist();
}
// 使用相对路径
pub fn eat_at_restaurant2() {
front_of_house::hosting::add_to_waitlist();
}
// 使用 use 关键字
use crate::front_of_house::hosting;
pub fn eat_at_restaurant3() {
hosting::add_to_waitlist();
}
fn main() {
eat_at_restaurant();
eat_at_restaurant2();
eat_at_restaurant3();
}
文件分层
项目结构:
restaurant/
├── Cargo.toml
└── src/
├── lib.rs
├── main.rs
└── front_of_house.rs
src/front_of_house.rs:
pub mod hosting {
pub fn add_to_waitlist() {}
}
src/lib.rs:
mod front_of_house;
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
Rust 错误处理
Result 类型
use std::fs::File;
use std::io::{self, Read};
fn read_file_contents(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
fn main() {
// 使用 match 处理 Result
match read_file_contents("hello.txt") {
Ok(contents) => println!("文件内容: {}", contents),
Err(e) => println!("错误: {}", e),
}
// 使用 unwrap(如果出错会 panic)
let contents = read_file_contents("hello.txt").unwrap();
println!("内容: {}", contents);
// 使用 expect(自定义错误信息)
let contents = read_file_contents("hello.txt")
.expect("无法读取文件");
println!("内容: {}", contents);
}
panic! 宏
fn main() {
// 直接 panic
// panic!("严重错误!");
// 通过索引访问触发 panic
let v = vec![1, 2, 3];
// v[99]; // 这会 panic
// 使用 Result 而不是 panic
let result = safe_division(10, 0);
match result {
Ok(value) => println!("结果: {}", value),
Err(e) => println!("错误: {}", e),
}
}
fn safe_division(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("除数不能为零"))
} else {
Ok(a / b)
}
}
Rust 泛型与特性
泛型基础
// 泛型函数
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest {
largest = item;
}
}
largest
}
// 泛型结构体
struct Point<T> {
x: T,
y: T,
}
impl<T> Point<T> {
fn x(&self) -> &T {
&self.x
}
}
// 为特定类型实现方法
impl Point<f32> {
fn distance_from_origin(&self) -> f32 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
println!("最大数字是 {}", result);
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
println!("最大字符是 {}", result);
let integer_point = Point { x: 5, y: 10 };
let float_point = Point { x: 1.0, y: 4.0 };
println!("integer_point.x = {}", integer_point.x());
println!("float_point 距离原点: {}", float_point.distance_from_origin());
}
特性(Trait)
// 定义特性
pub trait Summary {
fn summarize(&self) -> String;
// 默认实现
fn summary(&self) -> String {
String::from("(阅读更多...)")
}
}
// 实现特性
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
// 特性作为参数
pub fn notify(item: &impl Summary) {
println!("突发新闻! {}", item.summarize());
}
// 特性约束语法
pub fn notify_twice<T: Summary>(item1: &T, item2: &T) {
println!("新闻1: {}", item1.summarize());
println!("新闻2: {}", item2.summarize());
}
// 多个特性约束
use std::fmt::Display;
pub fn notify_display<T: Summary + Display>(item: &T) {
println!("显示: {}", item);
println!("摘要: {}", item.summarize());
}
fn main() {
let tweet = Tweet {
username: String::from("horse_ebooks"),
content: String::from("of course, as you probably already know, people"),
reply: false,
retweet: false,
};
println!("1 则新推文: {}", tweet.summarize());
notify(&tweet);
let article = NewsArticle {
headline: String::from("大新闻!"),
location: String::from("北京"),
author: String::from("记者"),
content: String::from("这是一个重要的新闻内容..."),
};
notify_twice(&tweet, &article);
}
Rust 生命周期
生命周期注解
// 函数中的生命周期
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
// 结构体中的生命周期
struct ImportantExcerpt<'a> {
part: &'a str,
}
impl<'a> ImportantExcerpt<'a> {
fn level(&self) -> i32 {
3
}
fn announce_and_return_part(&self, announcement: &str) -> &str {
println!("请注意: {}", announcement);
self.part
}
}
fn main() {
let string1 = String::from("长的字符串");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("较长的字符串是: {}", result);
let novel = String::from("叫我以实玛利。很多年前...");
let first_sentence = novel.split('。').next().expect("找不到句号");
let i = ImportantExcerpt {
part: first_sentence,
};
println!("摘录: {}", i.part);
println!("等级: {}", i.level());
let part = i.announce_and_return_part("重要通知");
println!("返回的部分: {}", part);
}
生命周期省略规则
// 这些函数不需要显式的生命周期注解
// 因为编译器可以应用生命周期省略规则
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[0..i];
}
}
&s[..]
}
fn longest_word<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
fn main() {
let s = String::from("hello world");
let word = first_word(&s);
println!("第一个单词: {}", word);
let s1 = "短的";
let s2 = "较长的字符串";
let result = longest_word(s1, s2);
println!("较长的: {}", result);
}
Rust 文件与 IO
文件读写
use std::fs::{File, OpenOptions};
use std::io::{self, Read, Write, BufRead, BufReader, BufWriter};
use std::path::Path;
// 读取文件内容
fn read_file(path: &str) -> Result<String, io::Error> {
let mut file = File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
// 写入文件
fn write_file(path: &str, contents: &str) -> Result<(), io::Error> {
let mut file = File::create(path)?;
file.write_all(contents.as_bytes())?;
Ok(())
}
// 追加到文件
fn append_to_file(path: &str, contents: &str) -> Result<(), io::Error> {
let mut file = OpenOptions::new()
.append(true)
.open(path)?;
file.write_all(contents.as_bytes())?;
Ok(())
}
// 逐行读取文件
fn read_lines(path: &str) -> Result<Vec<String>, io::Error> {
let file = File::open(path)?;
let reader = BufReader::new(file);
let mut lines = Vec::new();
for line in reader.lines() {
lines.push(line?);
}
Ok(lines)
}
fn main() -> Result<(), io::Error> {
// 写入文件
write_file("example.txt", "Hello, World!\n这是第二行")?;
// 读取文件
let contents = read_file("example.txt")?;
println!("文件内容:\n{}", contents);
// 追加内容
append_to_file("example.txt", "\n这是追加的内容")?;
// 逐行读取
let lines = read_lines("example.txt")?;
println!("文件行数: {}", lines.len());
for (i, line) in lines.iter().enumerate() {
println!("行 {}: {}", i + 1, line);
}
// 检查文件是否存在
if Path::new("example.txt").exists() {
println!("文件存在");
}
Ok(())
}
目录操作
use std::fs;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建目录
fs::create_dir_all("my_directory/sub_dir")?;
println!("目录创建成功");
// 读取目录
let entries = fs::read_dir(".")?;
for entry in entries {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
println!("目录: {:?}", path);
} else {
println!("文件: {:?}", path);
}
}
// 获取文件元数据
let metadata = fs::metadata("example.txt")?;
println!("文件大小: {} 字节", metadata.len());
println!("是否是文件: {}", metadata.is_file());
// 删除文件
fs::remove_file("example.txt")?;
println!("文件已删除");
// 删除目录
fs::remove_dir_all("my_directory")?;
println!("目录已删除");
Ok(())
}
Rust 集合与字符串
Vector 深入
fn vector_operations() {
let mut v = vec![1, 2, 3, 4, 5];
// 访问元素
let third = &v[2];
println!("第三个元素是: {}", third);
// 安全访问
match v.get(2) {
Some(third) => println!("第三个元素是: {}", third),
None => println!("没有第三个元素"),
}
// 遍历并修改
for i in &mut v {
*i += 10;
}
// 使用枚举存储多种类型
#[derive(Debug)]
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("蓝色")),
SpreadsheetCell::Float(10.12),
];
for cell in &row {
match cell {
SpreadsheetCell::Int(i) => println!("整数: {}", i),
SpreadsheetCell::Float(f) => println!("浮点数: {}", f),
SpreadsheetCell::Text(s) => println!("文本: {}", s),
}
}
}
fn main() {
vector_operations();
}
HashMap
use std::collections::HashMap;
fn hashmap_examples() {
// 创建 HashMap
let mut scores = HashMap::new();
// 插入值
scores.insert(String::from("蓝队"), 10);
scores.insert(String::from("黄队"), 50);
// 访问值
let team_name = String::from("蓝队");
let score = scores.get(&team_name);
match score {
Some(s) => println!("{} 的分数是: {}", team_name, s),
None => println!("没有找到 {}", team_name),
}
// 遍历 HashMap
for (key, value) in &scores {
println!("{}: {}", key, value);
}
// 只在键不存在时插入
scores.entry(String::from("红队")).or_insert(30);
scores.entry(String::from("蓝队")).or_insert(50); // 不会更新
println!("更新后的分数: {:?}", scores);
// 根据旧值更新
let text = "hello world wonderful world";
let mut map = HashMap::new();
for word in text.split_whitespace() {
let count = map.entry(word).or_insert(0);
*count += 1;
}
println!("词频统计: {:?}", map);
}
fn main() {
hashmap_examples();
}
字符串操作
fn string_operations() {
// 创建字符串
let mut s = String::new();
let s = "初始内容".to_string();
let s = String::from("初始内容");
// 更新字符串
let mut s = String::from("foo");
s.push_str("bar");
s.push('!');
// 字符串拼接
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2; // 注意 s1 被移动了,不能再使用
// 格式化字符串
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
let s = format!("{}-{}-{}", s1, s2, s3);
println!("{}", s);
// 字符串索引和切片
let hello = "Здравствуйте";
let s = &hello[0..4]; // 前4个字节
println!("{}", s);
// 遍历字符串
for c in "नमस्ते".chars() {
println!("{}", c);
}
for b in "नमस्ते".bytes() {
println!("{}", b);
}
}
fn main() {
string_operations();
}
Rust 面向对象
结构体和方法
pub struct AveragedCollection {
list: Vec<i32>,
average: f64,
}
impl AveragedCollection {
pub fn new() -> AveragedCollection {
AveragedCollection {
list: vec![],
average: 0.0,
}
}
pub fn add(&mut self, value: i32) {
self.list.push(value);
self.update_average();
}
pub fn remove(&mut self) -> Option<i32> {
let result = self.list.pop();
match result {
Some(value) => {
self.update_average();
Some(value)
}
None => None,
}
}
pub fn average(&self) -> f64 {
self.average
}
fn update_average(&mut self) {
let total: i32 = self.list.iter().sum();
self.average = total as f64 / self.list.len() as f64;
}
}
fn main() {
let mut collection = AveragedCollection::new();
collection.add(10);
collection.add(20);
collection.add(30);
println!("平均值: {}", collection.average());
collection.remove();
println!("移除一个元素后的平均值: {}", collection.average());
}
特性与多态
pub trait Draw {
fn draw(&self);
}
pub struct Screen {
pub ***ponents: Vec<Box<dyn Draw>>,
}
impl Screen {
pub fn run(&self) {
for ***ponent in self.***ponents.iter() {
***ponent.draw();
}
}
}
pub struct Button {
pub width: u32,
pub height: u32,
pub label: String,
}
impl Draw for Button {
fn draw(&self) {
println!("绘制按钮: {}x{}, 标签: '{}'",
self.width, self.height, self.label);
}
}
struct SelectBox {
width: u32,
height: u32,
options: Vec<String>,
}
impl Draw for SelectBox {
fn draw(&self) {
println!("绘制选择框: {}x{}, 选项: {:?}",
self.width, self.height, self.options);
}
}
fn main() {
let screen = Screen {
***ponents: vec![
Box::new(SelectBox {
width: 75,
height: 10,
options: vec![
String::from("是"),
String::from("可能"),
String::from("否"),
],
}),
Box::new(Button {
width: 50,
height: 10,
label: String::from("确定"),
}),
],
};
screen.run();
}
Rust 并发编程
线程
use std::thread;
use std::time::Duration;
fn main() {
// 创建新线程
let handle = thread::spawn(|| {
for i in 1..10 {
println!("线程中的数字 {}!", i);
thread::sleep(Duration::from_millis(1));
}
});
// 主线程
for i in 1..5 {
println!("主线程中的数字 {}!", i);
thread::sleep(Duration::from_millis(1));
}
// 等待线程结束
handle.join().unwrap();
// 使用 move 闭包
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("这是向量: {:?}", v);
});
handle.join().unwrap();
}
通道(Channel)
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
// 创建通道
let (tx, rx) = mpsc::channel();
// 克隆发送端
let tx1 = tx.clone();
// 生产者线程1
thread::spawn(move || {
let vals = vec![
String::from("hi"),
String::from("from"),
String::from("the"),
String::from("thread"),
];
for val in vals {
tx1.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
}
});
// 生产者线程2
thread::spawn(move || {
let vals = vec![
String::from("more"),
String::from("messages"),
String::from("for"),
String::from("you"),
];
for val in vals {
tx.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
}
});
// 消费者
for received in rx {
println!("收到: {}", received);
}
}
互斥锁(Mutex)
use std::sync::{Arc, Mutex};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("结果: {}", *counter.lock().unwrap());
}
Rust 宏
声明宏
// 定义声明宏
macro_rules! vec {
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push($x);
)*
temp_vec
}
};
}
macro_rules! calculate {
(eval $e:expr) => {{
{
let val: usize = $e;
println!("{} = {}", stringify!{$e}, val);
}
}};
}
fn main() {
// 使用 vec! 宏
let v = vec![1, 2, 3];
println!("向量: {:?}", v);
// 使用 calculate! 宏
calculate! {
eval 1 + 2
}
calculate! {
eval (1 + 2) * (3 / 1)
}
}
过程宏
Cargo.toml:
[lib]
proc-macro = true
[dependencies]
syn = "1.0"
quote = "1.0"
自定义派生宏示例:
use proc_macro::TokenStream;
use quote::quote;
use syn;
#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
impl_hello_macro(&ast)
}
fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let gen = quote! {
impl HelloMacro for #name {
fn hello_macro() {
println!("你好,宏!我是 {}", stringify!(#name));
}
}
};
gen.into()
}
使用自定义宏:
use hello_macro::HelloMacro;
#[derive(HelloMacro)]
struct Pancakes;
fn main() {
Pancakes::hello_macro();
}
Rust 智能指针
Box
fn box_example() {
let b = Box::new(5);
println!("b = {}", b);
// 递归类型
#[derive(Debug)]
enum List {
Cons(i32, Box<List>),
Nil,
}
use List::{Cons, Nil};
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))));
println!("列表: {:?}", list);
}
fn main() {
box_example();
}
Rc 和 RefCell
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Debug)]
enum List {
Cons(Rc<RefCell<i32>>, Rc<List>),
Nil,
}
use List::{Cons, Nil};
fn rc_refcell_example() {
let value = Rc::new(RefCell::new(5));
let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));
*value.borrow_mut() += 10;
println!("a after = {:?}", a);
println!("b after = {:?}", b);
println!("c after = {:?}", c);
}
fn main() {
rc_refcell_example();
}
Rust 异步编程
async/await 基础
use std::time::Duration;
use tokio::time::sleep;
// 异步函数
async fn learn_song() -> String {
sleep(Duration::from_secs(2)).await;
String::from("我在唱歌!")
}
async fn sing_song(song: String) {
println!("{}", song);
}
async fn dance() {
println!("我在跳舞!");
}
async fn learn_and_sing() {
let song = learn_song().await;
sing_song(song).await;
}
async fn async_main() {
let f1 = learn_and_sing();
let f2 = dance();
// 使用 join! 同时等待多个 Future
tokio::join!(f1, f2);
}
#[tokio::main]
async fn main() {
println!("开始表演...");
async_main().await;
println!("表演结束!");
}
使用 tokio 进行异步编程
use tokio::***::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
println!("服务器运行在 127.0.0.1:8080");
loop {
let (mut socket, _) = listener.a***ept().await?;
tokio::spawn(async move {
let mut buf = [0; 1024];
// 读取数据
match socket.read(&mut buf).await {
Ok(0) => return, // 连接关闭
Ok(n) => {
// 回显数据
if let Err(e) = socket.write_all(&buf[0..n]).await {
eprintln!("写入套接字失败: {}", e);
}
}
Err(e) => {
eprintln!("读取套接字失败: {}", e);
}
}
});
}
}
异步通道
use tokio::sync::mpsc;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let (tx, mut rx) = mpsc::channel(32);
// 生产者
let producer = tokio::spawn(async move {
for i in 0..10 {
if let Err(_) = tx.send(i).await {
println!("接收端已关闭");
break;
}
sleep(Duration::from_millis(100)).await;
}
});
// 消费者
let consumer = tokio::spawn(async move {
while let Some(message) = rx.recv().await {
println!("收到: {}", message);
}
});
let _ = tokio::join!(producer, consumer);
}
Rust下一步学习方向建议
- Web 开发:学习 Actix-web 或 Rocket 框架
- 系统编程:深入操作系统和网络编程
- 嵌入式开发:探索 Rust 在嵌入式领域的应用
- 区块链开发:学习智能合约开发
- 性能优化:掌握 Rust 的性能调优技巧