rust 2025年1月1日

Learn Rust in a Month of Lunches

胡喝海吃一个月,学会Rust?
书籍封面

Learn Rust in a Month of Lunches

作者:Allen Wyma 出版日期:2024-03-26 出版社:Manning
本书涵盖了Rust编程语言的方方面面。它从基础概念如变量、数据类型和内存管理开始,逐步深入到更高级的主题,例如所有权、生命周期、错误处理、并发编程和异步编程。书中包含大量的代码示例和练习,旨在帮助读者在短时间内掌握Rust编程。此外,书中还介绍了一些常用的外部库,以及如何使用Cargo构建和管理Rust项目。
  • 第一章:Rust 基础入门

    • 核心概念: 本章主要介绍了 Rust 的基本语法和概念,包括变量声明、代码块、打印输出、类型转换和字符串。
    • 变量与代码块:
      • 使用 let 关键字声明变量,代码块用 {} 表示。变量的作用域(lifetime)限制在代码块内部。
      • Shadowing (遮蔽) 是指用新的 let 绑定同名变量,使之前的变量失效。
      • 变量的类型通常由 Rust 自动推断,但可以使用 as 关键字进行显式类型转换。
    • 打印输出:
      • println! 宏用于打印输出,{} 用来捕获变量的值。{:?} 用于调试输出,{:#?} 用于更美观的调试输出,可以分行显示结构体等复杂类型的内容。
      • print! 宏与 println! 类似,但不添加换行符。
      • 可以使用 r#""# 来创建原始字符串,避免转义字符的麻烦。
      • 在字符串前加 b 可以打印字符串的字节表示。
    • 字符串类型: &str 是一种字符串切片类型,后续章节会详细介绍。
  • 第二章:内存、变量与所有权

    • 核心概念: 本章深入探讨了 Rust 的内存管理机制,包括所有权、借用和引用。
    • 所有权: Rust 通过所有权系统来管理内存,每个值都有一个所有者。
    • 引用:
      • 不可变引用&)允许多个读取者同时访问数据,但不能修改。
      • 可变引用&mut)允许一个写入者修改数据,但不能同时存在其他引用。
    • 打印输出格式化: {:} 用于显示打印, {:?}用于debug打印,{:#?}用于美化debug打印。可以使用 "{:padding_char^min_length}" 来控制打印的对齐和填充。
      • 例如,println!("{:ㅎ^11}", letter); 会在字母 “a” 的左右两侧填充韩文字符 ㅎ,总长度为 11。
  • 第三章:更复杂的类型

    • 核心概念: 本章介绍了 Rust 中更复杂的数据类型和控制流,包括元组、枚举、结构体、if 语句、match 语句和循环。
    • 元组: 元组可以将多个不同类型的值组合在一起。可以使用 _ 忽略元组中不需要的值。
    • 控制流:
      • if 语句用于根据条件执行代码块。
      • match 语句用于模式匹配,可以根据不同的值执行不同的代码块。可以使用 _ 作为通配符,匹配其他情况。if 关键字可以用于 match 语句中进行条件匹配。
      • 循环包括 loopfor 等,loop 会一直循环直到 breakfor 循环可以迭代一个范围,如 0..3 (不包含3) 和 0..=3 (包含3)。
    • 结构体:
      • 结构体 (struct) 用于将多个相关的值组合成一个数据结构。可以使用 struct ColorRgb(u8, u8, u8); 定义一个元组结构体,也可以使用 struct SizeAndColor { size: u32, color: ColorRgb, } 定义一个命名结构体。
    • 枚举:
      • 枚举 (enum) 用于定义一组可能的值,例如 enum ThingsInTheSky { Sun, Stars, }。可以使用 :: 来选择枚举的变体。
  • 第四章:构建自定义类型

    • 核心概念: 本章继续深入探讨了 Rust 的自定义类型,包括如何在枚举中存储数据,以及 use 关键字的用法。
    • 枚举变体中的数据: 枚举的变体可以携带数据,例如 enum Number { U32(u32), I32(i32), }
    • use 关键字: use 关键字用于简化代码,可以导入枚举的变体。use 可以避免在使用枚举变体时重复书写枚举名称。use std::mem::size_of_val; 可以使用 size_of_val() 函数,而无需每次都写 std::mem::
  • 第五章:泛型、Option 和 Result

    • 核心概念: 本章介绍了 Rust 的泛型、OptionResult 类型,用于编写更灵活、更健壮的代码。
    • 泛型: 泛型允许函数或结构体接受多种类型,可以使用 <T> 来声明泛型类型。where 关键字用于在泛型类型上添加约束,例如 where T: Display 表示 T 必须实现 Display trait。
    • Option 类型: Option 类型用于处理可能为空的值,它有两个变体:Some(T)None
    • Result 类型: Result 类型用于处理可能失败的操作,它有两个变体:Ok(T)Err(E)Err 变体通常包含描述错误信息的类型。
    • 模式匹配: 可以使用 match 语句对 OptionResult 类型进行模式匹配,处理不同的情况。
  • 第六章:更多集合类型和错误处理

    • 核心概念: 本章介绍了更多的集合类型和 Rust 的错误处理机制,包括 ? 运算符和 panic! 宏。
    • ? 运算符: ? 运算符用于简化 Result 类型的错误处理,如果结果是 Ok,则返回其值,否则提前返回错误。
    • panic! 宏: panic! 宏用于抛出不可恢复的错误,程序会终止。assert!assert_eq!assert_ne! 宏用于在测试中检查条件是否满足。
    • 集合类型: 本章提到 Rust 还有很多集合类型,例如 BinaryHeap (二叉堆), 但没有详细介绍。
  • 第七章:Traits:让不同的类型做相同的事

    • 核心概念: 本章重点介绍了 Rust 的 trait,用于定义共享行为,实现多态。
    • Traits: Traits 可以被不同的类型实现,从而实现代码的复用,类似于其他语言的接口 (interface)。T: Display 表示类型 T 必须实现 Display trait。
    • unwrap_orunwrap_or_else 方法: unwrap_or 方法在 OptionNoneResultErr 时返回一个默认值。unwrap_or_else 方法则接收一个闭包来生成默认值。
    • 生命周期: 'a 表示生命周期,例如 struct City<'a> { name: &'a str, date_founded: u32 },表示 name 的生命周期至少与 City 结构体一样长。
  • 第十章:生命周期

    • 核心概念: 本章主要探讨了生命周期和内部可变性。
    • 生命周期: 生命周期用于确保引用不会悬空,<'a> 用于声明生命周期。
    • 内部可变性: CellRefCellMutexRwLock 这些类型提供了内部可变性,允许在不可变类型中修改数据。
      • Cell 类型用于包装实现了 Copy trait 的类型,可以使用 .get().set() 方法修改其值。
      • RefCell 类型使用 .borrow().borrow_mut() 方法提供运行时借用检查,允许多个不可变借用或一个可变借用。
      • MutexRwLock 类型用于多线程编程,保证线程安全地访问共享数据。Mutex 提供互斥访问,RwLock 提供读写锁,允许多个读操作或一个写操作。
  • 第十一章:多线程及其他

    • 核心概念: 本章涵盖了多线程、todo! 宏、类型别名、Cow 类型和 Rc 类型等主题。
    • 多线程: 可以使用 std::thread::spawn() 创建新线程,使用 JoinHandle 等待线程结束。move 关键字用于将变量的所有权转移到闭包中。
    • todo! 宏: todo! 宏用于标记代码中尚未实现的部分,让编译器暂时忽略错误。
    • 类型别名: 使用 type 关键字创建类型别名,可以给现有类型取一个新名字。
    • Cow 类型: Cow 类型(Copy-on-Write)用于处理借用或拥有的数据,可以在需要时进行复制,提高效率。
    • Rc 类型: Rc 类型(Reference Counting)用于在多个所有者之间共享数据,当最后一个 Rc 实例被删除时,数据会被释放。
  • 第十二章:闭包、泛型和线程

    • 核心概念: 本章深入探讨了闭包、泛型和线程,并介绍了闭包的三种 trait:FnFnMutFnOnce
    • 闭包: 闭包是一种可以捕获环境的匿名函数,具有三种 trait:
      • Fn:捕获环境中的不可变引用。
      • FnMut:捕获环境中的可变引用。
      • FnOnce:捕获环境中的值,只能调用一次。
    • 闭包作为参数: 函数可以接受闭包作为参数,并使用泛型来指定闭包的 trait。可以使用 impl Trait 来表示返回闭包的函数。
    • 线程: 本章继续讨论了线程,主要介绍了如何使用闭包在线程中执行代码。
  • 第十三章:Box 和 Rust 文档

    • 核心概念: 本章介绍了 Box 类型、如何阅读 Rust 文档,以及一些高级错误处理技巧。
    • Box 类型: Box 类型用于在堆上分配内存,例如 Box<dyn Error> 用于存储实现了 Error trait 的类型。
    • 读取 Rust 文档: Rust 文档可以使用 cargo doc 命令生成。可以通过点击 [src] 查看源代码。
    • 高级错误处理: 可以使用 thiserror crate 创建自定义错误类型,并使用 #[from] 注解简化错误转换。还可以使用 blanket trait implementations 来处理所有实现了 std::error::Error 的类型。
  • 第十四章:测试和从测试构建代码

    • 核心概念: 本章介绍了 Rust 的测试框架和如何使用测试驱动开发 (TDD) 方法构建代码。
    • 测试: 可以使用 #[test] 注解标记测试函数。assert_eq! 宏用于检查两个值是否相等,#[should_panic] 注解用于标记应该 panic 的测试。
    • 测试驱动开发 (TDD): 本章通过一个简单的减法计算器例子,说明了如何先写测试,再实现代码。
  • 第十五章:Default、构建者模式和 Deref

    • 核心概念: 本章介绍了 Default trait、构建者模式和 Deref trait。
    • Default trait: Default trait 用于为类型提供默认值,可以使用 ::default() 方法获取默认值。
    • 构建者模式: 构建者模式用于创建复杂对象,提供链式调用的方法来设置对象的属性。
    • DerefDerefMut trait: Deref trait 允许像使用原始类型一样使用智能指针。DerefMut trait 允许可变借用 。
  • 第十六章:Const、”unsafe” Rust 和外部包

    • 核心概念: 本章介绍了 constunsafe Rust 和如何使用外部 crate。
    • const const 关键字用于定义常量,const 可以用于泛型参数 。const fn 用于声明可以在编译时求值的函数 。
    • unsafe Rust: unsafe 关键字用于标记不安全的 Rust 代码,例如直接操作内存 。
    • 外部包: 可以使用 Cargo.toml 文件管理项目依赖,并使用 use 关键字导入外部 crate 的模块。
  • 第十七章:Anyhow 和 Thiserror

    • 核心概念: 本章介绍了 AnyhowThiserror 两个常用的错误处理 crate。
    • Anyhow Anyhow 提供了 anyhow::Error 类型,用于快速处理错误。anyhow! 宏用于快速创建错误。
    • Thiserror Thiserror 允许使用 #[derive(Error)] 为自定义错误类型派生 Error trait。
  • 第十八章:文件操作

    • 核心概念: 本章介绍了如何在 Rust 中进行文件操作,包括创建、打开、写入和读取文件。
    • 文件操作: std::fs::File 用于表示文件,可以使用 File::create() 创建新文件,File::open() 打开现有文件, write_all() 写入字节数据, read_to_string() 读取文件内容。
    • OpenOptions OpenOptions 结构体用于自定义文件操作的行为,如只创建文件,不覆盖已有文件。
  • 第十九章:异步编程

    • 核心概念: 本章介绍了 Rust 的异步编程,使用了 tokio crate。
    • 异步编程: 使用 async 关键字声明异步函数,使用 .await 等待异步操作完成。 #[tokio::main] 用于标记异步的 main 函数。可以使用 tokio::try_join! 来等待多个异步任务完成,并在其中任何一个任务失败时返回错误。
  • 第二十章:操作符重载和其他类型

    • 核心概念: 本章介绍了 Rust 的操作符重载、关联类型和 bool 类型。
    • 操作符重载: 通过实现 std::ops 中的 trait 可以实现操作符重载,例如 AddSubMulDiv
    • 关联类型和关联常量: Trait 可以包含关联类型和常量,使用 const 定义常量。
    • bool 类型: Rust 的 bool 类型只有 truefalse 两个值。
  • 第二十一章:继续探索

    • 核心概念: 本章介绍了 Rust 标准库中的一些其他重要功能,包括 panic hook 和 backtrace。
    • Panic Hook: 可以使用 std::panic::set_hook 设置自定义的 panic hook,在程序 panic 时执行。
    • Backtrace: Backtrace 用于追踪程序调用栈,可以帮助调试错误。
    • unreachable! 宏: unreachable! 宏用于标记永远不会被执行的代码。
  • 第二十二章:编写自定义宏

    • 核心概念: 本章介绍了如何编写自定义宏,用于代码生成。
    • 宏: 可以使用 macro_rules! 定义宏。宏可以使用 identexprtt 等类型匹配不同的输入。
    • 宏的重复: 使用 $(...)*+ 可以匹配零个或多个、一个或多个重复的标记。? 用于表示零个或一个重复。
    • 标准库宏: format_args! 宏 用于格式化字符串,todo! 宏用于标记未实现的代码。dbg! 宏用于调试打印。 matches! 宏用于匹配表达式和模式。
  • 第二十三章:终端时钟和秒表

    • 核心概念: 本章展示了如何使用 Rust 构建一个终端时钟和秒表程序。
    • Ratatui: 本章使用了 ratatui crate 来构建终端界面。
    • 程序结构: 秒表应该具有三种状态:未启动、运行和停止。
  • 第二十四章:Web 服务

    • 核心概念: 本章介绍了如何构建一个简单的 Web 应用程序。
    • Axum: 本章使用了 Axum crate 来构建 Web 服务。
    • 静态变量: 提到了如何使用 Arc<Mutex> 来在多线程环境中使用静态变量,但没有深入展开。

总结来说,这本书从 Rust 的基础语法开始,逐步深入到更高级的概念,如所有权、生命周期、泛型、闭包、多线程、宏和外部 crate 等,并通过实际例子展示了如何使用 Rust 构建各种应用程序。