2026 年,Go 和 Rust 已经是后端开发领域最炙手可热的两门语言。Go 以简洁高效著称,Rust 以极致性能和安全闻名。但"性能"这两个字,到底差多少?谁在什么场景下更快?

今天这篇文章,不讲感觉,只讲数据。所有性能数据来源于 Programming Language Benchmarks(2026 年 6 月更新)、The Computer Language Benchmarks Game 以及多个社区实测项目,编译器版本为 rustc 1.90.0go 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 实现:

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 实现:

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):

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 标准库):

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):

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 标准库):

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):

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):

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/awaitResult 类型,代码稍长 - Go 的 sync.WaitGroup 模式在 Rust 中用 JoinHandle 替代,语义类似但写法不同

5.4 并发安全

Go 的并发安全: - 依赖开发者自律:go vet -race 检测数据竞争 - channel 鼓励"不要通过共享内存通信,而要通过通信共享内存" - 但实际项目中 sync.Mutex 用得非常多,数据竞争仍然是常见 bug 来源

Rust 的并发安全: - 编译期保证SendSync 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 调用
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 做性能关键模块

没有"最好"的语言,只有最适合你场景的语言。希望这篇数据驱动的分析能帮你做出更好的技术选型决策。


参考资料: