經過 30 天的探索,我們深入理解了 Rust 的主要概念:所有權、借用、生命週期。
今天我們要回答最實務的問題:如何將 Rust 的思維應用到日常工作中?何時該用 Rust,何時不該?
// PHP:隱式共享,執行期錯誤
class UserService {
private $db;
public function getUser($id) {
$user = $this->db->query("SELECT * FROM users WHERE id = ?", [$id]);
if (!$user) {
return null; // 可能被忽略
}
return $user;
}
}
// 使用時容易出錯
$user = $service->getUser(123);
echo $user->name; // 如果 $user 是 null?執行期錯誤
// Rust:顯式錯誤處理,編譯期保證
struct UserService {
db: Database,
}
impl UserService {
fn get_user(&self, id: u64) -> Result<User, Error> {
self.db.query_one("SELECT * FROM users WHERE id = $1", &[&id])
}
}
// 使用時必須處理錯誤
fn use_service(service: &UserService) {
match service.get_user(123) {
Ok(user) => println!("{}", user.name),
Err(e) => eprintln!("錯誤: {}", e),
}
}
關鍵轉變:
// Vue:可變狀態
export default {
data() {
return {
users: []
}
},
methods: {
addUser(user) {
this.users.push(user); // 直接修改
},
updateUser(id, newData) {
const user = this.users.find(u => u.id === id);
if (user) {
Object.assign(user, newData); // 直接修改
}
}
}
}
// Rust:不可變預設,明確可變
struct AppState {
users: Vec<User>,
}
impl AppState {
fn add_user(&mut self, user: User) {
self.users.push(user); // 需要 &mut self
}
fn update_user(&mut self, id: u64, new_data: UserData) -> Result<(), Error> {
let user = self.users.iter_mut()
.find(|u| u.id == id)
.ok_or(Error::NotFound)?;
user.update(new_data);
Ok(())
}
// 不可變方法不需要 mut
fn get_user(&self, id: u64) -> Option<&User> {
self.users.iter().find(|u| u.id == id)
}
}
關鍵轉變:
# Python:動態型別,執行期檢查
def process_data(data):
if isinstance(data, list):
return sum(data)
elif isinstance(data, dict):
return sum(data.values())
else:
raise TypeError("不支援的型別")
# 使用時可能出錯
result = process_data("hello") # 執行期錯誤
// Rust:靜態型別,編譯期檢查
enum Data {
List(Vec<i32>),
Dict(HashMap<String, i32>),
}
fn process_data(data: Data) -> i32 {
match data {
Data::List(list) => list.iter().sum(),
Data::Dict(dict) => dict.values().sum(),
}
}
// 使用時型別安全
fn use_process() {
let data = Data::List(vec![1, 2, 3]);
let result = process_data(data);
// 無法傳入錯誤型別
// let result = process_data("hello"); // ❌ 編譯錯誤
}
關鍵轉變:
// Go:GC 管理記憶體
type Cache struct {
data map[string]*Data
mu sync.RWMutex
}
func (c *Cache) Get(key string) *Data {
c.mu.RLock()
defer c.mu.RUnlock()
return c.data[key] // 回傳指標,GC 處理生命週期
}
func (c *Cache) Set(key string, value *Data) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = value // GC 處理舊值
}
// Rust:所有權管理記憶體
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
struct Cache {
data: Arc<RwLock<HashMap<String, Arc<Data>>>>,
}
impl Cache {
fn get(&self, key: &str) -> Option<Arc<Data>> {
let data = self.data.read().unwrap();
data.get(key).cloned() // 回傳 Arc,明確共享所有權
}
fn set(&self, key: String, value: Arc<Data>) {
let mut data = self.data.write().unwrap();
data.insert(key, value); // 舊值自動 Drop
}
}
關鍵轉變:
概念 | PHP/JS | Python | Go | Rust |
---|---|---|---|---|
記憶體管理 | GC | GC | GC | 所有權 |
共享 | 隱式複製/引用 | 引用 | 指標 | &T / Arc<T> |
可變 | 預設可變 | 預設可變 | 預設可變 | 預設不可變 |
生命週期 | GC 決定 | GC 決定 | GC 決定 | 編譯期決定 |
概念 | PHP/JS | Python | Go | Rust |
---|---|---|---|---|
錯誤類型 | Exception | Exception | error 值 | Result<T, E> |
處理方式 | try/catch | try/except | if err != nil | match / ? |
強制處理 | 否 | 否 | 否 | 是 |
型別安全 | 否 | 否 | 否 | 是 |
概念 | PHP | JS | Python | Go | Rust |
---|---|---|---|---|---|
並發模型 | 多進程 | Event Loop | GIL | goroutine | 執行緒/async |
共享狀態 | 無 | 單執行緒 | 鎖 | channel/鎖 | Arc<Mutex> |
安全保證 | 無 | 單執行緒 | 執行期 | 執行期 | 編譯期 |
// Laravel
class UserController extends Controller {
public function show($id) {
$user = User::find($id);
if (!$user) {
return response()->json(['error' => 'Not found'], 404);
}
return response()->json($user);
}
}
// Rust (使用 axum)
use axum::{
extract::Path,
http::StatusCode,
Json,
response::IntoResponse,
};
async fn get_user(
Path(id): Path<u64>,
State(db): State<Database>,
) -> Result<Json<User>, AppError> {
let user = db.get_user(id).await?;
Ok(Json(user))
}
// 錯誤處理
impl IntoResponse for AppError {
fn into_response(self) -> Response {
match self {
AppError::NotFound => {
(StatusCode::NOT_FOUND, "User not found").into_response()
}
AppError::Database(e) => {
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response()
}
}
}
}
遷移要點:
# Python
def process_logs(filename):
errors = []
with open(filename) as f:
for line in f:
if 'ERROR' in line:
errors.append(parse_error(line))
return errors
// Rust
use std::fs::File;
use std::io::{BufRead, BufReader};
fn process_logs(filename: &str) -> Result<Vec<Error>, std::io::Error> {
let file = File::open(filename)?;
let reader = BufReader::new(file);
let errors: Result<Vec<_>, _> = reader
.lines()
.filter_map(|line| {
let line = line.ok()?;
if line.contains("ERROR") {
Some(parse_error(&line))
} else {
None
}
})
.collect();
errors
}
遷移要點:
// Go
func processItems(items []Item) []Result {
results := make(chan Result, len(items))
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item Item) {
defer wg.Done()
results <- process(item)
}(item)
}
wg.Wait()
close(results)
var output []Result
for r := range results {
output = append(output, r)
}
return output
}
// Rust
use tokio::task;
async fn process_items(items: Vec<Item>) -> Vec<Result> {
let handles: Vec<_> = items
.into_iter()
.map(|item| {
task::spawn(async move {
process(item).await
})
})
.collect();
let mut results = Vec::new();
for handle in handles {
if let Ok(result) = handle.await {
results.push(result);
}
}
results
}
遷移要點:
// 高頻交易、遊戲引擎、影像處理
fn hot_path(data: &[f64]) -> f64 {
data.iter().sum() // 零成本抽象
}
// 作業系統、驅動程式、嵌入式系統
unsafe fn direct_hardware_access() {
// 完全控制記憶體
}
// 金融系統、醫療系統、航空系統
fn critical_operation() -> Result<(), Error> {
// 編譯期保證
}
// ripgrep, fd, bat, exa
fn main() {
// 快速啟動、低記憶體使用
}
#[wasm_bindgen]
pub fn compute(data: &[u8]) -> Vec<u8> {
// 在瀏覽器中執行
}
# Python 更適合
def prototype():
# 快速驗證想法
pass
# Python 生態系更成熟
import pandas as pd
df = pd.read_csv('data.csv')
// Laravel 更快速
Route::get('/users', [UserController::class, 'index']);
// React/Vue 更適合
export default {
// 快速開發 UI
}
是否需要極致效能?
├─ 是 → 考慮 Rust
└─ 否 → 是否需要記憶體安全保證?
├─ 是 → 考慮 Rust
└─ 否 → 是否是系統程式設計?
├─ 是 → 考慮 Rust
└─ 否 → 是否需要快速開發?
├─ 是 → 使用熟悉的語言
└─ 否 → 評估團隊技能和專案需求
現有系統 (Python/Go)
↓
↓ 呼叫
↓
Rust 模組 (效能關鍵部分)
# Python 呼叫 Rust
import my_rust_module
def process_data(data):
# 關鍵路徑用 Rust
result = my_rust_module.fast_process(data)
# 其他邏輯用 Python
return transform(result)
現有系統 (PHP/Laravel)
↓
↓ HTTP API
↓
新服務 (Rust)
1. 剖析找出瓶頸
2. 用 Rust 重寫瓶頸部分
3. 透過 FFI 整合
4. 驗證效能提升
5. 逐步擴展
// Rust 強迫我們明確表達意圖
fn process(data: &str) -> Result<Output, Error> {
// 錯誤處理:明確
// 所有權:明確
// 生命週期:明確
}
應用到其他語言:
// 能在編譯期檢查的,不要留到執行期
fn safe_divide(a: i32, b: NonZeroI32) -> i32 {
a / b // 編譯期保證不會除以零
}
應用到其他語言:
// 預設不可變,需要時才可變
let data = vec![1, 2, 3]; // 不可變
let mut data = vec![1, 2, 3]; // 明確可變
應用到其他語言:
// 清楚誰擁有資料
fn take_ownership(data: String) { } // 拿走
fn borrow_data(data: &str) { } // 借用
應用到其他語言:
Arc<Mutex>
Rust 不只是一門語言,更是一種思維方式:
這些原則不只適用於 Rust,也能讓我們在任何語言中寫出更好的程式碼。
Rust 逼我成為更好的工程師,不是因為它的語法,而是因為它改變了我思考程式的方式。