工程化全景
Go 的工程化工具链是其最大优势之一:内置格式化、测试、基准测试、性能分析,几乎不需要第三方工具。
工具链全景
Go 工程化
├── 包管理
│ └── Go Modules (go.mod / go.sum)
│
├── 代码质量
│ ├── gofmt / goimports — 格式化(内置)
│ ├── go vet — 静态分析(内置)
│ ├── golangci-lint — 综合 Linter
│ └── staticcheck — 高级静态分析
│
├── 测试
│ ├── go test — 测试框架(内置)
│ ├── testify — 断言库
│ ├── gomock — Mock 框架
│ └── go-fuzz — 模糊测试(内置,1.18+)
│
├── 性能分析
│ ├── go test -bench — 基准测试(内置)
│ ├── pprof — CPU/内存分析(内置)
│ └── trace — 执行追踪(内置)
│
├── 开发体验
│ ├── Air — 热重载
│ ├── dlv — 调试器
│ └── gopls — LSP 语言服务器
│
└── 构建 & 部署
├── go build — 编译(内置)
├── goreleaser — 多平台发布
└── Docker 多阶段构建推荐项目结构
myapp/
├── cmd/ # 可执行程序入口
│ ├── server/
│ │ └── main.go
│ └── worker/
│ └── main.go
│
├── internal/ # 私有代码(外部包无法导入)
│ ├── handler/ # HTTP/gRPC 处理层
│ ├── service/ # 业务逻辑层
│ ├── repository/ # 数据访问层
│ ├── model/ # 数据模型
│ └── middleware/ # 中间件
│
├── pkg/ # 可被外部导入的公共库
│ ├── logger/
│ ├── config/
│ └── errors/
│
├── api/ # API 定义(proto / OpenAPI)
│ └── proto/
│
├── config/ # 配置文件
│ ├── config.yaml
│ └── config.prod.yaml
│
├── scripts/ # 构建、部署脚本
├── docs/ # 文档
├── Makefile
├── Dockerfile
├── go.mod
└── go.sumMakefile 最佳实践
makefile
# Makefile
.PHONY: all build test lint clean docker
APP_NAME := myapp
VERSION := $(shell git describe --tags --always --dirty)
LDFLAGS := -ldflags "-X main.Version=$(VERSION) -s -w"
# 默认目标
all: lint test build
# 构建
build:
go build $(LDFLAGS) -o bin/$(APP_NAME) ./cmd/server
# 测试
test:
go test -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
# 基准测试
bench:
go test -bench=. -benchmem ./...
# 代码检查
lint:
golangci-lint run ./...
go vet ./...
# 格式化
fmt:
gofmt -s -w .
goimports -w .
# 生成代码(proto、mock 等)
generate:
go generate ./...
# 清理
clean:
rm -rf bin/ coverage.out coverage.html
# Docker 构建
docker:
docker build -t $(APP_NAME):$(VERSION) .
# 热重载开发
dev:
air
# 数据库迁移
migrate-up:
goose -dir migrations postgres "$(DATABASE_URL)" up
migrate-down:
goose -dir migrations postgres "$(DATABASE_URL)" downgolangci-lint 配置
yaml
# .golangci.yml
run:
timeout: 5m
go: "1.22"
linters:
enable:
- errcheck # 检查未处理的错误
- gosimple # 简化代码建议
- govet # go vet 检查
- ineffassign # 无效赋值
- staticcheck # 静态分析
- unused # 未使用的代码
- gofmt # 格式检查
- goimports # import 排序
- misspell # 拼写检查
- revive # 代码风格
- gosec # 安全检查
- bodyclose # HTTP body 关闭检查
- noctx # HTTP 请求缺少 context
- prealloc # slice 预分配建议
linters-settings:
errcheck:
check-type-assertions: true
govet:
enable-all: true
revive:
rules:
- name: exported
arguments:
- "checkPrivateReceivers"
issues:
exclude-rules:
- path: _test\.go
linters:
- gosec
- errcheckDocker 多阶段构建
dockerfile
# Dockerfile
# 构建阶段
FROM golang:1.22-alpine AS builder
WORKDIR /app
# 先复制依赖文件,利用 Docker 缓存
COPY go.mod go.sum ./
RUN go mod download
# 复制源码并构建
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
-ldflags="-s -w" \
-o /app/server \
./cmd/server
# 运行阶段(极小镜像)
FROM gcr.io/distroless/static-debian12
WORKDIR /app
COPY --from=builder /app/server .
COPY --from=builder /app/config ./config
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/app/server"]