Rust 入門與環境設置 – 第一個 Rust 程式(Hello World)
簡介
在程式語言的學習旅程中,「Hello World」 幾乎是每位開發者的第一步。它不只是一行輸出文字的程式碼,更是驗證開發環境、熟悉編譯流程、了解語言基本語法的最佳切入點。對於 Rust 這樣主打安全、效能與現代化的系統程式語言而言,從「Hello World」開始,就能感受到編譯器的嚴謹檢查與 Cargo 生態系的便利。
本篇文章將帶領讀者 從安裝 Rust、建立專案、編寫 & 執行第一支程式,一步步說明每個關鍵概念,並提供實用範例、常見陷阱與最佳實踐,讓你在最短時間內掌握 Rust 的開發基礎,為之後的更複雜專案奠定穩固基礎。
核心概念
1. 安裝 Rust 與 Cargo
Rust 官方提供的安裝工具 rustup 同時會安裝 Cargo(Rust 的套件管理與建置工具)。在終端機執行以下指令即可完成安裝:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
安裝完成後,使用 rustc --version 與 cargo --version 確認版本資訊:
rustc 1.78.0 (9c6c0c8a8 2024-05-01)
cargo 1.78.0 (9c6c0c8a8 2024-05-01)
Tip:
rustup會自動管理工具鏈(stable、beta、nightly),建議先使用 stable 版,以確保相容性。
2. 建立第一個專案
使用 Cargo 建立一個新專案,指令如下:
cargo new hello_world --bin
cd hello_world
此指令會產生以下目錄結構:
hello_world/
├─ Cargo.toml # 專案的設定檔與相依性宣告
└─ src/
└─ main.rs # 程式入口點
Note:
--bin代表建立可執行檔(binary),若改為--lib則會產生函式庫(library)樣板。
3. 撰寫 main.rs
main.rs 是 Rust 程式的 入口函式,必須包含 fn main()。以下是最簡單的「Hello World」範例:
// src/main.rs
fn main() {
// 使用 println! 巨集輸出文字到標準輸出
println!("Hello, world!");
}
println!為 巨集(macro),在編譯期會展開成對應的程式碼,類似 C/C++ 的printf,但支援更安全的格式化。
4. 編譯與執行
使用 Cargo 直接編譯並執行:
cargo run
執行結果:
Compiling hello_world v0.1.0 (/path/to/hello_world)
Finished dev [unoptimized + debuginfo] target(s) in 0.56s
Running `target/debug/hello_world`
Hello, world!
重要:
cargo run會先執行 編譯,若程式已是最新則直接執行;這是開發階段最常使用的指令。
5. 格式化與風格檢查
Rust 社群強烈建議使用 rustfmt 來統一程式碼風格。安裝方式:
rustup component add rustfmt
格式化整個專案:
cargo fmt
此外,clippy 提供靜態分析與最佳實踐建議:
rustup component add clippy
cargo clippy -- -D warnings # 把警告視為錯誤,強制修正
6. 進階的輸出範例
以下示範 變數插值、多行字串 與 格式化參數,讓「Hello World」不再單調:
// src/main.rs
fn main() {
// 1. 基本插值
let name = "Rustacean";
println!("Hello, {}!", name); // => Hello, Rustacean!
// 2. 多行字串(raw string)避免跳脫字元
let multi = r#"
歡迎使用 Rust!
這裡是多行字串範例。
"#;
println!("{}", multi);
// 3. 數值格式化:十進位、十六進位、二進位
let num = 42;
println!("十進位: {}", num); // 42
println!("十六進位: {:x}", num); // 2a
println!("二進位: {:b}", num); // 101010
}
說明
r#"...#"為 raw string,不需要跳脫\n、\"等字元。{:x}、{:b}為 格式化參數,分別代表十六進位與二進位表示。
7. 常見錯誤示範
錯誤 1:忘記在 main 函式前加 fn
// 錯誤寫法
main() {
println!("Hello");
}
編譯器會回報:
error: expected identifier, found `(`
--> src/main.rs:1:5
|
1 | main() {
| ^^^ unexpected token
解決:正確寫法是 fn main() { ... }。
錯誤 2:使用未宣告的變數
fn main() {
println!("Value: {}", value);
}
編譯錯誤:
error[E0425]: cannot find value `value` in this scope
--> src/main.rs:2:30
|
2 | println!("Value: {}", value);
| ^^^^^ not found in this scope
解決:先宣告變數 let value = 10; 再使用。
錯誤 3:格式字串與參數數量不匹配
fn main() {
println!("{} {}", "only one");
}
編譯錯誤:
error: argument never used
--> src/main.rs:2:13
|
2 | println!("{} {}", "only one");
| ^^^^^^^^^^^^^^^^
解決:確保 {} 數量與提供的參數相同,或使用位置參數 println!("{0} {0}", "repeat");。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 建議的最佳實踐 |
|---|---|---|
| 忘記加分號 | Rust 在每條語句結尾需要 ;,缺少會導致編譯錯誤或意外的表達式返回值。 |
養成在每行結尾加分號的習慣,特別是 let、函式呼叫等。 |
使用 println! 前未匯入 std::fmt |
雖然大多數情況不需要手動匯入,但自訂格式化 trait 時必須。 | 在自訂結構實作 Display 前,先 use std::fmt;。 |
未使用 cargo fmt 統一風格 |
不同開發者的排版差異會降低可讀性。 | 在 CI pipeline 中加入 cargo fmt -- --check,確保提交前已格式化。 |
直接在 main 中寫大量程式碼 |
會讓程式入口變得雜亂,難以測試。 | 將功能抽離成獨立函式或模組,main 只負責呼叫。 |
忽略 Result 錯誤處理 |
初學者常把 unwrap() 用在所有 Result,在錯誤時會 panic。 |
使用 ? 運算子傳遞錯誤,或在開發階段使用 expect("說明")。 |
實際應用場景
CLI 工具的快速原型
println!可直接輸出訊息,配合std::env::args()解析參數,讓你在數分鐘內完成一個簡易的命令列工具,例如檔案搜尋或文字統計。嵌入式開發的除錯訊息
在微控制器(如 STM32)上,透過 UART 輸出println!(需額外設定)即可即時觀察變數狀態,協助除錯。WebAssembly(Wasm)中的 console.log
使用wasm-bindgen,println!會映射成 JavaScript 的console.log,讓 Rust 程式在瀏覽器中直接輸出除錯資訊。日誌系統的基礎
雖然正式專案會使用log或tracingcrate,但在學習階段,println!已足以了解訊息流與格式化技巧,為日後升級打好基礎。
總結
- 「Hello World」不只是輸出一句話,它同時驗證了 Rust 編譯器、Cargo 建置流程與開發環境的正確性。
- 透過
cargo new、cargo run、rustfmt、clippy,你已掌握 Rust 專案的完整生命週期。 - 了解
println!的格式化能力與常見錯誤,可在日後的 CLI、嵌入式、WebAssembly 等多種情境中快速產出除錯或日誌訊息。 - 最佳實踐:保持程式碼風格一致、避免
unwrap、將功能模組化,這些習慣會讓你的 Rust 程式更安全、可維護。
從今天的「Hello, world!」開始,未來你將能以 Rust 建構高效能、零安全漏洞的系統程式。祝你在 Rust 的旅程中玩得開心、寫得安心! 🚀