Rust 程式語言在設計上極度重視記憶體安全與併行處理能力,其獨特的變數管理哲學是實現此目標的基石。本文將從最基礎的程式結構出發,逐步解析 Rust 如何透過預設不可變性(Immutability)來強制開發者建立更穩固、可預測的程式碼。相較於傳統語言,Rust 要求開發者明確標示意圖,例如使用 mut 關鍵字宣告可變動的狀態,或是利用變數遮蔽(Shadowing)進行型別或數值的安全轉換。這些看似嚴格的規則,實則是 Rust 提供編譯時期保障、避免執行時期錯誤的核心機制,也是軟體工程師從傳統思維轉向現代系統程式設計的關鍵一步。
軟體工程師的進階修煉:從抽象化到實戰應用的全面提升
編寫你的第一個程式語言程式
現在你已經設定好程式語言並配置了你的開發環境,是時候編寫你的第一個程式語言程式了。像許多程式語言一樣,我們將從經典的「Hello, World!」範例開始。這看起來可能很簡單,但它是熟悉程式語言程式基本結構的絕佳方式。
理解 main 函式
在程式語言中,每個可執行程式都從一個名為 main 的特殊函式開始。這是你程式的進入點,也是執行開始的地方。如果你熟悉其他程式語言,這個概念應該不陌生。main 函式類似於 C/C++ 中的 int main() 或 Java 中的 public static void main()。
在程式語言中,定義 main 函式的語法很簡單:
fn main() {
// 程式碼將在此處執行
}
fn關鍵字是function的縮寫,用於宣告一個新函式。main是函式的名稱,在程式語言中,它必須始終命名為main作為進入點。- 大括號
{}定義了函式的主體,其中包含程式運行時執行的程式碼。
儘管 main 函式預設不返回任何值,但如果需要,你可以添加返回型別,不過對於簡單的程式,我們不需要擔心這個。
「Hello, World!」範例
現在讓我們從頭到尾走一遍編寫和運行這個程式的整個過程。
- 建立一個新的程式語言專案:
程式語言使用一個名為
Cargo的建構系統和套件管理器,它使得建立新專案、管理依賴項和建構程式變得非常容易。 開啟你的終端機,導航到你想要建立專案的目錄。然後,運行以下指令:
cargo new hello_world
這個指令將會建立一個名為 hello_world 的新目錄,其中已經設定好了一個基本的專案結構。在這個目錄內部,你會找到一個 src 資料夾,其中包含一個 main.rs 檔案。這是你的程式語言程式碼所在的地方。
2. 導航到你的專案目錄:
進入新建立的 hello_world 目錄:
cd hello_world
- 編寫程式碼:
在你的文字編輯器或 IDE 中開啟
main.rs檔案。你會看到Cargo已經為你生成了一個基本的main函式:
fn main() {
println!("Hello, world!");
}
這就是你的第一個程式語言程式!Cargo 已經將它設定為直接輸出「Hello, world!」。
4. 建構並運行你的程式:
要運行你的程式,請在終端機中使用 Cargo 的 run 指令:
cargo run
Cargo 會自動編譯你的程式碼,然後執行生成的執行檔。你將會在終端機中看到輸出:
Hello, world!
拆解「Hello, World!」範例
儘管「Hello, world!」看起來是一個微不足道的範例,但它引入了程式語言中的幾個重要概念:
fn關鍵字:這是你在程式語言中定義函式的方式。函式是程式語言程式的建構區塊,隨著我們探索這種語言,你會經常看到fn。main函式:這是你的程式語言程式的進入點。當你執行程式時,程式語言會尋找main函式並從那裡開始執行。- 巨集 (Macros):
println!巨集展示了程式語言如何處理像列印到控制台這樣的任務。程式語言巨集(由!標記)與函式略有不同,並提供更大的靈活性。我們稍後會更詳細地探討巨集,但目前你只需要知道println!是一種方便的列印文字方式。 Cargo:程式語言的建構系統和套件管理器。有了Cargo,你不必擔心手動編譯程式碼——它會為你處理一切,從建構程式到管理依賴項。
透過這個簡單的範例,你已經初次體驗了程式語言的語法、其強大的巨集系統,以及使用 Cargo 處理程式語言工具鏈的便捷性。隨著我們繼續前進,你將開始建構更複雜的程式並使用程式語言的核心功能,但請記住——每個大型專案都始於一小步,在這個案例中,就是「Hello, world!」。
第二章:基本概念
變數與可變性
程式語言,像許多程式語言一樣,使用變數來儲存資料值。然而,程式語言處理變數的方式在一個重要方面是獨特的:預設情況下,程式語言中的變數是不可變的 (immutable)。這意味著一旦你為變數賦值,你就不能更改該值,除非你明確地將變數宣告為可變的。讓我們探討這意味著什麼以及如何在程式語言中使用可變變數。
預設不可變:程式語言的設計哲學
程式語言中的變數預設是不可變的,除非你明確地將它們宣告為可變的。
不可變性是程式語言中的一個核心概念,因為它鼓勵更安全、更可預測的程式碼。當一個變數是不可變的時,你知道它的值在它被使用的範圍內不會改變,這使得推斷程式的行為變得更容易。
這是一個不可變變數的簡單範例:
fn main() {
let x = 5;
println!("x 的值是: {}", x);
// x = 6; // 這一行會導致編譯時期錯誤
}
let 關鍵字用於宣告一個新變數 x,其值為 5。如果你稍後嘗試更改 x 的值(如註釋掉的那一行所示),程式語言編譯器將會拋出錯誤,因為 x 是不可變的。
使用 mut 宣告可變變數
雖然不可變性是預設行為,但在許多情況下,你會希望變數的值在程式執行期間發生變化。要將變數宣告為可變的,你需要使用 mut 關鍵字。
讓我們修改前面的範例,使 x 變為可變:
fn main() {
let mut x = 5;
println!("x 的值是: {}", x);
x = 6; // 這可行,因為 x 是可變的
println!("x 現在的值是: {}", x);
}
透過添加 mut 關鍵字,我們使 x 變為可變。現在,賦值 x = 6 可以正常工作,程式將列印 x 的新值而不會產生任何錯誤。
當你將變數宣告為可變時,你是在告訴程式語言你打算更改它的值。這種明確性在防止意外修改方面大有幫助,使你的程式碼更安全且更容易理解。
變數遮蔽 (Shadowing Variables)
在程式語言中,變數遮蔽是一個強大的功能,它允許你在同一個作用域內宣告一個與先前變數同名的新變數。當你「遮蔽」一個變數時,新變數會有效地隱藏舊變數,任何對該變數名稱的引用現在都將指向新版本。這聽起來一開始可能有點令人困惑,但在實踐中它可能非常有用,特別是當你想要重複使用變數名稱同時轉換或精煉它們的值時。
讓我們透過一個範例來分解它:
fn main() {
let x = 5;
println!("x 的值是: {}", x); // 輸出: x 的值是: 5
let x = x + 1; // 遮蔽了之前的 x
println!("x 的值是: {}", x); // 輸出: x 的值是: 6
let x = x * 2; // 再次遮蔽
println!("x 的值是: {}", x); // 輸出: x 的值是: 12
}
- 我們首先宣告
x,其值為5。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "程式語言基本概念:變數與可變性" {
node "變數宣告" as VarDecl {
component "let 關鍵字" as LetKeyword
component "預設不可變" as ImmutableDefault
component "mut 關鍵字 (可變)" as MutKeyword
}
node "不可變性原則" as ImmutabilityPrinciple {
component "安全性提升" as SafetyImprovement
component "程式碼可預測性" as Predictability
component "編譯時期錯誤檢查" as CompileTimeCheck
}
node "可變性應用" as MutabilityApplication {
component "值變更需求" as ValueChangeNeed
component "明確宣告意圖" as ExplicitIntent
component "防止意外修改" as PreventAccidentalModification
}
node "變數遮蔽 (Shadowing)" as Shadowing {
component "相同作用域內重新宣告" as ReDeclareInScope
component "新變數隱藏舊變數" as NewHidesOld
component "轉換或精煉值" as TransformRefineValue
}
VarDecl --> ImmutabilityPrinciple : 基礎概念
VarDecl --> MutabilityApplication : 擴展應用
VarDecl --> Shadowing : 特殊宣告方式
LetKeyword --> ImmutableDefault : let 預設行為
MutKeyword --> MutabilityApplication : 啟用可變性
ImmutableDefault --> SafetyImprovement
ImmutableDefault --> Predictability
ImmutableDefault --> CompileTimeCheck
MutabilityApplication --> ValueChangeNeed
MutabilityApplication --> ExplicitIntent
MutabilityApplication --> PreventAccidentalModification
Shadowing --> ReDeclareInScope
Shadowing --> NewHidesOld
Shadowing --> TransformRefineValue
}
@enduml看圖說話:
此圖示闡釋了程式語言中變數與可變性的基本概念。核心在於變數宣告,它使用 let 關鍵字,並強調預設不可變的特性。若需變數可變,則需使用 mut 關鍵字。不可變性原則帶來安全性提升、程式碼可預測性和強大的編譯時期錯誤檢查。而可變性應用則滿足了值變更需求,透過明確宣告意圖來防止意外修改。此外,圖示還介紹了變數遮蔽 (Shadowing) 這一特殊機制,允許在相同作用域內重新宣告變數,使新變數隱藏舊變數,常應用於轉換或精煉值的場景。這些概念共同構成了程式語言獨特的變數管理哲學,旨在提供更安全、更清晰的程式設計體驗。
結論:
從內在修養到外在表現的全面檢視顯示,軟體工程師的進階修煉,不僅是學習新語法,更是心智模式的深刻重塑。Rust 的變數與可變性設計,正是此修煉的核心道場。與傳統語言的便利性相比,Rust 預設的不可變性看似增加了初期門檻,這恰恰是其價值所在:它強制開發者在每次賦值變更前進行「正念覺察」,將無意識的習慣轉化為有意識的決策。這個從「便利」到「嚴謹」的思維轉變,是突破資深工程師成長瓶頸的關鍵。
我們預見,隨著系統複雜度與安全性要求的日益提高,這種「安全優先」的設計哲學將從底層語言向上影響至應用架構與團隊協作模式。將不可變性、遮蔽等概念內化為編碼直覺,不僅是技術能力的提升,更是專業紀律與系統思維的深度整合。
玄貓認為,此修養路徑代表了未來高階軟體工程的主流方向,值得所有追求卓越的工程師提前養成。掌握它,意味著你選擇了用更高的內在標準,去建構更穩固的數位世界。