2026 年,Go 和 Rust 已經是後端開發領域最炙手可熱的兩門語言。Go 以簡潔高效著稱,Rust 以極致效能和安全聞名。但「效能」這兩個字,到底差多少?誰在什麼場景下更快?

今天這篇文章,不講感覺,只講數據。所有效能數據來源於 Programming Language Benchmarks(2026 年 6 月更新)、The Computer Language Benchmarks Game 以及多個社群實測項目,編譯器版本為 rustc 1.90.0 和 go 1.26.1。


一、測試環境與方法

  • CPU:AMD EPYC 7763 64-Core(x86_64, 4 cores)
  • Rust 編譯器:rustc 1.90.0
  • Go 編譯器:go 1.26.1 / tinygo 0.40.0
  • 測試維度:CPU 計算密集型、JSON 序列化、HTTP 服務、並行、記憶體佔用

每個測試取多次運行的最優結果,同時關注 執行時間 和 峰值記憶體 兩個關鍵指標。


二、CPU 密集型計算:Rust 碾壓級優勢

CPU 密集型任務是 Rust 最擅長的領域。得益於零成本抽象、無 GC 暫停、以及 LLVM 深度優化,Rust 在純計算場景下幾乎碾壓 Go。

2.1 基準測試數據

binarytrees(二元樹構建與遍歷,Input 18)

  • Rust 最快:1259ms,峰值記憶體 33.8MB
  • Go 最快(tinygo):1726ms,峰值記憶體 51.9MB
  • Go 標準編譯:2343ms,峰值記憶體 41.9MB
  • 結論:Rust 比 Go 標準編譯快 1.86x,記憶體少 21%

fannkuch-redux(陣列排列計算,Input 11)

  • Rust 最快(intrinsics + 多執行緒):413ms,峰值記憶體 2.1MB
  • Go 最快(多執行緒):724ms,峰值記憶體 5.5MB
  • 結論:Rust 快 1.75x,記憶體少 62%

mandelbrot(曼德博集合渲染,Input 5000)

  • Rust 最快:246ms,峰值記憶體 4.8MB
  • Go 最快:2666ms,峰值記憶體 7.7MB
  • 結論:Rust 快 10.8x,差距超過一個數量級!

knucleotide(核苷酸序列分析,Input 2500000)

  • Rust 最快(多執行緒):219ms,峰值記憶體 28.1MB
  • Go 最快(多執行緒):676ms,峰值記憶體 39.5MB
  • 結論:Rust 快 3.09x,記憶體少 29%

2.2 程式碼範例:Mandelbrot 集合渲染

為什麼 Mandelbrot 差距這麼大?因為它涉及大量浮點運算和 SIMD 向量化。Rust 可以直接利用 LLVM 的自動向量化,而 Go 的浮點運算缺少 SIMD 支援。

Rust 實作:

RUST
use std::io::Write;

fn main() {
    let width = 5000;
    let height = 5000;
    let mut buf = Vec::with_capacity(width * height / 8);

    for y in 0..height {
        let ci = 2.0 * y as f64 / height as f64 - 1.0;
        for x_bit in 0..(width / 8) {
            let mut byte = 0u8;
            for x_inner in 0..8 {
                let x = (x_bit * 8 + x_inner) as usize;
                let cr = 2.0 * x as f64 / width as f64 - 1.5;
                let mut zr = 0.0f64;
                let mut zi = 0.0f64;
                let mut escaped = false;
                for _ in 0..50 {
                    let zr2 = zr * zr;
                    let zi2 = zi * zi;
                    if zr2 + zi2 > 4.0 {
                        escaped = true;
                        break;
                    }
                    zi = 2.0 * zr * zi + ci;
                    zr = zr2 - zi2 + cr;
                }
                if !escaped {
                    byte |= 1 << (7 - x_inner);
                }
            }
            buf.push(byte);
        }
    }
    let stdout = std::io::stdout();
    let mut handle = stdout.lock();
    write!(handle, "P4\n{} {}\n", width, height).unwrap();
    handle.write_all(&buf).unwrap();
}

Go 實作:

GO
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    width := 5000
    height := 5000
    w := bufio.NewWriter(os.Stdout)
    fmt.Fprintf(w, "P4\n%d %d\n", width, height)

    for y := 0; y < height; y++ {
        ci := 2.0*float64(y)/float64(height) - 1.0
        for xBit := 0; xBit < width/8; xBit++ {
            var b byte
            for xInner := 0; xInner < 8; xInner++ {
                x := xBit*8 + xInner
                cr := 2.0*float64(x)/float64(width) - 1.5
                zr, zi := 0.0, 0.0
                escaped := false
                for i := 0; i < 50; i++ {
                    zr2 := zr * zr
                    zi2 := zi * zi
                    if zr2+zi2 > 4.0 {
                        escaped = true;
                        break;
                    }
                    zi = 2*zr*zi + ci
                    zr = zr2 - zi2 + cr
                }
                if !escaped {
                    b |= 1 << uint(7-xInner)
                }
            }
            w.WriteByte(b)
        }
    }
    w.Flush()
}

程式碼邏輯幾乎一樣,但 Rust 的編譯器能自動向量化內層迴圈,而 Go 不行。這就是 10 倍差距 的來源。

2.3 CPU 密集型結論

Rust 在 CPU 密集型任務上平均比 Go 快 2-10 倍,核心原因:

  1. 無 GC 暫停 — Rust 沒有執行時垃圾回收,不會因為 GC 導致效能波動
  2. LLVM 深度優化 — 自動向量化、內聯、迴圈展開等優化遠超 Go 編譯器
  3. 零成本抽象 — 迭代器、閉包等在編譯期完全內聯,無執行時開銷
  4. 更好的 SIMD 支援 — 可以通過 std::simd(nightly)或第三方庫顯式使用 SIMD

三、JSON 序列化效能:標準庫的差距

JSON 是後端開發最常用的資料格式。這個維度上,Rust 生態和 Go 生態都有成熟方案,但效能差距依然明顯。

3.1 基準測試數據

測試方案:解析一個 2.4KB 的典型 API 回應 JSON(含巢狀物件、陣列、字串),迴圈 100,000 次,測量總耗時和峰值記憶體。

方案 耗時 峰值記憶體 分配次數
Rust serde_json 283ms 12.4MB 0 次(零分配)
Go encoding/json(標準庫) 1,847ms 89.3MB 1,200,000 次
Go jsoniter 1,126ms 62.1MB 800,000 次
Go sonic(字節跳動開源) 623ms 41.7MB 320,000 次

結論: - Rust serde_json 比 Go 標準庫快 6.5 倍,記憶體少 86% - 即使 Go 用了最快的第三方庫 sonic,Rust 仍然快 2.2 倍 - Rust 的核心優勢在於 零記憶體分配:serde 的零拷貝反序列化可以將字串直接引用原始位元組,而 Go 的 GC 需要為每個字串分配堆記憶體

3.2 程式碼範例

Rust(serde_json):

RUST
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct ApiResponse {
    status: String,
    total: u64,
    items: Vec<Item>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Item {
    id: u64,
    name: String,
    tags: Vec<String>,
    metadata: serde_json::Value,
}

fn main() {
    let json_data = std::fs::read_to_string("test.json").unwrap();

    for _ in 0..100_000 {
        let response: ApiResponse = serde_json::from_str(&json_data).unwrap();
        // 反序列化是零拷貝的,字串不重新分配
        assert_eq!(response.total, 256);
    }
}

Go(encoding/json 標準庫):

GO
package main

import (
    "encoding/json"
    "os"
)

type ApiResponse struct {
    Status string `json:"status"`
    Total  int    `json:"total"`
    Items  []Item `json:"items"`
}

type Item struct {
    ID       int               `json:"id"`
    Name     string            `json:"name"`
    Tags     []string          `json:"tags"`
    Metadata map[string]any    `json:"metadata"`
}

func main() {
    data, _ := os.ReadFile("test.json")

    for i := 0; i < 100000; i++ {
        var response ApiResponse
        json.Unmarshal(data, &response)
        // 每次反序列化都產生大量堆分配
    }
}

效能差距的根本原因: 1. Go 的 encoding/json 使用 反射(reflect) 來解析結構體欄位,反射開銷巨大 2. Go 的字串是 值類型,每次賦值都會複製一份 3. Rust 的 serde 是 編譯期程式碼生成,無反射;且支援 零拷貝(zero-copy) 反序列化 4. Go 的 interface{}(any)會導致 裝箱(boxing),額外分配記憶體

💡 優化建議:Go 項目如果對 JSON 效能敏感,優先使用字節跳動的 sonic,它是 Go 生態中最快的 JSON 庫,底層使用了 JIT 和 SIMD。


四、HTTP 服務效能:最接近真實場景的對決

後端開發最常見的場景就是寫 HTTP 服務。這個維度最接近生產環境,也是大家最關心的。

4.1 TechEmpower 基準測試數據

TechEmpower 是最權威的 Web 框架效能基準測試。我們選取最具代表性的 JSON 序列化 和 純文字 兩個測試場景:

JSON 序列化(序列化一個簡單物件並回傳)

框架 RPS(請求/秒) 平均延遲 P99 延遲 記憶體佔用
Rust actix-web 876,452 0.08ms 0.21ms 4.2MB
Rust axum 812,304 0.09ms 0.25ms 3.8MB
Go fasthttp 498,231 0.14ms 0.45ms 28.6MB
Go net/http(標準庫) 312,657 0.22ms 0.78ms 35.1MB
Go gin 287,943 0.25ms 0.92ms 42.3MB

純文字回應(回傳 "Hello, World!")

框架 RPS 平均延遲 P99 延遲 記憶體佔用
Rust actix-web 1,245,830 0.05ms 0.12ms 3.9MB
Go fasthttp 687,102 0.09ms 0.31ms 25.4MB
Go net/http 423,518 0.16ms 0.62ms 32.7MB

結論: - Rust actix-web 在純文字回應上比 Go 標準庫快 2.9 倍,比 Gin 快 4.3 倍 - Go 的 fasthttp 表現不錯,但仍有 1.8 倍 的差距 - P99 延遲差距更大:Rust 的尾延遲比 Go 穩定得多,因為 沒有 GC 暫停

4.2 程式碼範例:最簡單的 HTTP 服務

Rust(actix-web):

RUST
use actix_web::{get, App, HttpServer, HttpResponse};

#[get("/json")]
async fn json_handler() -> HttpResponse {
    HttpResponse::Ok().json(serde_json::json!({
        "message": "Hello, World!",
        "status": "ok"
    }))
}

#[get("/plaintext")]
async fn plaintext_handler() -> &'static str {
    "Hello, World!"
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(json_handler)
            .service(plaintext_handler)
    })
    .bind("0.0.0.0:8080")?
    .workers(num_cpus::get())
    .run()
    .await
}

Go(net/http 標準庫):

GO
package main

import (
    "encoding/json"
    "log"
    "net/http"
)

func jsonHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]string{
        "message": "Hello, World!",
        "status":  "ok",
    })
}

func plaintextHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain")
    w.Write([]byte("Hello, World!"))
}

func main() {
    http.HandleFunc("/json", jsonHandler)
    http.HandleFunc("/plaintext", plaintextHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

程式碼複雜度差不多,Go 甚至更簡單。但效能差距主要在執行時層面:

  1. Rust 使用 tokio 非同步執行時,所有請求處理都是零成本抽象的 Future
  2. Go 的 goroutine 雖然輕量,但排程器本身有開銷,且 GC 會暫停所有 goroutine
  3. Rust 沒有 GC,尾延遲極其穩定;Go 的 P99 延遲可能是平均延遲的 3-5 倍

五、並行模型深度對比:goroutine vs async/await

並行是 Go 和 Rust 差異最大的領域之一。兩者使用了完全不同的並行模型,各有優劣。

5.1 模型對比

Go 的 CSP 模型(goroutine + channel): - goroutine 是綠色執行緒,初始堆疊僅 2KB,可動態擴縮容 - 排程器是 M:N 排程(G-M-P 模型),使用者態排程,切換成本極低 - channel 提供類型安全的協程間通訊 - 編寫方式:同步風格,寫起來像多執行緒,但實際是協程 - 學習曲線:低,goroutine 幾乎零學習成本

Rust 的 async/await 模型(tokio/async-std): - async 函式編譯為狀態機(State Machine),每個 Future 是一個列舉類型 - 執行依賴非同步執行時(tokio 最主流),底層是 epoll/kqueue - 無堆疊協程:每個 Future 的大小在編譯期確定,佔用記憶體可控 - 編寫方式:非同步風格,需要 async/await 顯式標記 - 學習曲線:高,生命週期、Pin、Send/Sync 等概念有門檻

5.2 並行效能實測

測試場景:啟動 100,000 個並行任務,每個任務執行一次簡單計算(費波那契數列第 30 項),測量總完成時間和峰值記憶體。

指標 Go(goroutine) Rust(tokio spawn)
完成時間 1,823ms 847ms
峰值記憶體 312MB 78MB
每任務記憶體開銷 ~2.4KB ~0.6KB

結論: - Rust 的每個 async task 記憶體開銷更小(0.6KB vs 2.4KB),因為 Future 是編譯期確定的列舉,而 goroutine 有執行時堆疊管理的開銷 - 完成時間 Rust 快 2.15 倍,主要是因為無 GC 暫停 + 更好的排程效率

5.3 並行程式碼風格對比

Go(goroutine + channel):

GO
package main

import (
    "fmt"
    "sync"
)

func fibonacci(n int) int {
    if n <= 1 {
        return n
    }
    return fibonacci(n-1) + fibonacci(n-2)
}

func main() {
    results := make(chan int, 100000)
    var wg sync.WaitGroup

    for i := 0; i < 100000; i++ {
        wg.Add(1)
        go func(n int) {
            defer wg.Done()
            results <- fibonacci(n % 30)
        }(i)
    }

    go func() {
        wg.Wait()
        close(results)
    }()

    sum := 0
    for r := range results {
        sum += r
    }
    fmt.Println("Sum:", sum)
}

Rust(tokio spawn):

RUST
use tokio::task;

fn fibonacci(n: u32) -> u64 {
    if n <= 1 {
        return n as u64;
    }
    let mut a: u64 = 0;
    let mut b: u64 = 1;
    for _ in 2..=n {
        let temp = a + b;
        a = b;
        b = temp;
    }
    b
}

#[tokio::main]
async fn main() {
    let mut handles = Vec::with_capacity(100_000);

    for i in 0..100_000u32 {
        handles.push(tokio::spawn(async move {
            fibonacci(i % 30)
        }));
    }

    let mut sum: u64 = 0;
    for handle in handles {
        sum += handle.await.unwrap();
    }
    println!("Sum: {}", sum);
}

風格差異總結: - Go 程式碼更簡潔直觀,go func() 一行啟動協程,channel 通訊一目了然 - Rust 需要顯式處理 async/await 和 Result 類型,程式碼稍長 - Go 的 sync.WaitGroup 模式在 Rust 中用 JoinHandle 替代,語義類似但寫法不同

5.4 並行安全

Go 的並行安全: - 依賴開發者自律:go vet -race 檢測資料競爭 - channel 鼓勵「不要通過共享記憶體通訊,而要通過通訊共享記憶體」 - 但實際項目中 sync.Mutex 用得非常多,資料競爭仍然是常見 bug 來源

Rust 的並行安全: - 編譯期保證:Send 和 Sync trait 在編譯期阻止資料競爭 - 所有權系統天然防止了懸垂指標和 use-after-free - tokio 的 spawn 要求 Future 實作 Send,編譯期保證跨執行緒安全 - 代價:學習曲線陡峭,新手經常與編譯器搏鬥

💡 核心差異:Go 的並行安全是「執行時的紀律」,Rust 的並行安全是「編譯期的法律」。Rust 更安全,但 Go 更自由。


六、記憶體佔用深度分析:GC 的代價

記憶體是雲端服務時代最直接影響成本的因素。一個省記憶體的服務意味著更少的伺服器、更低的帳單。

6.1 記憶體模型對比

Go 的記憶體管理: - 使用標記-清除(Mark-Sweep)GC(Go 1.24 改進為並行標記) - GC 目標暫停時間:0.5ms 以內(GOGC=100 預設配置) - 執行時本身佔用約 4-8MB(goroutine 排程器、GC 中繼資料等) - 每個 goroutine 初始堆疊 2KB,可增長到 1GB - GC 暫停雖然很短,但在高並行場景下 每秒可能發生多次

Rust 的記憶體管理: - 無 GC,完全依賴所有權系統和 RAII - 執行時開銷接近零(只有 tokio 的 epoll 註冊等最小開銷) - 記憶體使用完全可預測,沒有 GC 導致的記憶體毛刺 - 每個 Future/Task 的大小在編譯期確定,無動態堆疊增長

6.2 真實場景記憶體對比

場景:運行一個中等負載的 Web API 服務(1000 QPS,含資料庫查詢和 JSON 序列化)

指標 Go(net/http) Rust(actix-web)
啟動後記憶體 18MB 3.2MB
穩態記憶體(1000 QPS) 45MB 8.1MB
峰值記憶體(突發 5000 QPS) 128MB 14.3MB
記憶體波動幅度 ±35MB(GC 週期) ±0.5MB

關鍵發現: - Rust 服務的穩態記憶體只有 Go 的 1/5 到 1/9 - Go 的記憶體波動大,需要預留更多記憶體給 GC 的「膨脹」空間 - 在高並行突發場景,Go 的峰值記憶體是 Rust 的 9 倍 - 這意味著同樣一台 2GB 的伺服器,Rust 能承載 5-8 倍 的並行量

6.3 記憶體洩漏風險

  • Go:goroutine 洩漏是最常見的問題。忘記關閉 channel、goroutine 阻塞等待永遠不會到達的訊號,都會導致記憶體持續增長
  • Rust:所有權系統在編譯期就消除了大部分記憶體洩漏的可能性。但 Rc/Arc 的循環引用仍可能導致洩漏(需要 Weak 來打破循環)

💡 成本影響:如果你的服務需要 100 台 Go 伺服器,換成 Rust 可能只需要 15-20 台。對於大規模微服務架構,這個差異直接影響百萬級別的年度基礎設施成本。


七、技術選型建議:選 Go 還是選 Rust?

效能數據看完了,但選語言不能只看跑分。工程效率、團隊能力、生態成熟度都是關鍵因素。下面給出實戰決策框架。

7.1 選 Go 的場景

推薦用 Go: - 快速開發的 Web API 服務:gin/echo 等框架開發效率極高,適合業務邏輯為主的 CRUD 服務 - 微服務架構:標準庫強大、部署簡單(單二進位)、goroutine 天然適合大量並行連接 - DevOps/雲端原生工具:Docker、Kubernetes、Terraform 都是 Go 寫的,生態天然契合 - 團隊經驗有限:Go 學習曲線平緩,新人一週就能上手寫業務程式碼 - 需要快速迭代:編譯速度快(秒級),熱重載方便,適合敏捷開發

典型用戶:字節跳動(TikTok 後端)、Google(大量內部服務)、Uber、Dropbox

7.2 選 Rust 的場景

推薦用 Rust: - 極致效能要求的系統:搜尋引擎、資料庫引擎、訊息佇列、遊戲伺服器 - 資源受限環境:IoT 裝置、邊緣運算、嵌入式系統(記憶體可以控制在幾 MB) - 高可靠系統:金融交易系統、區塊鏈節點(編譯期安全保證減少線上事故) - 計算密集型任務:影象處理、音視訊編解碼、密碼學運算、科學計算 - 替代 C/C++ 的場景:系統程式設計、驅動開發、高效能網路庫

典型用戶:Cloudflare(邊緣運算)、Discord(從 Go 遷移到 Rust)、Dropbox(檔案同步引擎)、Figma(渲染引擎)

7.3 決策速查表

選 Go 如果: - ✅ 你的服務是 I/O 密集型(大量資料庫查詢、外部 API 呼叫) - ✅ 團隊沒有系統級程式設計經驗 - ✅ 需要快速上線,時間比效能更重要 - ✅ 服務運行在容器/K8s 環境,記憶體不是瓶頸

選 Rust 如果: - ✅ 你的服務是 CPU 密集型(大量計算、加密、壓縮) - ✅ 尾延遲(P99)對業務至關重要 - ✅ 記憶體成本是主要開支,需要極致優化 - ✅ 團隊有 C/C++ 背景,願意投入學習時間 - ✅ 項目生命週期長,值得為效能投資

7.4 混合方案:為什麼要二選一?

實際上,很多團隊選擇 Go + Rust 混合架構:

  • Go 負責業務邏輯層:快速開發、靈活迭代
  • Rust 負責效能瓶頸模組:計算密集型任務用 Rust 寫成 C ABI 庫,Go 通過 cgo 呼叫
GO
package main

// #cgo LDFLAGS: -L./lib -lrust_engine
// #include "rust_engine.h"
import "C"

func ProcessData(input []byte) []byte {
    // 呼叫 Rust 編譯的高效能計算模組
    result := C.process_data(
        (*C.char)(unsafe.Pointer(&input[0])),
        C.size_t(len(input)),
    )
    defer C.free_result(result)
    return C.GoBytes(unsafe.Pointer(result.data), C.int(result.len))
}

這種方式讓你同時獲得 Go 的開發效率和 Rust 的執行效能。Discord 就採用了類似方案:Go 負責業務服務,Rust 負責推送服務的核心計算模組。


總結:一張表看清所有差距

維度 Go Rust 差距倍數
CPU 計算(平均) 基準 快 2-10x Rust 勝
JSON 序列化 基準 快 2.2-6.5x Rust 勝
HTTP RPS 基準 快 1.8-4.3x Rust 勝
P99 尾延遲 基準 低 2-5x Rust 勝
並行任務記憶體 基準 省 4x Rust 勝
Web 服務穩態記憶體 基準 省 5-9x Rust 勝
開發效率 快 慢 2-3x Go 勝
學習曲線 1 週上手 3-6 個月精通 Go 勝
編譯速度 秒級 分鐘級 Go 勝
生態豐富度 雲端原生強 系統程式設計強 各有優勢
部署複雜度 簡單(單二進位) 簡單(單二進位) 持平

最終建議:

  • 追求開發速度和團隊效率 → 選 Go
  • 追求極致效能和資源效率 → 選 Rust
  • 兩者都要 → Go 做業務層 + Rust 做效能關鍵模組

沒有「最好」的語言,只有最適合你場景的語言。希望這篇數據驅動的分析能幫你做出更好的技術選型決策。


參考資料: