从 Go 迁移到 Rust
问题
从 Go 迁移到 Rust 有哪些核心差异需要注意?
答案
核心概念映射
| Go | Rust | 说明 |
|---|---|---|
goroutine | tokio::spawn | Rust 的 task 更轻量 |
channel | tokio::sync::mpsc | 类似但有所有权语义 |
interface | trait | Rust 的 trait 更强大 |
defer | Drop | Rust 自动调用,无需显式声明 |
error | Result<T, E> | 强制处理,编译时检查 |
nil | Option<T> | 编译时消除空指针 |
mutex | Mutex<T> | Mutex 保护数据而非代码段 |
go func(){} | tokio::spawn(async {}) | 需要 Send + 'static |
| GC | 所有权系统 | 编译时确定生命周期 |
关键心智模型转换
错误处理:panic → Result
// Go:容易忘记检查 error
result, err := doSomething()
if err != nil {
return err
}
// Rust:编译器强制处理
let result = do_something()?; // ? 自动传播错误
// 不可能忘记处理错误
并发:共享内存 → 所有权
// Go:共享内存需要手动加锁
var mu sync.Mutex
var counter int
mu.Lock()
counter++
mu.Unlock()
// Rust:Mutex 保护数据,编译器确保加锁
let counter = Arc::new(Mutex::new(0));
// 不加锁就无法访问数据
let mut val = counter.lock().unwrap();
*val += 1;
// 离开作用域自动解锁
Null 处理
// Go:运行时 nil panic
var user *User
user.Name // panic: nil pointer dereference
// Rust:编译时保证
let user: Option<User> = None;
// user.name // ← 编译错误!必须先检查
if let Some(u) = user {
println!("{}", u.name); // 安全
}
迁移建议
- 渐进式:不要一次性重写,先从性能瓶颈模块开始
- FFI 桥接:可以通过 CGo ↔ C ↔ Rust 相互调用
- 先学所有权:这是最大的心智模型转换
- 接受编译慢:换来的是运行时安全
常见面试问题
Q1: 什么时候应该选 Rust 而非 Go?
答案:
| 选择 | 场景 |
|---|---|
| Go | 快速开发、微服务、运维工具、团队 Go 经验丰富 |
| Rust | 极致性能、内存敏感、WebAssembly、系统编程、安全关键 |