--style go_zero 和 gozero 到底差在哪?一句话:它只决定「代码生成出来后,文件名怎么拼写」,跟代码里的结构体名、函数名、变量名一点关系都没有。gozero 是默认,连写小写;go_zero 是蛇形,带下划线。这篇把它的机制、真实产物差异、常见误区一次讲清。
--style 只改「文件名」,不改「代码内容」go-zero 的代码生成器(goctl)在落盘文件时,会用 --style 指定的「命名格式符」重新拼写文件名。它本身是个纯字符串格式化器,完全不碰 .go 文件里的任何标识符。
记得住的三行:
① gozero(默认)= 小写连写,无分隔符 → 生成的文件叫 loginhandler.go、usermodel_gen.go。
② go_zero = 蛇形,下划线分隔 → 生成的文件叫 login_handler.go、user_model_gen.go。
③ 两种风格下,文件里的 Go 代码一模一样:结构体仍叫 LoginLogic、UserModel(PascalCase),因为那些来自 ToCamel(),与 style 无关。
tools/goctl/config/config.go 里写死 DefaultFormat = "gozero"(默认是 gozero);NamingFormat 字段注释原文是「define the naming format of the generated file name」——明确只针对「文件名」。go-zero 没有发明一堆风格名词,而是用 go 和 zero 两个「格式字符」当占位符,让你自己拼出想要的文件名风格。
任意合法风格符都能拆成 [go 部分][分隔符][zero 部分]:
go 小写 / Go 首字母大写 / GO 全大写)。_ 下划线 / - 横线 / # 任意字符 / 什么都不写就直接连)。go_zero_,zero=小写 → 蛇形(snake_case)goZerogozerogo-zero / GOZERO / Go#zero# 分隔go 或 zero、顺序颠倒的 gOZero、以及 goZEro / goZERo / goZeRo / foo 都会报错。规则是:必须同时含 go 和 zero,且 go 在 zero 前面,每个部分只能整段同大小写。welcome_to_go_zero,不同风格输出什么这是 go-zero 官方文档给的标准示例表。看一眼就懂「风格符」到底在格式化什么。
| 风格符(--style) | 格式化结果 | 说明 |
|---|---|---|
gozero 默认 | welcometogozero | 全小写、无分隔(lowercase) |
goZero | welcomeToGoZero | 首词小写、其余首字母大写(camelCase) |
go_zero | welcome_to_go_zero | 全小写、下划线分隔(snake_case) |
go-zero | welcome-to-go-zero | 横线分隔(kebab-case) |
GOZERO | WELCOMETOGOZERO | 全大写(UPPERCASE) |
Go#zero | Welcome#to#go#zero | 自定义分隔符 #,首词首字母大写 |
welcome_to_go_zero(已经是蛇形)。格式器的工作是:先按 _ 和大写字母把串切成词,再按风格符重新拼回去。所以它本质是「基于 snake 或 camel 串的二次格式化」。format.FileNamingFormat 是怎么干的源码位置 tools/goctl/util/format/format.go。一句话流程:切词 → 首词按 go 风格、其余按 zero 风格 → 用 through 分隔符拼接。
_ 和大写字母。这也是为什么 go_zero 能在 loginHandler 的 H 处把下划线插进去——生成器喂给格式器的就是 loginHandler(首字母大写),词边界天然存在。@handler login,两种风格生成的文件名这是你平时最能直观看到的区别。左 gozero(默认),右 go_zero。同一个接口,文件名拼写不同,但里面的代码完全一致。
--style gozero(默认)--style go_zero--style gozero--style go_zerogo_zero 只是在「基础名」和「后缀」之间插了个下划线。所以用 go_zero 你会看到 login_handler.go,用默认 gozero 看到 loginhandler.go——后缀本身都在,只是有没有下划线连接的区别。这是最大的误区:有人以为 --style go_zero 会让结构体也变成蛇形。不会。文件名怎么拼,和代码里怎么命名,是两件事。
在 goctl model 的 gencustom 里,结构体名来自:
"upperStartCamelObject": in.Name.ToCamel(), // 表名 → UserModel(PascalCase) "lowerStartCamelObject": stringx.From(in.Name.ToCamel()).Untitle(),
而文件名走的是另一条路:
modelFilename, _ := format.FileNamingFormat(g.cfg.NamingFormat, fmt.Sprintf("%s_model", tn.Source())) // 只影响文件名 name := util.SafeString(modelFilename) + "_gen.go"
看得很清楚:struct 名走 ToCamel()(永远 PascalCase),文件名走 FileNamingFormat()(受 style 控制)。两者完全独立。
| 受影响? | gozero | go_zero |
|---|---|---|
| 磁盘文件名 | loginhandler.go | login_handler.go |
| 结构体 / 类型名 | LoginLogic / UserModel | LoginLogic / UserModel(一样) |
| 函数 / 方法名 | NewServiceContext | NewServiceContext(一样) |
| 包名(package) | handler / logic | handler / logic(一样) |
--style凡是会「落盘生成 .go 文件」的命令,基本都能接 --style。
| 命令 | 效果 |
|---|---|
goctl api go / new / plugin | handler / logic / types / config / svc / main 等文件名 |
goctl rpc protoc / proto | pb.go / 服务端 .go 文件名 |
goctl model mysql datasource / ddl | model 文件名(user_model_gen.go 这类) |
goctl model pg datasource | PostgreSQL model 文件名 |
goctl model mongo | Mongo model 文件名 |
goctl docker / kube deploy | Dockerfile / k8s yaml 相关命名 |
--style 控制文件名风格。它不影响你已经手写的代码,只作用于本次新生成的部分。三种姿势:命令行每次指定、写进 goctl.yaml 固定默认、注意版本间默认值的差异。
# API:默认 gozero goctl api go -api user.api -dir . --style gozero # API:想要下划线文件名 goctl api go -api user.api -dir . --style go_zero # Model:表名带下划线 goctl model mysql datasource \ -url="root:pass@tcp(127.0.0.1:3306)/db" \ -table="*" -dir ./model --style go_zero
goctl.yaml,全项目固定默认在项目根目录放一个 goctl.yaml,以后不用每条命令都带 --style:
# goctl.yaml(项目根目录)
namingFormat: go_zero
goctl 启动时会读这个文件,namingFormat 即默认风格符。这样团队所有人生成出来文件名风格一致。
go_zero」。那是过时/错误的。以当前 go-zero 源码为准:DefaultFormat = "gozero",默认就是连写小写。如果你看到别人仓库里文件名带下划线,那是对方显式传了 --style go_zero 或配了 goctl.yaml,不是默认行为。login_handler.go 就以为「go-zero 强制文件带下划线后缀」。错——那只是对方选了 go_zero 风格;用默认 gozero 生成出来是 loginhandler.go,一样能编译、一样能跑。核心结论:--style 是 goctl 的「文件名拼写器」,只改落在磁盘上的文件名。gozero(默认)= 小写连写无分隔;go_zero = 下划线蛇形。两者都不碰代码里的结构体/函数名(那些永远按 Go 规范 PascalCase)。