Rust 入门

Rust 教程

什么是 Rust?

Rust 是一门系统编程语言,由 Mozilla 研究院开发,专注于安全、速度和并发。它的设计思想是:在保证内存安全的同时,不牺牲性能。

Rust 的特点:

  • 零成本抽象
  • 移动语义
  • 保证内存安全
  • 线程无数据竞争
  • 基于 trait 的泛型
  • 模式匹配
  • 类型推断
  • 最小运行时
  • 高效 C 绑定
// 第一个 Rust 程序
fn main() {
    println!("Hello, World!");
}

Rust 环境搭建

安装 Rust

Windows 安装:

  1. 下载 rustup-init.exe
  2. 运行安装程序,按默认选项安装
  3. 重启命令行工具

Linux/macOS 安装:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env

验证安装

rustc --version
cargo --version

开发工具配置

推荐使用 VS Code:

  1. 安装 VS Code
  2. 安装 rust-analyzer 扩展
  3. 安装 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 的性能调优技巧
转载请说明出处内容投诉
CSS教程网 » Rust 入门

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买