Skip to content

工程化全景

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.sum

Makefile 最佳实践

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)" down

golangci-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
        - errcheck

Docker 多阶段构建

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"]

各工具详细文档

本站内容由 褚成志 整理编写,仅供学习参考