Go 和 Rust 作为编译型语言,CI 流程与解释型语言差异显著:编译速度、交叉编译能力、静态链接、二进制分发。Go 的工具链简洁高效,Rust 的类型系统和 borrow checker 在编译期捕获大量错误。本文覆盖 Go/Rust 的 GitHub Actions CI 最佳实践——从缓存策略到交叉编译,从安全扫描到多平台发布。
一、Go CI 流水线
1.1 基础工作流
# .github/workflows/go.yml
name: Go CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
go: ['1.19', '1.20', '1.21', '1.22']
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: Cache Go modules
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Download dependencies
run: go mod download
- name: Run tests
run: go test -v -race -coverprofile=coverage.out ./...
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage.out
1.2 关键要点
actions/setup-go@v5 自动处理 GOMODCACHE 缓存
-race 标志:启用数据竞争检测(Go 并发必备)
-coverprofile:生成覆盖率文件
# Go 的测试文化是「内置的」——go test 是标准工具链的一部分
二、Rust CI 流水线
2.1 基础工作流
# .github/workflows/rust.yml
name: Rust CI
on: [push, pull_request]
env:
CARGO_TERM_COLOR: always
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
rust: [stable, beta, nightly]
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-action@stable
with:
toolchain: ${{ matrix.rust }}
- name: Cache Cargo
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Check formatting
run: cargo fmt -- --check
- name: Run clippy
run: cargo clippy -- -D warnings
- name: Run tests
run: cargo test --verbose
- name: Generate coverage
run: cargo tarpaulin --verbose --out Xml
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./cobertura.xml
2.2 Rust 工具链
rustfmt:代码格式化(类似 Black/Prettier)
clippy:Lint 工具(比编译器更严格的检查)
cargo-check:快速编译检查(不生成二进制)
cargo-tarpaulin:覆盖率工具
# Rust 的「编译即检查」哲学使大量问题在编译期消除
三、交叉编译
3.1 Go 交叉编译
- name: Cross compile
run: |
GOOS=linux GOARCH=amd64 go build -o bin/app-linux-amd64
GOOS=linux GOARCH=arm64 go build -o bin/app-linux-arm64
GOOS=darwin GOARCH=amd64 go build -o bin/app-darwin-amd64
GOOS=darwin GOARCH=arm64 go build -o bin/app-darwin-arm64
GOOS=windows GOARCH=amd64 go build -o bin/app-windows-amd64.exe
3.2 Rust 交叉编译
- name: Install cross
run: cargo install cross --git https://github.com/cross-rs/cross
- name: Build for Linux ARM64
run: cross build --target aarch64-unknown-linux-gnu --release
- name: Build for Linux x86_64
run: cross build --target x86_64-unknown-linux-musl --release
3.3 musl 静态链接
Go:默认静态链接(CGO_ENABLED=0)
Rust:musl 目标实现真正静态链接(不依赖 glibc)
# 静态链接的优势:
# - Alpine 镜像运行(无 glibc)
# - 跨 Linux 发行版兼容
# - 更小的攻击面
四、性能基准测试
4.1 Go Benchmark
- name: Run benchmarks
run: go test -bench=. -benchmem ./... | tee benchmark.txt
- name: Store benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
tool: 'go'
output-file-path: benchmark.txt
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
4.2 Rust Criterion
- name: Run Criterion benchmarks
run: cargo bench
- name: Upload benchmark results
uses: actions/upload-artifact@v3
with:
name: benchmark-results
path: target/criterion/
五、安全扫描
5.1 Go 安全扫描
- name: Run Nancy
uses: sonatype-nexus-community/nancy-github-action@main
with:
goListFile: go.list
- name: Run gosec
uses: securego/gosec@master
with:
args: '-fmt sarif -out results.sarif ./...'
5.2 Rust 安全扫描
- name: Run cargo-audit
uses: actions-rs/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Run cargo-deny
uses: EmbarkStudios/cargo-deny-action@v1
六、Release 自动化
6.1 GoReleaser
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# .goreleaser.yml
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
archives:
- format: tar.gz
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
6.2 Rust cargo-release
- name: Publish to crates.io
run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
七、多平台 Artifact 发布
7.1 矩阵构建多平台
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
- os: macos-latest
target: x86_64-apple-darwin
- os: macos-latest
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
steps:
- uses: actions/checkout@v4
- name: Build
run: cargo build --release --target ${{ matrix.target }}
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: binary-${{ matrix.target }}
path: target/${{ matrix.target }}/release/myapp*
总结
Go 和 Rust 的 CI 都受益于「编译即检查」的哲学——大量问题在编译期消除。Go 的 CI 重点是:go test -race 检测数据竞争、交叉编译简便(GOOS/GOARCH)、GoReleaser 一键多平台发布。Rust 的 CI 重点是:cargo fmt/clippy 保持代码质量、tarpaulin 生成覆盖率、cargo-audit 扫描依赖漏洞、cross 工具链处理交叉编译。两者的缓存都关键——Go 的 ~/go/pkg/mod 和 Rust 的 ~/.cargo + target/ 目录缓存能显著加速 CI。静态链接(Go 默认/Rust musl)让二进制分发变得简单,一个文件即可跨发行版运行。
延伸阅读:
- GitHub Actions Java/JVM CI — JVM 项目 CI
- GitHub Actions PR 自动化 — 发布自动化
- Go 语言专题 — Go 语言深入
- Rust 专题 — Rust 语言深入
- GoReleaser 文档
- Cross 文档
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。