gofmt不能直接格式化JSON/YAML配置文件,它仅支持.go文件,处理非Go文件会报“cannot format non-Go files”错误;应使用gojq处理JSON、yq处理YAML,并通过脚本按扩展名分发调用。

gofmt 能不能直接格式化 JSON/YAML 配置文件
gofmt 只处理 .go 文件,对 config.json、settings.yaml 之类完全无感。硬塞进去会报错:cannot format non-Go files。它不识别非 Go 语法,也不提供插件机制扩展支持。想靠它统一格式化项目里所有配置文件,这条路走不通。
用 gojq 或 yq 处理 JSON/YAML 的实操要点
真正能落地的方式是组合命令行工具:对 JSON 用 gojq(比 jq 更轻、纯 Go 实现、无 libc 依赖),对 YAML 用 yq(v4+ 版本基于 go-yq,不是 Python 那个)。它们都支持 in-place 格式化:
-
gojq -n -f /dev/stdin tmp.json && mv tmp.json config.json—— 但更推荐用gojq --indent 2 . config.json > tmp.json再替换,避免空文件风险 -
yq e -P config.yaml输出美化后的 YAML;加-i参数可原地覆盖:yq -i e -P config.yaml - 注意
yq v4默认使用yaml解析器,若配置含!!python类型或自定义 tag,会失败;此时需显式加--yaml-output或换用yq v3(Python 版)
写一个统一入口脚本自动识别并格式化各类配置文件
项目根目录下放一个 format-configs.sh(或 format-configs.go),核心逻辑是按扩展名分发处理:
#!/bin/sh
find . -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" \) | while read f; do
case "$f" in
*.json) gojq --indent 2 "." "$f" > "$f.tmp" && mv "$f.tmp" "$f" ;;
*.yaml|*.yml) yq -i e -P "$f" ;;
esac
done
关键细节:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 不要用
find ... -exec直接调用yq -i,某些旧版yq在路径含空格时会崩溃 -
gojq的--indent值必须是 2/4/0,不能是""或负数,否则静默失败 - 如果项目有
.gitignore,建议在find后加-not -path "./vendor/*" -not -path "./node_modules/*"
CI 中集成时容易忽略的环境一致性问题
gojq 和 yq 的行为版本敏感。比如 yq v4.35.1 默认把 true 序列化为 true,而 v4.40.0+ 改成 True(首字母大写),导致 Git diff 暴增。解决方式只有两个:
- 在 CI 脚本里固定二进制版本:
curl -L https://github.com/mikefarah/yq/releases/download/v4.35.1/yq_linux_amd64 -o /usr/local/bin/yq - 或改用 Go 实现的轻量替代:如
ghodss/yaml+encoding/json写个最小化格式化工具,编译后嵌入项目/scripts/format-configs,彻底规避外部工具链漂移
真正的麻烦不在语法,而在不同团队成员本地用的 yq 版本不一致,一次 git commit 就触发全量重排 —— 这种情况比格式本身更消耗协作成本。

















