构建 Go 项目最佳实践
1. 语言
- 语言学习
- Go 语言圣经学习笔记 2017 年学习 Go 的笔记,虽然有些内容有些老旧(比如 package 管理),但语言核心的东西是没大变化
- Effective Go 精简版 比较基础的用法,教你避“坑”
- Go 的异常处理:defer,panic,recover
- 理解 Go 的 Array 和 Slice:除了理解之外,主要的记录了使用 Slice 过程中遇到的“坑”,但是 gopher 似乎不认为是个“设计缺陷”
- Go http 请求必须要手动 resp.Body.Close 基本上每个 gopher 都翻过的错,不关闭 resp.body 导致 fd 飙升
- Go MySQL 报错 closing bad idle connection: EOF 一次问题排查
- Go for…range 实际上 range 返回的都是浅拷贝,并不是迭代器
- Go 日期格式化和解析
- 外部资源 汇总
- 安装和卸载
- package 管理
- package 推荐
- The Go libraries that never failed us: 22 libraries you need to know 22 个高质量库
- Router: Echo, chi
- OpenAPI: deepmap/oapi-codegen, openapi-generator-cli
- Communication: gRPC, protoc
- Messaging: Watermill
- Database:
- SQL: sqlx, SQLBoiler, Migrations(sql-migrate, goose)
- Observability:
- Logging: logrus, zap
- Metrics and tracing: opencensus-go,
- Configuration: caarlos0/env, koanf
- Build CLI: urfave/cli
- Testing:
- Assertions: testify, go-cmp, gofakeit
- Mocking:
- Misc:
- Extra types support: google/uuid, oklog/ulid, shopspring/decimal,
- Errors: hashicorp/go-multierror
- Useful tools: samber/lo, Task
- Live code reloading: reflex
- Linter: golangci-lint, go-cleanarch
- Formatters: go fmt, goimports, gofumpt
- The Go libraries that never failed us: 22 libraries you need to know 22 个高质量库
2. 工程实践
2.1. 项目结构
Go 目前没有一个权威性质的 Web framework(类似 Python 的 Django/Flask,Java 的 SprintBoot 等),大部分 Web 框架所做的事情 是 router + middleware 的方式。并没有提供了一个如何组织项目代码,划分模块的规范。这可能与 Go 生态圈的文化和语言的应用场景有关。
尽管如此,还是需要一个规范性的东西来约束,方便协作。评价比较高的有 project-layout,它参考了主流的 Go 开源代码的组织方式, 2019 年开始我也进行了断断续续的翻译 Go 项目布局标准。现在官方也支持 中文版 了。
实际体验下来,大体思路是没错的,但对于构建一个 Web 服务来说,还是太过宽泛了。所以我根据自己的经验,在 Go project layout 的基础上整理了一套属于自己的规范。Go 项目目录结构.
2.2. 技术选型
- Web 框架 用 gin
- Redis
- logger packages,日志 level 规范(个人经验和习惯):
trace
仅仅用于调试日志,删掉无伤大雅debug
业务预期内未导致数据变更,但希望记录下来,如 List/Get 操作info
业务预期内导致了数据变更的操作,如 Create/Update/Delete 等warn
非业务预期行为,但对业务本身无任何影响,如客户端参数格式、枚举值错误等error
非业务预期行为,对业务造成影响,如写入数据库、cache、MQ 等失败fatal
非业务预期行为,影响整体业务运行,如 DB 初始化失败
- MongoDB 用官方的
- MySQL,ORM 还是使用 ent 吧
- ORM
- http client:resty
- 序列化:msgpack 说是比 JSON 的效率高五六倍,文档 https://msgpack.uptrace.dev/
- 模板渲染:
- template 官方实现
- mustache 是一个跨语言的模板定义,Go 的实现 https://github.com/hoisie/mustache
2.3. 编码规范
基本上 Go programming language 已经说的挺清楚了,Effective Go 里又有补充,加之 Go 的社区命名都比较统一,日常命名应该没啥疑惑。
如果你还想单独把编码规范抽出来,可以看下 uber 的:uber go guide。
2.4. 代码质量
- 单元测试
- 使用 golangci-lint 作为 linter,我的配置,macOS/Linux 下添加软链到
~/.golangci.yaml
2.5. 服务质量
- Prometheus 使用 Prometheus 监控 web server
- 调优