15分钟学 Go 第 52 天 :发布与版本控制
第52天:发布与版本控制
一、学习目标
学习项目 | 掌握程度 | 应用场景 |
---|---|---|
语义化版本 | 深入理解 | 项目版本号管理 |
Go Modules | 熟练应用 | 依赖管理 |
持续集成 | 基础掌握 | 自动化构建与测试 |
发布流程 | 熟练应用 | 项目打包与发布 |
版本控制 | 深入理解 | 代码管理与协作 |
二、版本管理实践
让我们通过一个实际的项目来学习版本管理:
myapp/
├── .github/
│ └── workflows/
│ ├── build.yml
│ └── release.yml
├── cmd/
│ └── myapp/
│ └── main.go
├── internal/
│ ├── api/
│ │ └── handler.go
│ ├── config/
│ │ └── config.go
│ └── version/
│ └── version.go
├── pkg/
│ └── utils/
│ └── utils.go
├── Makefile
├── go.mod
├── go.sum
└── README.md
首先,让我们创建版本管理相关的代码:
// internal/version/version.go
package version
import (
"fmt"
"runtime"
)
var (
// Version 应用版本号
Version = "v0.1.0"
// GitCommit Git提交hash
GitCommit = ""
// BuildTime 构建时间
BuildTime = ""
// GoVersion Go版本
GoVersion = runtime.Version()
// Platform 运行平台
Platform = fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
)
// Info 版本信息结构
type Info struct {
Version string `json:"version"`
GitCommit string `json:"git_commit"`
BuildTime string `json:"build_time"`
GoVersion string `json:"go_version"`
Platform string `json:"platform"`
}
// GetVersion 获取版本信息
func GetVersion() Info {
return Info{
Version: Version,
GitCommit: GitCommit,
BuildTime: BuildTime,
GoVersion: GoVersion,
Platform: Platform,
}
}
// String 返回格式化的版本信息
func (i Info) String() string {
return fmt.Sprintf(
"Version: %s\nGit Commit: %s\nBuild Time: %s\nGo Version: %s\nPlatform: %s",
i.Version,
i.GitCommit,
i.BuildTime,
i.GoVersion,
i.Platform,
)
}
接下来创建主程序:
// cmd/myapp/main.go
package main
import (
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"os"
"myapp/internal/version"
)
var (
showVersion = flag.Bool("version", false, "Show version information")
port = flag.Int("port", 8080, "Server port")
)
func main() {
flag.Parse()
// 显示版本信息
if *showVersion {
fmt.Println(version.GetVersion())
os.Exit(0)
}
// 设置路由
http.HandleFunc("/", handleRoot)
http.HandleFunc("/version", handleVersion)
// 启动服务器
addr := fmt.Sprintf(":%d", *port)
log.Printf("Starting server on %s", addr)
if err := http.ListenAndServe(addr, nil); err != nil {
log.Fatal(err)
}
}
func handleRoot(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to MyApp!")
}
func handleVersion(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(version.GetVersion())
}
创建Makefile用于构建和发布:
# 变量定义
BINARY=myapp
VERSION=$(shell git describe --tags --always)
COMMIT_SHA=$(shell git rev-parse --short HEAD)
BUILD_TIME=$(shell date -u '+%Y-%m-%d_%H:%M:%S')
LDFLAGS=-ldflags "-X myapp/internal/version.Version=${VERSION} -X myapp/internal/version.GitCommit=${COMMIT_SHA} -X myapp/internal/version.BuildTime=${BUILD_TIME}"
# 默认目标
.PHONY: all
all: clean build
# 清理构建目录
.PHONY: clean
clean:
rm -rf build/
rm -f ${BINARY}
# 运行测试
.PHONY: test
test:
go test -v ./...
# 运行基准测试
.PHONY: bench
bench:
go test -bench=. ./...
# 检查代码风格
.PHONY: lint
lint:
golangci-lint run
# 构建应用
.PHONY: build
build:
go build ${LDFLAGS} -o ${BINARY} cmd/myapp/main.go
# 安装应用
.PHONY: install
install:
go install ${LDFLAGS} ./cmd/myapp
# 构建所有平台
.PHONY: build-all
build-all:
# Linux
GOOS=linux GOARCH=amd64 go build ${LDFLAGS} -o build/${BINARY}-linux-amd64 cmd/myapp/main.go
GOOS=linux GOARCH=arm64 go build ${LDFLAGS} -o build/${BINARY}-linux-arm64 cmd/myapp/main.go
# MacOS
GOOS=darwin GOARCH=amd64 go build ${LDFLAGS} -o build/${BINARY}-darwin-amd64 cmd/myapp/main.go
GOOS=darwin GOARCH=arm64 go build ${LDFLAGS} -o build/${BINARY}-darwin-arm64 cmd/myapp/main.go
# Windows
GOOS=windows GOARCH=amd64 go build ${LDFLAGS} -o build/${BINARY}-windows-amd64.exe cmd/myapp/main.go
# 创建发布包
.PHONY: release
release: build-all
cd build && \
tar czf ${BINARY}-linux-amd64.tar.gz ${BINARY}-linux-amd64 && \
tar czf ${BINARY}-linux-arm64.tar.gz ${BINARY}-linux-arm64 && \
tar czf ${BINARY}-darwin-amd64.tar.gz ${BINARY}-darwin-amd64 && \
tar czf ${BINARY}-darwin-arm64.tar.gz ${BINARY}-darwin-arm64 && \
zip ${BINARY}-windows-amd64.zip ${BINARY}-windows-amd64.exe
# 运行应用
.PHONY: run
run: build
./${BINARY}
# 生成版本信息
.PHONY: version
version:
@echo "Version: ${VERSION}"
@echo "Commit: ${COMMIT_SHA}"
@echo "Build Time: ${BUILD_TIME}"
创建GitHub Actions工作流:
# .github/workflows/build.yml
name: Build and Test
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.19
- name: Install dependencies
run: |
go mod download
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
- name: Run linter
run: make lint
- name: Run tests
run: make test
- name: Build
run: make build
---
# .github/workflows/release.yml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.19
- name: Build release artifacts
run: make release
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: |
build/*.tar.gz
build/*.zip
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
让我们创建一个流程图来说明发布流程:
三、版本管理规范
1. 语义化版本
版本号组成 | 说明 | 示例 |
---|---|---|
主版本号 | 不兼容的API修改 | v1.0.0 |
次版本号 | 向下兼容的功能性新增 | v1.1.0 |
修订号 | 向下兼容的问题修正 | v1.1.1 |
先行版本号 | 预发布版本标识 | v1.0.0-alpha.1 |
2. 发布类型
发布类型 | 说明 | 使用场景 |
---|---|---|
主版本发布 | 重大更新 | API破坏性变更 |
特性发布 | 新功能发布 | 新增功能特性 |
补丁发布 | 问题修复 | Bug修复 |
预发布 | 测试版本 | 功能预览 |
3. 标签管理
# 创建标签
git tag -a v1.0.0 -m "Release version 1.0.0"
# 推送标签
git push origin v1.0.0
# 查看标签
git tag -l
# 删除标签
git tag -d v1.0.0
git push origin :v1.0.0
四、模块管理
1. go.mod 文件
module myapp
go 1.19
require (
github.com/gin-gonic/gin v1.9.1
github.com/spf13/viper v1.16.0
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.24.0
)
// 替换本地模块
replace myapp/internal/api => ./internal/api
// 排除特定版本
exclude github.com/old/package v1.0.0
2. 依赖管理命令
# 初始化新模块
go mod init myapp
# 下载依赖
go mod download
# 整理依赖
go mod tidy
# 验证依赖
go mod verify
# 列出依赖
go list -m all
# 更新依赖
go get -u ./...
3. 工作区管理
// go.work
go 1.19
use (
.
./pkg/utils
./internal/api
)
replace (
myapp/pkg/utils => ./pkg/utils
myapp/internal/api => ./internal/api
)
五、项目文档
1. API文档生成
让我们创建一个API文档生成示例:
// internal/api/handler.go
package api
import (
"net/http"
"github.com/swaggo/swag/example/basic/api"
)
// @title MyApp API
// @version 1.0
// @description This is a sample server for MyApp.
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.url http://www.example.com/support
// @contact.email support@example.com
// @license.name MIT
// @license.url https://opensource.org/licenses/MIT
// @host localhost:8080
// @BasePath /api/v1
type Handler struct {}
// GetVersion godoc
// @Summary Get version information
// @Description get version info
// @Tags version
// @Accept json
// @Produce json
// @Success 200 {object} version.Info
// @Router /version [get]
func (h *Handler) GetVersion(w http.ResponseWriter, r *http.Request) {
// Implementation...
}
// CreateUser godoc
// @Summary Create a new user
// @Description create new user
// @Tags users
// @Accept json
// @Produce json
// @Param user body User true "User object"
// @Success 201 {object} User
// @Failure 400 {object} Error
// @Router /users [post]
func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) {
// Implementation...
}
// User represents the user model
type User struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password,omitempty"`
}
// Error represents an error response
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
}
六、发布检查清单
1. 发布前检查
检查项 | 说明 | 验证方法 |
---|---|---|
单元测试 | 确保所有测试通过 | make test |
代码质量 | 检查代码风格 | make lint |
依赖更新 | 检查依赖是否最新 | go list -u -m all |
文档更新 | 确保文档同步更新 | 手动检查 |
性能测试 | 验证性能指标 | make bench |
2. 发布步骤
-
代码准备
# 更新主分支 git checkout main git pull origin main # 创建发布分支 git checkout -b release/v1.0.0 # 更新版本号 # 编辑 internal/version/version.go
-
测试验证
# 运行测试 make test # 构建验证 make build-all
-
创建发布
# 创建标签 git tag -a v1.0.0 -m "Release version 1.0.0" # 推送标签 git push origin v1.0.0
-
发布确认
- 确认 GitHub Actions 工作流完成
- 验证发布包
- 更新文档
- 发布公告
七、最佳实践建议
-
版本管理
- 严格遵循语义化版本
- 保持更新日志同步
- 合理使用预发布版本
- 做好版本标签管理
-
发布流程
- 自动化构建和测试
- 统一的发布流程
- 完善的文档更新
- 做好发布通知
-
维护建议
- 及时响应问题报告
- 定期更新依赖
- 保持文档最新
- 做好版本维护
总结
本节课程我们学习了项目的发布和版本控制管理,主要内容包括:
- 语义化版本管理
- 模块依赖管理
- 自动化构建和发布
- 文档维护
- 最佳实践建议
建议在实际项目中:
- 建立规范的版本管理流程
- 使用自动化工具提高效率
- 保持良好的文档习惯
- 重视质量控制
怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!