直接回答:Go 业务开发的默认组合基本是 Gin 做 HTTP、GORM 做数据访问、zap 做日志,再按需加定时任务、依赖注入和协程池。选库的判断标准不是"star 多",而是维护是否活跃、依赖是否轻、出问题时能不能看懂源码——标准库能解决的,就别急着引第三方。
Web 框架:Gin
1 | r := gin.Default() |
- 适合:写 REST 接口,路由、参数绑定、中间件、校验都能覆盖,社区资料多,招人也好找。
- 注意:
gin.Context不能跨 goroutine 使用;在协程里要用c.Copy(),否则会有数据竞争。 - 替代:标准库
net/http(1.22 之后增强了路由能力)、Fiber(基于 fasthttp,性能好但生态和标准库有差异)、Echo。
如果项目接口很少、依赖想尽量少,直接用 net/http 也完全够,不用为了框架而框架。
日志:zap
1 | logger, _ := zap.NewProduction() |
zap 的核心优势是结构化日志:日志是键值对而不是拼接好的字符串,方便采集到 ELK、Loki 之后按字段检索。相比 log.Printf,性能也高得多。
使用上的两个经验:
- 开发环境用
NewDevelopment(可读),生产用NewProduction(JSON 格式),通过配置切换; - 别把日志当业务数据源。需要统计的字段落到数据库或埋点系统里,日志只用于排查。
替代方案是 logrus(更直观,但性能弱于 zap)和 Go 1.21 起的标准库 log/slog(标准库、够用,新项目值得优先考虑)。
JSON:jsoniter
标准库 encoding/json 已经够稳,jsoniter 的价值在于大流量场景下的序列化开销。它的 API 和标准库兼容,替换成本很低:
1 | import jsoniter "github.com/json-iterator/go" |
经验是:先测再用。接口 QPS 不高、JSON 不大时,标准库和它的差距可以忽略,多一个依赖反而不划算。真到了 CPU 大部分花在序列化上的时候再换。
数据访问:GORM
1 | db.Where("status = ?", 1).Order("id desc").Limit(20).Find(&orders) |
- 适合常规 CRUD,关联、钩子、自动迁移都能省不少代码;
- 注意点:批量写入要用
CreateInBatches;Find到结构体切片时记得初始化 slice;关联保存有隐式行为,容易多写或多查;复杂查询该写原生 SQL 就写,别硬凑。 - 替代:
sqlx(更贴近 SQL)、ent(代码生成、类型安全)、sqlc(写 SQL 生成代码)。
对 SQL 控制欲强的团队,sqlc 或 sqlx 往往比 ORM 更省心;但业务迭代快、表结构常变时,ORM 的开发效率优势明显。
定时任务:robfig/cron
1 | c := cron.New() |
单机定时任务用它足够,支持标准 cron 表达式(默认 5 段,秒级要用 cron.WithSeconds())。
两个必须注意的点:
- 多实例部署会重复执行。要么用分布式锁(Redis、etcd)保证只有一个实例跑,要么干脆把定时任务拆成独立服务;
- 任务要自己兜住 panic 和超时,否则一次卡死会影响后面的调度。
分布式的替代方案是 xxl-job、asynq(基于 Redis)这类带管理界面的调度系统。
依赖注入:wire
wire 用代码生成代替运行时反射:你写 wire.go 声明依赖关系,它生成组装代码。好处是启动快、依赖关系在编译期就能发现错误;代价是多人协作时要理解它的写法,增删依赖要重新生成。
1 | func InitApp() (*App, error) { |
项目依赖层次不深的时候,手动组装其实更直观。wire 的价值在依赖多、初始化流程长的中大型项目里。
协程池:ants
1 | p, _ := ants.NewPool(200) |
无限制地 go func() 会在任务量突增时把内存和下游连接数打满。协程池把并发度限制在可控范围内,适合"任务量不可预测、每个任务开销又不小"的场景。
如果任务是阻塞 IO 且数量固定,用带缓冲的 channel 做信号量往往更简单:
1 | sem := make(chan struct{}, 200) |
选型原则
- 标准库优先:
net/http、log/slog、encoding/json能覆盖就别引依赖; - 看维护状态:最近一年有没有提交、issue 有没有人回,比 star 数重要;
- 依赖要少:一个库带进来十几个传递依赖时,先想想值不值;
- 可替换性:把第三方库挡在一层自己的接口后面,换库时才不用改遍全站。
本文整理自我自己早先收集的一份 Go 库清单,按用途重新分类并补上了选型判断和实践注意点,文字由 AI 协助改写后经我复核。各库的具体用法以官方文档为准。
这篇笔记整理自我自己的实践记录,如果做法有出入,或者你踩过别的坑,欢迎到留言板一起聊聊。