# 《Rust編程之道》學習筆記一 ## 序 ### Rust語言的主要特點 - 系統級語言 - 無GC - 基於LLVM - 記憶體安全 - 強類型+靜態類型 - 混合編程範式 - 零成本抽象 - 線程安全 ### 程式員的快樂 何謂快樂?真正的快樂不僅僅是寫代碼時的“酸爽”,更應該是代碼部署到生產 ...
《Rust編程之道》學習筆記一
序
Rust語言的主要特點
- 系統級語言
- 無GC
- 基於LLVM
- 記憶體安全
- 強類型+靜態類型
- 混合編程範式
- 零成本抽象
- 線程安全
程式員的快樂
何謂快樂?真正的快樂不僅僅是寫代碼時的“酸爽”,更應該是代碼部署到生產環境之後的“安穩”。
程式的三大定律
- 程式必須正確
- 程式必須可維護,但不能違反第一條定律
- 程式必須高效,但不能違反前兩條定律
程式的正確性
- 程式滿足了實際的問題需求
- 滿足了自身的程式規約
如何保證程式的正確性
- 通過對程式的各種測試、斷言和錯誤處理機制,來保證其滿足實際的問題需求。
- 通過較為成熟的類型理論,來保證程式自身的規約正確。
Rust語言對程式的三定律支持的恰到好處。
目前Rust被陸續應用在區塊鏈、游戲、WebAssembly 技術、機器學習,分散式資料庫、網路服務基礎設施、Web框架、操作系統和嵌入式等領域。
前言
Rust 學習曲線陡的根本原因在於 Rust 語言融合了多種語言特性和多種編程範式。
從Rust 的設計哲學出發,牢牢把握它的設計一致性,就可以把它的所有特性都串起來,從而達到掌握它的目的。
《Rust 編程之道》特點
- 從設計哲學出發,探索 Rust 語言的內在一致性。
- 設計哲學是一門優秀編程語言報錯語言一致性的關鍵所在。
- 設計哲學是語言特性和語法要素設計的誘因和準則。
- 從源碼分析入手,探索 Rust 地道的編程風格。
- 從工程角度著手,探索 Rust 對健壯性的支持。
- 從底層原理開始,探索 Rust 記憶體安全的本質。
章節概述
第一章 新時代的語言
第二章 語言精要
第三章 類型系統
第四章 記憶體管理
第五章 所有權系統
第六章 函數、閉包和迭代器
第七章 結構化編程
第八章 字元串與集合類型
第九章 構建健壯的程式
第十章 模塊化編程
第十一章 安全併發
第十二章 元編程
第十三章 超越安全的邊界
第 1 章 新時代的語言
不謀全局者,不足謀一域。
一門好的語言是有內涵哲學的語言,它表裡如一,有所想,有所為。
兩個難題
- 很難編寫記憶體安全的代碼。
- 很難編寫線程安全的代碼。
Ada 語言
2006 年,自稱 “職業編程語言工程師” 的 Graydon Hoare(簡稱為 GH),開始開發一門名為 Rust 的編程語言。
什麼是 “職業編程語言工程師”?用 GH 自己的話說,職業編程語言工程師的日常工作就是給其他語言開發編譯器和工具集,但並未參與這些語言本身的設計。
GH 對 Rust 語言的期望
- 必須是更加安全、不易崩潰的,尤其在操作記憶體時,這一點更為重要。
- 不需要有垃圾回收這樣的系統,不能為了記憶體安全而引入性能負擔。
- 不是一門僅僅擁有一個主要特性的語言,而應該擁有一系列的廣泛特性,這些特性之間又不乏一致性。這些特性可以很好地相互協作,從而使該語言更容易編寫、維護和調試,讓程式員寫出更安全、更高效的代碼。
Rust 是一門同時追求安全、併發和性能的現代系統級編程語言。
設計哲學
- 記憶體安全
- 零成本抽象
- 實用性
有些事現在不做,一輩子都沒機會再做了。 -- 練習曲[2006]
“程式即類型證明”
類型系統的好處
- 允許編譯器偵測無意義甚至無效的代碼,暴露程式中隱含的錯誤。
- 可以為編譯器提供有意義的類型信息,幫助優化代碼。
- 可以增強代碼的可讀性,更直白地闡述開發者的意圖。
- 提供了一定程度的高級抽象,提升開發效率。
簡單來說,類型安全是指類型系統可以保證程式的行為是意義明確、不出錯的。
未定義行為(Undefined Behavior):發生了語言規範規定之外的行為。
Rust語言如果想保證記憶體安全,首先要做的就是保證類型安全。
類型安全的語言:OCaml、Haskell
類型系統的作用是定義編程語言中值和表達式的類型,將它們歸類,賦予它們不同的行為,指導它們如何相互作用。
記憶體安全
什麼是記憶體安全?簡單來說,就是不會出現記憶體訪問錯誤。
只有當程式訪問未定義記憶體的時候才會產生記憶體錯誤。
一般來說,發生以下幾種情況就會產生記憶體錯誤:
- 引用空指針
- 使用未初始化記憶體
- 釋放後使用,也就是使用懸垂指針
- 緩衝區溢出,比如數組越界
- 非法釋放已經釋放過的指針或未分配的指針,也就是重覆釋放
Rust 語言安全記憶體管理模型
- 所有權系統
- 每個被分配的記憶體都有一個獨占其所有權的指針
- 只有當該指針被銷毀時,其對應的記憶體才能隨之被釋放
- RAII 機制
- 借用和生命周期
- 每個變數都有其生命周期,一旦超出生命周期,變數就會被自動釋放
- 如果是借用,則可以通過標記生命周期參數供編譯器檢查的方式,防止出現懸垂指針,也就是釋放後使用的情況。
Rust 從 Haskell 的類型系統借鑒了以下特性:
- 沒有空指針
- 預設不可變
- 表達式
- 高階函數
- 代數數據類型
- 模式匹配
- 泛型
- Trait 和關聯類型
- 本地類型推導
Rust 獨有的特性
- 仿射類型(Affine Type),該類型用來表達 Rust所有權中的 Move 語義
- 借用、生命周期
Rust 編譯器可以在編譯期對類型進行檢查,看其是否滿足安全記憶體模型,在編譯器就能發現記憶體不安全問題,有效地阻止未定義行為的發生。
Rust 編譯器會通過靜態檢查分析,在編譯器就檢查出多線程併發代碼中所有的數據競爭問題。
零成本抽象
Rust 的抽象並不會存在運行時性能開銷,這一切都是在編譯期完成的。
Rust 中零成本抽象的基石就是泛型和Trait。
實用性
如何評價一門編程語言的實用性?
- 實踐性
- 有益性
- 穩定性
日常開發中一般有三類非正常情況:失敗、錯誤和異常。
Rust 語言針對這三類非正常情況分別提供了專門的處理方式,讓開發者可以分情況去選擇。
- 對於失敗的情況,可以使用斷言工具。
- 對於錯誤,Rust 提供了基於返回值的分層錯誤處理方式,比如 Option
可以用來處理可能存在空值的情況,而 Result 就專門用來處理可以被合理解決並需要傳播的錯誤。 - 對於異常,Rust 將其看作無法被合理解決的問題,提供了線程恐慌機制,在發生異常的時候,線程可以安全地退出。
Safe Rust 表示開發者將信任編譯器能夠在編譯時保證安全,而 Unsafe Rust 表示讓編譯器信任開發者有能力保證安全。
Rust 代碼是以包(crate)為編譯和分發單位的
學習Rust
- 保持初學者心態
- 先學習概念再動手實踐
- 把編譯器當作朋友
2015年,Rust發佈1.0版本
2018年,Rust團隊推出了新的大版本(edition)計劃
Rust 2015 版本
Rust 2018 版本
Rust 2021 版本
Rust的編譯器可以方便地管理版本的相容性
Rust 團隊維護三個發行分支:穩定版(Stable)、測試版(Beta)和開發版(Nightly)。
其中穩定版和測試版每6周發佈一次。
標記為不穩定(Unstable)和特性開關(Feature Gate)的語言特性或標準庫特性只能在開發版中使用。
Rust 編譯器是一個編譯前端,它的工作是對代碼進行詞法分析、語法分析、類型檢查、生成中間代碼、進行獨立於目標機器的優化等工作。
使用 LLVM 作為編譯器後端代碼生成框架,則可以利用 LLVM 相容多個目標機器的特性,實現跨平臺編譯和優化等工作。
在用戶使用Rust時,大多數時候無須考慮各個目標機器平臺的特有性質,基本上可以做到一次編寫,到處運行。
Rust 源碼經過分詞和解析,生成AST(抽象語法樹)。
然後把 AST 進一步簡化處理為 HIR(High-level IR),目的是讓編譯器更方便地做類型檢查。
HIR 會進一步被編譯為 MIR(Middle IR),這是一種中間表示。
最終,MIR 會被翻譯為 LLVM IR,然後被 LLVM 的處理編譯為能在各個平臺上運行的目標機器碼。
本文來自博客園,作者:尋月隱君,轉載請註明原文鏈接:https://www.cnblogs.com/QiaoPengjun/p/17625003.html