Rust权威指南
  • 推荐1
  • 收藏1
  • 浏览1.1K

Rust权威指南

Steve Klabnik,Carol Nichols (作者)  毛靖凯 , 唐刚 , 沙渺 (译者)

  • 书  号:978-7-121-38706-7
  • 出版日期:2020-06-01
  • 页  数:
  • 开  本:
  • 出版状态:正在印刷
  • 原书名: The Rust Programming Language
  • 原书号:9781593278281
  • 维护人:刘恩惠
本书由Rust 核心团队成员编写而成,由浅入深地探讨了Rust 语言的方方面面。从创建函数、选择数据类型及绑定变量等基础内容着手,逐步介绍所有权、生命周期、trait、安全保证等高级概念,错误处理、模式匹配、包管理、并发机制、函数式特性等实用工具,以及完整的项目开发实战案例。
作为开源的系统级编程语言,Rust 可以帮助你编写出更有效率且更加可靠的软件,在给予开发者底层控制能力的同时,通过高水准的工程设计避免了传统语言带来的诸多麻烦。
本书适合所有希望评估、入门、提高和研究Rust 语言的软件开发人员阅读。
Rust核心开发团队编写|Rust开发者不可或缺的案头书
毛靖凯,游戏设计师,一直专注于游戏领域研发,曾负责设计和维护了多个商业游戏的基础框架。业余时间活跃于Rust开源社区,并尝试使用Rust来解决游戏领域中的诸多问题。
唐刚,资深开发者,Rustcc社区创始人和维护者之一。目前就职于Cdot Network。使用Rust从事区块链共识协议的开发工作。
沙渺,嵌入式开发者,国内Rust语言社区和Raspberry Pi(树莓派)开发社区早期参与者。负责维护多个RISC-V架构硬件平台的基础函数库。
前 言
欢迎阅读《Rust权威指南》,我们会在本书中深入浅出地向你介绍Rust语言!
Rust是一门可以帮助你开发出高效率、高可靠性软件的编程语言。以往的编程语言往往无法同时兼顾高水准的工程体验与底层的控制能力,而Rust则被设计出来挑战这一目标,它力图同时提供强大的工程能力及良好的开发体验,在给予开发者控制底层细节能力(比如内存操作)的同时,避免传统语言带来的诸多麻烦。
谁是Rust的目标用户
基于各种各样的原因,Rust对于许多人来讲都是一门相当理想的语言。现在让我们看一看其中最重要的一些群体。
开发团队
Rust已经被证明可以高效地应用于大规模的、拥有不同系统编程背景的开发团队。底层代码总是容易出现各种各样隐晦的错误,对于大部分编程语言来说,想要发现这些错误,要么通过海量的测试样例,要么通过优秀程序员细致的代码评审。而在Rust的世界里,大部分的错误(甚至包括并发环境中产生的错误)都可以在编译阶段被编译器发现并拦截。得益于编译器这种类似于守门员的角色,开发团队可以在更多的时间内专注于业务逻辑而非错误调试。
当然,Rust也附带了一系列面向系统级编程的现代化开发工具:
 Cargo 提供了一套内置的依赖管理与构建工具。通过Cargo,你可以在Rust生态系统中一致地、轻松地增加、编译及管理依赖。
 Rustfmt 用于约定一套统一的编码风格。
 The Rust Language Server 则为集成开发环境(IDE)提供了可供集成的代码补全和错误提示工具。
通过使用上述工具,开发者可以有效率地进行系统级编程。
学生
对于那些有兴趣接触系统编程的学生而言,Rust也是一个非常好的选择,已经有不少人基于Rust来学习诸如操作系统开发之类的课程。另外,我们拥有一个非常热情的社区,社区成员们总是乐于回答来自初学者的各种问题。Rust开发团队希望通过本书让更多的人,特别是学生,能更加轻松地接触、学习系统编程的各种概念。
企业
目前已经有数百家或大或小的企业,将Rust用于生产环境并用它来处理各式各样的任务。这些任务包括命令行工具开发、Web服务开发、DevOps工具开发、嵌入式设备开发、音频图像分析转码、数字货币交易、生物信息提取、搜索引擎开发、物联网开发、机器学习算法研究,以及Firefox网络浏览器中的大部分功能开发。
开源开发者
当然,我们欢迎所有愿意参与构建Rust编程语言本身,或者周边社区、开发工具及第三方库的开发者。你们的贡献对于构建一个良好的Rust语言生态环境非常重要!
重视速度与稳定性的开发者
Rust适用于那些重视速度与稳定性的开发者。当谈论到速度时,我们不仅是指Rust程序可以拥有良好的运行时效率,而且还期望Rust可以提供良好的开发时效率。得益于Rust编译器的静态检查能力,我们可以稳定地在开发过程中增添功能或重构代码。与此形成鲜明对比的是,在缺少这些检查能力的语言中,开发者往往恐惧于修改那些脆弱的遗留代码。此外,得益于对零开销抽象这一概念的追求,开发者可以在无损耗的前提下使用高级语言特性。Rust力图使安全的代码也同样高效。
当然,这里提到的只是Rust使用场景中最有代表性的一部分用户,Rust语言也希望能够服务于尽可能多的其他开发者群体。总的来说,Rust最大的目标在于通过同时保证安全与效率、运行速度与编程体验,消除数十年来程序员们不得不接受的那些取舍。不妨给Rust一个机会,让我们一起来看一看它是否适合你。
谁是本书的目标读者
对于本书的读者,我们假设你已经使用过某种其他编程语言。虽然我们努力使本书的内容能够被具有不同编程背景的读者所接受,但我们不会花太多时间去讨论一些基本的编程概念。如果你对于编程是完全陌生的,那么你最好先阅读一些入门类的编程图书。
如何阅读本书
通常而言,我们假定读者按顺序从头到尾阅读本书。一开始我们会简单地介绍一些概念,接着在随后的章节中逐步深入,并有针对性地对其中的细节进行讨论。后面章节的讨论建立在前面章节引入的概念之上。
在本书中,你会发现两种类型的章节:概念讨论类章节和项目实践类章节。在概念讨论类章节中,你会接触到Rust的某些特性;在项目实践类章节中,我们会利用之前已经讲解过的Rust特性来共同构建一些小程序。第2章、第12章、第20章属于项目实践类章节,其余章节属于概念讨论类章节。
第1章会介绍如何安装Rust,如何编写“Hello, World!”程序,以及如何使用Cargo来对它进行管理及构建。
第2章会从实践的角度对Rust语言进行介绍,这里我们会从较高的层次去覆盖一系列概念,并在之后的章节中逐步深入研究细节。如果你是一个实践派,想要立即动手编写代码,那么第2章正好适合你。第3章会介绍Rust中类似于其他语言的那些特性,心急的人也许会尝试跳过这一章,并直接阅读第4章中关于Rust所有权系统的内容。相反,如果你是一个特别重视细节的学习者,期望一步一步了解清楚每一个角落,那么我建议你跳过第2章,从第3章开始按顺序阅读,并在想要通过实践来巩固知识点时再返回第2章进行阅读。
第5章会讨论结构体和方法,第6章会包含枚举、match表达式及if let控制流结构的相关内容。你将学会在Rust中使用结构体及枚举来创建自定义类型。
在第7章中,你会了解到Rust中的模块系统及私有性规则,并学会如何使用它们来组织代码和设计公共接口(API)。第8章会介绍一些标准库中提供的常用数据结构,比如Vec(动态数组)、String(字符串)及HashMap(哈希表)。第9章会讨论Rust中关于错误处理的一些设计理念和工具。
第10章会深入讲解关于泛型、trait(特征)和生命周期的概念,它们赋予了你复用代码的能力。第11章则是关于如何在Rust中构建测试系统的内容。即便是有Rust的安全检查,我们也需要通过测试来保障业务逻辑上的正确性。在第12章中,我们会实现命令行工具grep的一些功能子集,用于在文件中搜索某些特定文本,为此我们会用到很多前面章节中讨论的概念。
第13章会讨论Rust中与函数式编程相关的概念:闭包与迭代器。在第14章中,我们会更加深入地了解Cargo,以及与他人共享代码库的一些最佳实践。第15章会讨论标准库中的智能指针,以及它们所实现的相关trait。
在第16章中,我们会讨论多个不同的并发编程模型,并看一看Rust是如何让多线程编程变得不那么恐怖的。第17章则着眼于比较Rust与常见的面向对象编程范式的不同风格。
第18章是关于模式及模式匹配的介绍,它们给Rust语言带来了异常强大的表达能力。第19章则会覆盖一些有趣的高级主题,包括对不安全Rust、宏、trait、类型、函数及闭包的更深入的讨论。
终于,在第20章中,我们将从底层开始实现一个完整的多线程Web服务器!
最后的附录内会包含一系列有关语言的实用参考资料。附录A会列举Rust中全部的关键字,附录B会列举Rust中所有的运算符及其他符号,附录C会包含标准库中提供的可派生trait,附录D会介绍一些有用的开发工具,附录E会解释Rust中的版本机制。
当然,不管你怎样阅读本书都是可以的。假如你想要跳过某个特定的章节,那就跳过吧,你可以在感到疑惑的时候再返回略过的那些部分。用你觉得最舒服的方式去阅读本书就好!
在学习Rust的过程中,掌握如何阅读编译器显示的错误提示信息是一项尤为重要的能力:它们能够引导你编写出可用的代码。为此,我们会故意提供许多无法通过编译的示例,进而展示相关情境下编译器输出的错误提示信息。所以,在本书中随意挑选出来的示例代码也许根本就无法通过编译!请仔细阅读上下文来确定你尝试运行的示例代码是否是一段故意写错的代码。在大部分情况下,我们会指引你将不能编译的代码纠正为正确版本。

目录

目 录
第1章 入门指南 1
安装 1
在Linux或macOS环境中安装Rust 2
在Windows环境中安装Rust 3
更新与卸载 4
常见问题 4
本地文档 4
Hello, World! 5
创建一个文件夹 5
编写并运行一个Rust程序 6
对这个程序的剖析 7
编译与运行是两个不同的步骤 8
Hello, Cargo! 10
使用Cargo创建一个项目 10
使用Cargo构建和运行项目 13
以Release模式进行构建 15
学会习惯Cargo 15
总结 16

第2章 编写一个猜数游戏 17
创建一个新的项目 18
处理一次猜测 19
使用变量来存储值 20
使用Result类型来处理可能失败的情况 22
通过println!中的占位符输出对应的值 24
尝试运行代码 24
生成一个保密数字 25
借助包来获得更多功能 25
生成一个随机数 28
比较猜测数字与保密数字 31
使用循环来实现多次猜测 35
在猜测成功时优雅地退出 37
处理非法输入 38
总结 40
第3章 通用编程概念 42
变量与可变性 43
变量与常量之间的不同 46
隐藏 47
数据类型 48
标量类型 49
复合类型 54
函数 58
函数参数 60
函数体中的语句和表达式 61
函数的返回值 63
注释 66
控制流 67
if表达式 67
使用循环重复执行代码 72
总结 78
第4章 认识所有权 79
什么是所有权 79
所有权规则 82
变量作用域 82
String类型 83
内存与分配 84
所有权与函数 91
返回值与作用域 92
引用与借用 94
可变引用 96
悬垂引用 99
引用的规则 101
切片 101
字符串切片 104
其他类型的切片 109
总结 109
第5章 使用结构体来组织相关联的数据 111
定义并实例化结构体 112
在变量名与字段名相同时使用简化版的字段初始化方法 114
使用结构体更新语法根据其他实例创建新实例 114
使用不需要对字段命名的元组结构体来创建不同的类型 115
没有任何字段的空结构体 116
一个使用结构体的示例程序 118
使用元组来重构代码 119
使用结构体来重构代码:增加有意义的描述信息 120
通过派生trait增加实用功能 121
方法 124
定义方法 124
带有更多参数的方法 127
关联函数 128
多个impl块 129
总结 129
第6章 枚举与模式匹配 130
定义枚举 131
枚举值 131
Option枚举及其在空值处理方面的优势 136
控制流运算符match 140
绑定值的模式 142
匹配Option 143
匹配必须穷举所有的可能 145
_通配符 146
简单控制流if let 146
总结 148
第7章 使用包、单元包及模块来管理日渐复杂的项目 150
包与单元包 152
通过定义模块来控制作用域及私有性 153
用于在模块树中指明条目的路径 156
使用pub关键字来暴露路径 159
使用super关键字开始构造相对路径 161
将结构体或枚举声明为公共的 162
用use关键字将路径导入作用域 165
创建use路径时的惯用模式 166
使用as关键字来提供新的名称 168
使用pub use重导出名称 169
使用外部包 170
使用嵌套的路径来清理众多use语句 171
通配符 172
将模块拆分为不同的文件 172
总结 174
第8章 通用集合类型 175
使用动态数组存储多个值 176
创建动态数组 176
更新动态数组 177
销毁动态数组时也会销毁其中的元素 177
读取动态数组中的元素 178
遍历动态数组中的值 181
使用枚举来存储多个类型的值 181
使用字符串存储UTF-8编码的文本 183
字符串是什么 183
创建一个新的字符串 184
更新字符串 185
字符串索引 188
字符串切片 191
遍历字符串的方法 192
字符串的确没那么简单 193
在哈希映射中存储键值对 193
创建一个新的哈希映射 194
哈希映射与所有权 195
访问哈希映射中的值 196
更新哈希映射 197
哈希函数 199
总结 200
第9章 错误处理 201
不可恢复错误与panic! 202
使用panic!产生的回溯信息 203
可恢复错误与Result 207
匹配不同的错误 210
失败时触发panic的快捷方式:unwrap和expect 212
传播错误 213
要不要使用panic! 219
示例、原型和测试 220
当你比编译器拥有更多信息时 220
错误处理的指导原则 221
创建自定义类型来进行有效性验证 222
总结 225
第10章 泛型、trait与生命周期 226
通过将代码提取为函数来减少重复工作 227
泛型数据类型 230
在函数定义中 230
在结构体定义中 234
在枚举定义中 236
在方法定义中 237
泛型代码的性能问题 239
trait:定义共享行为 241
定义trait 241
为类型实现trait 242
默认实现 245
使用trait作为参数 247
返回实现了trait的类型 249
使用trait约束来修复largest函数 251
使用trait约束来有条件地实现方法 254
使用生命周期保证引用的有效性 256
使用生命周期来避免悬垂引用 256
借用检查器 257
函数中的泛型生命周期 259
生命周期标注语法 260
函数签名中的生命周期标注 261
深入理解生命周期 264
结构体定义中的生命周期标注 266
生命周期省略 267
方法定义中的生命周期标注 270
静态生命周期 271
同时使用泛型参数、trait约束与生命周期 272
总结 273
第11章 编写自动化测试 274
如何编写测试 275
测试函数的构成 275
使用assert!宏检查结果 280
使用assert_eq!宏和assert_ne!宏判断相等性 284
添加自定义的错误提示信息 287
使用should_panic检查panic 289
使用Result编写测试 294
控制测试的运行方式 295
并行或串行地进行测试 296
显示函数输出 296
只运行部分特定名称的测试 299
通过显式指定来忽略某些测试 301
测试的组织结构 303
单元测试 303
集成测试 305
总结 311
第12章 I/O项目:编写一个命令行程序 312
接收命令行参数 313
读取参数值 314
将参数值存入变量 316
读取文件 317
重构代码以增强模块化程度和错误处理能力 319
二进制项目的关注点分离 320
修复错误处理逻辑 325
从main中分离逻辑 330
将代码分离为独立的代码包 333
使用测试驱动开发来编写库功能 335
编写一个会失败的测试 336
编写可以通过测试的代码 339
处理环境变量 343
为不区分大小写的search函数编写一个会失败的测试 343
实现search_case_insensitive函数 345

将错误提示信息打印到标准错误而不是标准输出 349
确认错误被写到了哪里 350
将错误提示信息打印到标准错误 351
总结 352
第13章 函数式语言特性:迭代器与闭包 353
闭包:能够捕获环境的匿名函数 354
使用闭包来创建抽象化的程序行为 354
闭包的类型推断和类型标注 361
使用泛型参数和Fn trait来存储闭包 363
Cacher实现的局限性 367
使用闭包捕获上下文环境 368
使用迭代器处理元素序列 371
Iterator trait和next方法 373
消耗迭代器的方法 374
生成其他迭代器的方法 375
使用闭包捕获环境 376
使用Iterator trait来创建自定义迭代器 378
改进I/O项目 381
使用迭代器代替clone 381
使用迭代器适配器让代码更加清晰 385
比较循环和迭代器的性能 386
总结 388
第14章 进一步认识Cargo及crates.io 390
使用发布配置来定制构建 391
将包发布到crates.io上 392
编写有用的文档注释 393
使用pub use来导出合适的公共API 397
创建crates.io账户 401
为包添加元数据 401
发布到crates.io 403
发布已有包的新版本 404
使用cargo yank命令从cargo.io上移除版本 404
Cargo工作空间 405
创建工作空间 405
在工作空间中创建第二个包 407
使用cargo install从crates.io上安装可执行程序 413
使用自定义命令扩展Cargo的功能 414
总结 414
第15章 智能指针 415
使用Box在堆上分配数据 417
使用Box在堆上存储数据 417
使用装箱定义递归类型 418
通过Deref trait将智能指针视作常规引用 423
使用解引用运算符跳转到指针指向的值 424
把Box当成引用来操作 425
定义我们自己的智能指针 426
通过实现Deref trait来将类型视作引用 427
函数和方法的隐式解引用转换 428
解引用转换与可变性 430
借助Drop trait在清理时运行代码 431
使用std::mem::drop提前丢弃值 433
基于引用计数的智能指针Rc 435
使用Rc共享数据 436
克隆Rc会增加引用计数 439
RefCell和内部可变性模式 440
使用RefCell在运行时检查借用规则 441
内部可变性:可变地借用一个不可变的值 442
将Rc和RefCell结合使用来实现一个拥有多重所有权的可变数据 450
循环引用会造成内存泄漏 452
创建循环引用 453
使用Weak代替Rc来避免循环引用 456
总结 463

第16章 无畏并发 464
使用线程同时运行代码 466
使用spawn创建新线程 467
使用join句柄等待所有线程结束 469
在线程中使用move闭包 471
使用消息传递在线程间转移数据 475
通道和所有权转移 478
发送多个值并观察接收者的等待过程 480
通过克隆发送者创建多个生产者 481
共享状态的并发 483
互斥体一次只允许一个线程访问数据 484
RefCell/Rc和Mutex/Arc之间的相似性 493
使用Sync trait和Send trait对并发进行扩展 494
允许线程间转移所有权的Send trait 494
允许多线程同时访问的Sync trait 495
手动实现Send和Sync是不安全的 495
总结 495
第17章 Rust的面向对象编程特性 497
面向对象语言的特性 497
对象包含数据和行为 498
封装实现细节 498
作为类型系统和代码共享机制的继承 500
使用trait对象来存储不同类型的值 502
为共有行为定义一个trait 503
实现trait 505
trait对象会执行动态派发 509
trait对象必须保证对象安全 510
实现一种面向对象的设计模式 511
定义Post并新建一个处于草稿状态下的新实例 513
存储文章内容的文本 514
确保草稿的可读内容为空 515
请求审批文章并改变其状态 516
添加approve方法来改变content的行为 518
状态模式的权衡取舍 521
总结 527
第18章 模式匹配 529
所有可以使用模式的场合 530
match分支 530
if let条件表达式 531
while let条件循环 533
for循环 533
let语句 534
函数的参数 536
可失败性:模式是否会匹配失败 537
模式语法 539
匹配字面量 539
匹配命名变量 540
多重模式 541
使用...来匹配值区间 542
使用解构来分解值 543
忽略模式中的值 548
使用匹配守卫添加额外条件 554
@绑定 556
总结 557
第19章 高级特性 559
不安全Rust 560
不安全超能力 561
解引用裸指针 562
调用不安全函数或方法 564
访问或修改一个可变静态变量 570
实现不安全trait 572
使用不安全代码的时机 573

高级trait 573
在trait的定义中使用关联类型指定占位类型 573
默认泛型参数和运算符重载 575
用于消除歧义的完全限定语法:调用相同名称的方法 578
用于在trait中附带另外一个trait功能的超trait 582
使用newtype模式在外部类型上实现外部trait 585
高级类型 586
使用newtype模式实现类型安全与抽象 587
使用类型别名创建同义类型 587
永不返回的Never类型 590
动态大小类型和Sized trait 593
高级函数与闭包 595
函数指针 595
返回闭包 598
宏 599
宏与函数之间的差别 599
用于通用元编程的macro_rules!声明宏 600
基于属性创建代码的过程宏 603
如何编写一个自定义derive宏 604
属性宏 611
函数宏 611
总结 612
第20章 最后的项目:构建多线程Web服务器 613
构建单线程Web服务器 614
监听TCP连接 615
读取请求 617
仔细观察HTTP请求 620
编写响应 621
返回真正的HTML 622
验证请求有效性并选择性地响应 624
少许重构 626

把单线程服务器修改为多线程服务器 628
在现有的服务器实现中模拟一个慢请求 628
使用线程池改进吞吐量 629
优雅地停机与清理 652
为ThreadPool实现Drop trait 652
通知线程停止监听任务 655
总结 661
附录A 关键字 662
当前正在使用的关键字 662
将来可能会使用的保留关键字 664
原始标识符 665
附录B 运算符和符号 667
运算符 667
非运算符符号 669
附录C 可派生trait 673
面向程序员格式化输出的Debug 674
用于相等性比较的PartialEq和Eq 675
使用PartialOrd和Ord进行次序比较 675
使用Clone和Copy复制值 676
用于将值映射到另外一个长度固定的值的Hash 677
用于提供默认值的Default 678
附录D 有用的开发工具 679
使用rustfmt自动格式化代码 679
使用rustfix修复代码 680
使用Clippy完成更多的代码分析 681
使用Rust语言服务器来集成IDE 683
附录E 版本 684

本书勘误

印次
  • 页码:605  •  行数:倒数第4行  •  印次: 1

    由于这两个包紧密相关,所以我们将它们放置到了同一目录中。
    应该改为:
    由于这两个包紧密相关,所以我们在hello_macro包的目录中(hello_macro目录)创建了过程宏的包。

    红枣核桃 提交于 2020/6/11 10:41:14
    刘恩惠 确认于 2020/7/1 9:15:04

读者评论

  • 请问代码在哪下载?

    rocky_liyang发表于 2022/11/2 20:05:51
  • 这本书的代码能在哪找到

    SkyWaiting发表于 2020/7/20 16:17:19

推荐用户