go包名禁用标准库名(如log)、避免宽泛词(如util)、须小写单数无下划线、同一模块内包名唯一;测试包用xxx_test,需显式重命名冲突导入。

Go 包名不能叫 log、http、json 等标准库名字
编译会通过,但 import 时会覆盖标准库,导致 log.Println 调不到原生函数,或 http.ServeMux 找不到类型定义。这不是冲突报错,而是静默覆盖——你写的 log 包一旦被同目录其他文件 import,整个模块里所有对 log 的引用都会指向你的包。
- 常见翻车场景:新建项目想封装日志,随手建
log/目录,放个log.go,再在go.mod里声明module myproj/log - 标准库包名列表以
go list std输出为准,包括fmt、os、io、sync、time等 40+ 个,建议直接查,别凭记忆 - 别以为加前缀就安全,比如
mylog没问题,但logv2或log_ext仍可能让团队误判,不如直接叫logger
包名别用 util、common、base 这类宽泛词
这类名字不表达职责,导致后续没人敢往里加新功能(怕“污染”),也不敢删旧代码(怕别人偷偷依赖),最后变成无人维护的黑洞。更重要的是,Go 的包导入路径就是包名来源,github.com/you/proj/util 这种路径会让调用方写 util.DoX(),完全看不出逻辑归属。
- 优先按领域或功能命名:
payment、notify、cache,哪怕初期只有 2 个文件 - 如果真要抽象工具函数,按用途拆:比如时间处理放
timeutil,字符串处理放strutil,而不是全塞进一个util - 包名小写、单数、无下划线,
config可以,configs或my_config不推荐
同一模块内包名不能重复,即使路径不同
Go 编译器认的是包名(package xxx 声明),不是目录路径。比如 internal/a/log/log.go 和 internal/b/log/log.go 都声明 package log,构建时会报 duplicate package "log",哪怕它们物理路径完全不同。
- 错误常发生在重构时:把原
log包拆成多个子包,但忘了改package声明 - 解决办法只有两个:统一改成带前缀的包名(如
alog、blogger),或用语义化子包(log/writer、log/rotate),主包仍叫log,子包用package writer -
go list -f '{{.Name}}' ./...可快速扫出当前模块所有包名,人工去重比靠报错更省时间
测试文件里的 package xxx_test 不算新包名,但要注意导入歧义
xxx_test 是合法且推荐的测试包声明方式,它不会和 package xxx 冲突。但如果你在 xxx_test.go 里又 import 了同名包(比如自己写了 log 包并 import 它),而测试文件本身是 package log_test,那 log 就既指标准库,又指你自己的包,Go 会优先解析为当前模块内的 log,导致测试跑不通。
立即学习“go语言免费学习笔记(深入)”;
- 测试文件中若需用标准库
log,显式重命名导入:import stdlog "log" - 避免在测试文件里 import 和自身包名相同的自定义包,比如
cache/cache_test.go里 import"myproj/cache"—— 这容易引发循环引用或解析混乱 - 测试包名唯一作用是隔离标识,不参与构建产物,所以不用纠结它是否“好听”,保持
xxx_test即可
util,其他人看见就跟着仿,一两个月后满项目都是 util、utils、common_util,改起来得逐个 grep + 手动 rename。










