本書由Rust核心開發(fā)團(tuán)隊(duì)編寫而成,由淺入深地探討了Rust語言的方方面面。從學(xué)習(xí)函數(shù)、選擇數(shù)據(jù)結(jié)構(gòu)及綁定變量入手,逐步介紹所有權(quán)、trait、生命周期、安全保證等高級(jí)概念,模式匹配、錯(cuò)誤處理、包管理、函數(shù)式特性、并發(fā)機(jī)制等實(shí)用工具,以及兩個(gè)完整的項(xiàng)目開發(fā)實(shí)戰(zhàn)案例。 作為開源的系統(tǒng)級(jí)編程語言,Rust可以幫助你編寫出更為快速且更為可靠的軟件,在給予開發(fā)者底層控制能力的同時(shí),通過深思熟慮的工程設(shè)計(jì)避免了傳統(tǒng)語言帶來的諸多麻煩。 本書被視為Rust開發(fā)工作的必讀書目,適合所有希望評(píng)估、入門、提高和研究Rust語言的軟件開發(fā)人員閱讀。
Steve Klabnik,Rust文檔團(tuán)隊(duì)負(fù)責(zé)人,Rust核心開發(fā)者之一,Rust布道者及高產(chǎn)的開源貢獻(xiàn)者,此前致力于Ruby等項(xiàng)目的開發(fā)。Carol Nichols,Rust核心團(tuán)隊(duì)成員,i32、LLC聯(lián)合構(gòu)建者,Rust Belt Rust會(huì)議組織者。
毛靖凱,游戲設(shè)計(jì)師,一直專注于游戲領(lǐng)域研發(fā),曾負(fù)責(zé)設(shè)計(jì)和維護(hù)了多個(gè)商業(yè)游戲的基礎(chǔ)框架。業(yè)余時(shí)間活躍于Rust開源社區(qū),并嘗試使用Rust來解決游戲領(lǐng)域中的諸多問題。唐剛,資深開發(fā)者,Rustcc社區(qū)創(chuàng)始人和維護(hù)者之一。目前就職于Cdot Network。使用Rust從事區(qū)塊鏈共識(shí)協(xié)議的開發(fā)工作。沙渺,嵌入式開發(fā)者,國內(nèi)Rust語言社區(qū)和Raspberry Pi(樹莓派)開發(fā)社區(qū)早期參與者。負(fù)責(zé)維護(hù)多個(gè)RISC-V架構(gòu)硬件平臺(tái)的基礎(chǔ)函數(shù)庫。
目 錄
第1章 入門指南 1
安裝 1
在Linux或macOS環(huán)境中安裝Rust 2
在Windows環(huán)境中安裝Rust 3
更新與卸載 4
常見問題 4
本地文檔 4
Hello, World! 5
創(chuàng)建一個(gè)文件夾 5
編寫并運(yùn)行一個(gè)Rust程序 6
對(duì)這個(gè)程序的剖析 7
編譯與運(yùn)行是兩個(gè)不同的步驟 8
Hello, Cargo! 10
使用Cargo創(chuàng)建一個(gè)項(xiàng)目 10
使用Cargo構(gòu)建和運(yùn)行項(xiàng)目 13
以Release模式進(jìn)行構(gòu)建 15
學(xué)會(huì)習(xí)慣Cargo 15
總結(jié) 16
第2章 編寫一個(gè)猜數(shù)游戲 17
創(chuàng)建一個(gè)新的項(xiàng)目 18
處理一次猜測 19
使用變量來存儲(chǔ)值 20
使用Result類型來處理可能失敗的情況 22
通過println!中的占位符輸出對(duì)應(yīng)的值 24
嘗試運(yùn)行代碼 24
生成一個(gè)保密數(shù)字 25
借助包來獲得更多功能 25
生成一個(gè)隨機(jī)數(shù) 28
比較猜測數(shù)字與保密數(shù)字 31
使用循環(huán)來實(shí)現(xiàn)多次猜測 35
在猜測成功時(shí)優(yōu)雅地退出 37
處理非法輸入 38
總結(jié) 40
第3章 通用編程概念 42
變量與可變性 43
變量與常量之間的不同 46
隱藏 47
數(shù)據(jù)類型 48
標(biāo)量類型 49
復(fù)合類型 54
函數(shù) 58
函數(shù)參數(shù) 60
函數(shù)體中的語句和表達(dá)式 61
函數(shù)的返回值 63
注釋 66
控制流 67
if表達(dá)式 67
使用循環(huán)重復(fù)執(zhí)行代碼 72
總結(jié) 78
第4章 認(rèn)識(shí)所有權(quán) 79
什么是所有權(quán) 79
所有權(quán)規(guī)則 82
變量作用域 82
String類型 83
內(nèi)存與分配 84
所有權(quán)與函數(shù) 91
返回值與作用域 92
引用與借用 94
可變引用 96
懸垂引用 99
引用的規(guī)則 101
切片 101
字符串切片 104
其他類型的切片 109
總結(jié) 109
第5章 使用結(jié)構(gòu)體來組織相關(guān)聯(lián)的數(shù)據(jù) 111
定義并實(shí)例化結(jié)構(gòu)體 112
在變量名與字段名相同時(shí)使用簡化版的字段初始化方法 114
使用結(jié)構(gòu)體更新語法根據(jù)其他實(shí)例創(chuàng)建新實(shí)例 114
使用不需要對(duì)字段命名的元組結(jié)構(gòu)體來創(chuàng)建不同的類型 115
沒有任何字段的空結(jié)構(gòu)體 116
一個(gè)使用結(jié)構(gòu)體的示例程序 118
使用元組來重構(gòu)代碼 119
使用結(jié)構(gòu)體來重構(gòu)代碼:增加有意義的描述信息 120
通過派生trait增加實(shí)用功能 121
方法 124
定義方法 124
帶有更多參數(shù)的方法 127
關(guān)聯(lián)函數(shù) 128
多個(gè)impl塊 129
總結(jié) 129
第6章 枚舉與模式匹配 130
定義枚舉 131
枚舉值 131
Option枚舉及其在空值處理方面的優(yōu)勢 136
控制流運(yùn)算符match 140
綁定值的模式 142
匹配Option<T> 143
匹配必須窮舉所有的可能 145
_通配符 146
簡單控制流if let 146
總結(jié) 148
第7章 使用包、單元包及模塊來管理日漸復(fù)雜的項(xiàng)目 150
包與單元包 152
通過定義模塊來控制作用域及私有性 153
用于在模塊樹中指明條目的路徑 156
使用pub關(guān)鍵字來暴露路徑 159
使用super關(guān)鍵字開始構(gòu)造相對(duì)路徑 161
將結(jié)構(gòu)體或枚舉聲明為公共的 162
用use關(guān)鍵字將路徑導(dǎo)入作用域 165
創(chuàng)建use路徑時(shí)的慣用模式 166
使用as關(guān)鍵字來提供新的名稱 168
使用pub use重導(dǎo)出名稱 169
使用外部包 170
使用嵌套的路徑來清理眾多use語句 171
通配符 172
將模塊拆分為不同的文件 172
總結(jié) 174
第8章 通用集合類型 175
使用動(dòng)態(tài)數(shù)組存儲(chǔ)多個(gè)值 176
創(chuàng)建動(dòng)態(tài)數(shù)組 176
更新動(dòng)態(tài)數(shù)組 177
銷毀動(dòng)態(tài)數(shù)組時(shí)也會(huì)銷毀其中的元素 177
讀取動(dòng)態(tài)數(shù)組中的元素 178
遍歷動(dòng)態(tài)數(shù)組中的值 181
使用枚舉來存儲(chǔ)多個(gè)類型的值 181
使用字符串存儲(chǔ)UTF-8編碼的文本 183
字符串是什么 183
創(chuàng)建一個(gè)新的字符串 184
更新字符串 185
字符串索引 188
字符串切片 191
遍歷字符串的方法 192
字符串的確沒那么簡單 193
在哈希映射中存儲(chǔ)鍵值對(duì) 193
創(chuàng)建一個(gè)新的哈希映射 194
哈希映射與所有權(quán) 195
訪問哈希映射中的值 196
更新哈希映射 197
哈希函數(shù) 199
總結(jié) 200
第9章 錯(cuò)誤處理 201
不可恢復(fù)錯(cuò)誤與panic! 202
使用panic!產(chǎn)生的回溯信息 203
可恢復(fù)錯(cuò)誤與Result 207
匹配不同的錯(cuò)誤 210
失敗時(shí)觸發(fā)panic的快捷方式:unwrap和expect 212
傳播錯(cuò)誤 213
要不要使用panic! 219
示例、原型和測試 220
當(dāng)你比編譯器擁有更多信息時(shí) 220
錯(cuò)誤處理的指導(dǎo)原則 221
創(chuàng)建自定義類型來進(jìn)行有效性驗(yàn)證 222
總結(jié) 225
第10章 泛型、trait與生命周期 226
通過將代碼提取為函數(shù)來減少重復(fù)工作 227
泛型數(shù)據(jù)類型 230
在函數(shù)定義中 230
在結(jié)構(gòu)體定義中 234
在枚舉定義中 236
在方法定義中 237
泛型代碼的性能問題 239
trait:定義共享行為 241
定義trait 241
為類型實(shí)現(xiàn)trait 242
默認(rèn)實(shí)現(xiàn) 245
使用trait作為參數(shù) 247
返回實(shí)現(xiàn)了trait的類型 249
使用trait約束來修復(fù)largest函數(shù) 251
使用trait約束來有條件地實(shí)現(xiàn)方法 254
使用生命周期保證引用的有效性 256
使用生命周期來避免懸垂引用 256
借用檢查器 257
函數(shù)中的泛型生命周期 259
生命周期標(biāo)注語法 260
函數(shù)簽名中的生命周期標(biāo)注 261
深入理解生命周期 264
結(jié)構(gòu)體定義中的生命周期標(biāo)注 266
生命周期省略 267
方法定義中的生命周期標(biāo)注 270
靜態(tài)生命周期 271
同時(shí)使用泛型參數(shù)、trait約束與生命周期 272
總結(jié) 273
第11章 編寫自動(dòng)化測試 274
如何編寫測試 275
測試函數(shù)的構(gòu)成 275
使用assert!宏檢查結(jié)果 280
使用assert_eq!宏和assert_ne!宏判斷相等性 284
添加自定義的錯(cuò)誤提示信息 287
使用should_panic檢查panic 289
使用Result<T, E>編寫測試 294
控制測試的運(yùn)行方式 295
并行或串行地進(jìn)行測試 296
顯示函數(shù)輸出 296
只運(yùn)行部分特定名稱的測試 299
通過顯式指定來忽略某些測試 301
測試的組織結(jié)構(gòu) 303
單元測試 303
集成測試 305
總結(jié) 311
第12章 I/O項(xiàng)目:編寫一個(gè)命令行程序 312
接收命令行參數(shù) 313
讀取參數(shù)值 314
將參數(shù)值存入變量 316
讀取文件 317
重構(gòu)代碼以增強(qiáng)模塊化程度和錯(cuò)誤處理能力 319
二進(jìn)制項(xiàng)目的關(guān)注點(diǎn)分離 320
修復(fù)錯(cuò)誤處理邏輯 325
從main中分離邏輯 330
將代碼分離為獨(dú)立的代碼包 333
使用測試驅(qū)動(dòng)開發(fā)來編寫庫功能 335
編寫一個(gè)會(huì)失敗的測試 336
編寫可以通過測試的代碼 339
處理環(huán)境變量 343
為不區(qū)分大小寫的search函數(shù)編寫一個(gè)會(huì)失敗的測試 343
實(shí)現(xiàn)search_case_insensitive函數(shù) 345
將錯(cuò)誤提示信息打印到標(biāo)準(zhǔn)錯(cuò)誤而不是標(biāo)準(zhǔn)輸出 349
確認(rèn)錯(cuò)誤被寫到了哪里 350
將錯(cuò)誤提示信息打印到標(biāo)準(zhǔn)錯(cuò)誤 351
總結(jié) 352
第13章 函數(shù)式語言特性:迭代器與閉包 353
閉包:能夠捕獲環(huán)境的匿名函數(shù) 354
使用閉包來創(chuàng)建抽象化的程序行為 354
閉包的類型推斷和類型標(biāo)注 361
使用泛型參數(shù)和Fn trait來存儲(chǔ)閉包 363
Cacher實(shí)現(xiàn)的局限性 367
使用閉包捕獲上下文環(huán)境 368
使用迭代器處理元素序列 371
Iterator trait和next方法 373
消耗迭代器的方法 374
生成其他迭代器的方法 375
使用閉包捕獲環(huán)境 376
使用Iterator trait來創(chuàng)建自定義迭代器 378
改進(jìn)I/O項(xiàng)目 381
使用迭代器代替clone 381
使用迭代器適配器讓代碼更加清晰 385
比較循環(huán)和迭代器的性能 386
總結(jié) 388
第14章 進(jìn)一步認(rèn)識(shí)Cargo及crates.io 390
使用發(fā)布配置來定制構(gòu)建 391
將包發(fā)布到crates.io上 392
編寫有用的文檔注釋 393
使用pub use來導(dǎo)出合適的公共API 397
創(chuàng)建crates.io賬戶 401
為包添加元數(shù)據(jù) 401
發(fā)布到crates.io 403
發(fā)布已有包的新版本 404
使用cargo yank命令從cargo.io上移除版本 404
Cargo工作空間 405
創(chuàng)建工作空間 405
在工作空間中創(chuàng)建第二個(gè)包 407
使用cargo install從crates.io上安裝可執(zhí)行程序 413
使用自定義命令擴(kuò)展Cargo的功能 414
總結(jié) 414
第15章 智能指針 415
使用Box<T>在堆上分配數(shù)據(jù) 417
使用Box<T>在堆上存儲(chǔ)數(shù)據(jù) 417
使用裝箱定義遞歸類型 418
通過Deref trait將智能指針視作常規(guī)引用 423
使用解引用運(yùn)算符跳轉(zhuǎn)到指針指向的值 424
把Box<T>當(dāng)成引用來操作 425
定義我們自己的智能指針 426
通過實(shí)現(xiàn)Deref trait來將類型視作引用 427
函數(shù)和方法的隱式解引用轉(zhuǎn)換 428
解引用轉(zhuǎn)換與可變性 430
借助Drop trait在清理時(shí)運(yùn)行代碼 431
使用std::mem::drop提前丟棄值 433
基于引用計(jì)數(shù)的智能指針Rc<T> 435
使用Rc<T>共享數(shù)據(jù) 436
克隆Rc<T>會(huì)增加引用計(jì)數(shù) 439
RefCell<T>和內(nèi)部可變性模式 440
使用RefCell<T>在運(yùn)行時(shí)檢查借用規(guī)則 441
內(nèi)部可變性:可變地借用一個(gè)不可變的值 442
將Rc<T>和RefCell<T>結(jié)合使用來實(shí)現(xiàn)一個(gè)擁有多重所有權(quán)的可變數(shù)據(jù) 450
循環(huán)引用會(huì)造成內(nèi)存泄漏 452
創(chuàng)建循環(huán)引用 453
使用Weak<T>代替Rc<T>來避免循環(huán)引用 456
總結(jié) 463
第16章 無畏并發(fā) 464
使用線程同時(shí)運(yùn)行代碼 466
使用spawn創(chuàng)建新線程 467
使用join句柄等待所有線程結(jié)束 469
在線程中使用move閉包 471
使用消息傳遞在線程間轉(zhuǎn)移數(shù)據(jù) 475
通道和所有權(quán)轉(zhuǎn)移 478
發(fā)送多個(gè)值并觀察接收者的等待過程 480
通過克隆發(fā)送者創(chuàng)建多個(gè)生產(chǎn)者 481
共享狀態(tài)的并發(fā) 483
互斥體一次只允許一個(gè)線程訪問數(shù)據(jù) 484
RefCell<T>/Rc<T>和Mutex<T>/Arc<T>之間的相似性 493
使用Sync trait和Send trait對(duì)并發(fā)進(jìn)行擴(kuò)展 494
允許線程間轉(zhuǎn)移所有權(quán)的Send trait 494
允許多線程同時(shí)訪問的Sync trait 495
手動(dòng)實(shí)現(xiàn)Send和Sync是不安全的 495
總結(jié) 495
第17章 Rust的面向?qū)ο缶幊烫匦?497
面向?qū)ο笳Z言的特性 497
對(duì)象包含數(shù)據(jù)和行為 498
封裝實(shí)現(xiàn)細(xì)節(jié) 498
作為類型系統(tǒng)和代碼共享機(jī)制的繼承 500
使用trait對(duì)象來存儲(chǔ)不同類型的值 502
為共有行為定義一個(gè)trait 503
實(shí)現(xiàn)trait 505
trait對(duì)象會(huì)執(zhí)行動(dòng)態(tài)派發(fā) 509
trait對(duì)象必須保證對(duì)象安全 510
實(shí)現(xiàn)一種面向?qū)ο蟮脑O(shè)計(jì)模式 511
定義Post并新建一個(gè)處于草稿狀態(tài)下的新實(shí)例 513
存儲(chǔ)文章內(nèi)容的文本 514
確保草稿的可讀內(nèi)容為空 515
請(qǐng)求審批文章并改變其狀態(tài) 516
添加approve方法來改變content的行為 518
狀態(tài)模式的權(quán)衡取舍 521
總結(jié) 527
第18章 模式匹配 529
所有可以使用模式的場合 530
match分支 530
if let條件表達(dá)式 531
while let條件循環(huán) 533
for循環(huán) 533
let語句 534
函數(shù)的參數(shù) 536
可失敗性:模式是否會(huì)匹配失敗 537
模式語法 539
匹配字面量 539
匹配命名變量 540
多重模式 541
使用...來匹配值區(qū)間 542
使用解構(gòu)來分解值 543
忽略模式中的值 548
使用匹配守衛(wèi)添加額外條件 554
@綁定 556
總結(jié) 557
第19章 高級(jí)特性 559
不安全Rust 560
不安全超能力 561
解引用裸指針 562
調(diào)用不安全函數(shù)或方法 564
訪問或修改一個(gè)可變靜態(tài)變量 570
實(shí)現(xiàn)不安全trait 572
使用不安全代碼的時(shí)機(jī) 573
高級(jí)trait 573
在trait的定義中使用關(guān)聯(lián)類型指定占位類型 573
默認(rèn)泛型參數(shù)和運(yùn)算符重載 575
用于消除歧義的完全限定語法:調(diào)用相同名稱的方法 578
用于在trait中附帶另外一個(gè)trait功能的超trait 582
使用newtype模式在外部類型上實(shí)現(xiàn)外部trait 585
高級(jí)類型 586
使用newtype模式實(shí)現(xiàn)類型安全與抽象 587
使用類型別名創(chuàng)建同義類型 587
永不返回的Never類型 590
動(dòng)態(tài)大小類型和Sized trait 593
高級(jí)函數(shù)與閉包 595
函數(shù)指針 595
返回閉包 598
宏 599
宏與函數(shù)之間的差別 599
用于通用元編程的macro_rules!聲明宏 600
基于屬性創(chuàng)建代碼的過程宏 603
如何編寫一個(gè)自定義derive宏 604
屬性宏 611
函數(shù)宏 611
總結(jié) 612
第20章 最后的項(xiàng)目:構(gòu)建多線程Web服務(wù)器 613
構(gòu)建單線程Web服務(wù)器 614
監(jiān)聽TCP連接 615
讀取請(qǐng)求 617
仔細(xì)觀察HTTP請(qǐng)求 620
編寫響應(yīng) 621
返回真正的HTML 622
驗(yàn)證請(qǐng)求有效性并選擇性地響應(yīng) 624
少許重構(gòu) 626
把單線程服務(wù)器修改為多線程服務(wù)器 628
在現(xiàn)有的服務(wù)器實(shí)現(xiàn)中模擬一個(gè)慢請(qǐng)求 628
使用線程池改進(jìn)吞吐量 629
優(yōu)雅地停機(jī)與清理 652
為ThreadPool實(shí)現(xiàn)Drop trait 652
通知線程停止監(jiān)聽任務(wù) 655
總結(jié) 661
附錄A 關(guān)鍵字 662
當(dāng)前正在使用的關(guān)鍵字 662
將來可能會(huì)使用的保留關(guān)鍵字 664
原始標(biāo)識(shí)符 665
附錄B 運(yùn)算符和符號(hào) 667
運(yùn)算符 667
非運(yùn)算符符號(hào) 669
附錄C 可派生trait 673
面向程序員格式化輸出的Debug 674
用于相等性比較的PartialEq和Eq 675
使用PartialOrd和Ord進(jìn)行次序比較 675
使用Clone和Copy復(fù)制值 676
用于將值映射到另外一個(gè)長度固定的值的Hash 677
用于提供默認(rèn)值的Default 678
附錄D 有用的開發(fā)工具 679
使用rustfmt自動(dòng)格式化代碼 679
使用rustfix修復(fù)代碼 680
使用Clippy完成更多的代碼分析 681
使用Rust語言服務(wù)器來集成IDE 683
附錄E 版本 684