Rust 權威指南 (The Rust Programming Language (Covers Rust 2018))

Steve Klabnik , Carol Nichols 毛靖凱 唐剛 沙渺

買這商品的人也買了...

商品描述

本書由Rust核心開發團隊編寫而成,由淺入深地探討了Rust語言的方方面面。
從學習函數、選擇數據結構及綁定變量入手,逐步介紹所有權、trait、
生命週期、安全保證等高級概念,模式匹配、錯誤處理、包管理、
函數式特性、並發機制等實用工具,以及兩個完整的項目開發實戰案例。
作為開源的系統級編程語言,Rust可以幫助你編寫出更為快速且更為可靠的軟件,
在給予開發者底層控制能力的同時,通過深思熟慮的工程設計避免了傳統語言帶來的諸多麻煩。
本書被視為Rust開發工作的必讀書目,適合所有希望評估、
入門、提高和研究Rust語言的軟件開發人員閱讀。

作者簡介

Steve Klabnik

Rust文檔團隊負責人,Rust核心開發者之一,
Rust佈道者及高產的開源貢獻者,此前致力於Ruby等項目的開發。

Carol Nichols

Rust核心團隊成員,i32、LLC聯合構建者,Rust Belt Rust會議組織者。


毛靖凱

遊戲設計師,一直專注於遊戲領域研發,曾負責設計和維護了多個商業遊戲的基礎框架。
業餘時間活躍於Rust開源社區,並嘗試使用Rust來解決遊戲領域中的諸多問題。


唐剛

資深開發者,Rustcc社區創始人和維護者之一。
目前就職於Cdot Network。使用Rust從事區塊鏈共識協議的開發工作。

沙渺

嵌入式開發者,國內Rust語言社區和Raspberry Pi(樹莓派)開發社區早期參與者。
負責維護多個RISC-V架構硬件平台的基礎函數庫。

目錄大綱

目錄
第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<T> 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<T, E>編寫測試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<T>在堆上分配數據417
使用Box<T>在堆上存儲數據417
使用裝箱定義遞歸類型418
通過Deref trait將智能指針視作常規引用423
使用解引用運算符跳轉到指針指向的值424
把Box<T>當成引用來操作425
定義我們自己的智能指針426
通過實現Deref trait來將類型視作引用427
函數和方法的隱式解引用轉換428
解引用轉換與可變性430
借助Drop trait在清理時運行代碼431
使用std::mem::drop提前丟棄值433
基於引用計數的智能指針Rc<T> 435
使用Rc<T>共享數據436
克隆Rc<T>會增加引用計數439
RefCell<T>和內部可變性模式440
使用RefCell<T>在運行時檢查借用規則441
內部可變性:可變地借用一個不可變的值442
將Rc<T>和RefCell<T>結合使用來實現一個擁有多重所有權的可變數據450
循環引用會造成內存洩漏452
創建循環引用453
使用Weak<T>代替Rc<T>來避免循環引用456
總結463

第16章無畏並發464
使用線程同時運行代碼466
使用spawn創建新線程467
使用join句柄等待所有線程結束469
在線程中使用move閉包471
使用消息傳遞在線程間轉移數據475
通道和所有權轉移478
發送多個值並觀察接收者的等待過程480
通過克隆發送者創建多個生產者481
共享狀態的並發483
互斥體一次只允許一個線程訪問數據484
RefCell<T>/Rc< T>和Mutex<T>/Arc<T>之間的相似性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