go代码规范必须基于语言设计哲学而非框架模板:gofmt和goimports是强制契约,接口需最小化,错误必须显式处理,包结构按职责分层且命名小写单数。

Go 框架开发中没有“标准框架”,所以代码规范不能套用某框架的模板——它必须基于 Go 语言本身的设计哲学落地,而不是迁就某个 Web 框架的惯用写法。
gofmt 和 goimports 是底线,不是可选项
所有 Go 项目(含框架层、中间件、handler)都必须通过 gofmt -w 和 goimports -w 处理。这两者不是“格式美化工具”,而是强制性契约:
-
gofmt决定缩进(Tab)、括号位置(if x {不换行)、操作符空格(a + b),不执行等于违反 Go 语法共识 -
goimports自动增删包、按组排序(标准库 / 第三方 / 本地),手动维护 import 列表极易出错,尤其在跨包引用频繁的框架场景下 - 编辑器保存时自动运行是唯一可靠方式;CI 中应设为失败门禁,而非 warning
接口定义必须最小化,别提前抽象 Router 或 Service
框架代码最容易犯的错,是把“框架感”当成设计目标:过早定义 Router、Service、MiddleWareChain 等大接口。这违背了 Effective Go 的核心原则——“按需定义最小接口”:
- 真正需要多态的地方才定义接口,比如不同 DB 驱动共用
Queryer,而不是为所有 handler 统一塞进Handler interface{ ServeHTTP(...) } -
http.Handler本身已足够,除非你要封装特定行为(如带 trace ID 的 wrapper),否则别另起MyHandler接口 - 框架内部组件(如配置加载、日志初始化)优先用函数或结构体字段组合,而非接口+实现,减少抽象层级
错误处理必须显式传播,禁止吞掉 error 或用 panic 替代
框架层常因“统一错误返回”误用 panic 或忽略 error,这是最危险的风格偏差:
- 任何可能失败的操作(DB 查询、配置解析、HTTP client 调用)都必须返回
error,且调用方用if err != nil显式检查——哪怕只是return nil, err -
panic仅用于程序无法继续的致命错误(如监听端口失败后退出),绝不用于业务错误(如用户参数校验失败) - 框架提供的 handler 函数签名应保持 Go 原生风格:
func(w http.ResponseWriter, r *http.Request) error比func(w http.ResponseWriter, r *http.Request)更安全,便于中间件链式错误传递
包组织按职责分层,而非按框架概念切分
别建 router/、middleware/、service/ 这类“框架目录”。Go 的包结构应反映业务边界和依赖流向:
- 顶层包(如
cmd/myapp)只负责启动、配置注入、依赖组装 - 领域逻辑放
internal/domain/(如user、order),不暴露给外部 - 基础设施适配器(DB、HTTP client、缓存)放
internal/infra/,依赖倒置:domain 层定义接口,infra 层实现 - 框架相关代码(如 Gin 封装、Echo 中间件)应尽量薄,只做胶水层,逻辑下沉到 domain 或 infra
复杂点在于:框架带来的“约定优于配置”容易掩盖真实依赖关系,容易被忽略的是——包名小写、单数、无下划线(user 不是 users),以及每个包内避免循环导入,这比选什么框架更影响长期可维护性。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











