Go 更强的代码洁癖,可以把 gofmt 给换了!

大家好,我是煎鱼。

我们从一开始写 Go 代码和应用,就会被各种官方和民间教程,甚至 IDE 教导我们必须配一个 Gofmt 工具。他能够格式化 Go 程序的代码。会使用制表符表示缩进,空白表示对齐。

这解决了程序员届的老大难问题之一,代码格式上的规范问题。有效的提高了 Go 代码的阅读的友好度和减少了同事间的 ****。非常值得认可。

但有时候,还是会看到一些糟心的代码,总会觉得 Gofmt,还是格式化的不够。

今天给大家分享我发现的一个更狠的工具:gofumpt,例子主要基于官方文档。

更强的格式化:gofumpt

Gofumpt 会执行比 gofmt 更严格的 Go 格式规范。同时确保向后兼容。

该工具是 Go 1.21 的 gofmt 分支,需要 Go 1.20 或更高版本。它可以直接替代现有的 Go 代码格式化,也就是在 gofumpt 之后运行 gofmt 不会产生任何新的变化。

安装命令:

shell 复制代码
$ go install mvdan.cc/gofumpt@latest

执行命令:

shell 复制代码
$ gofumpt -l -w .
main.go

再查看对应被格式化的文件就已经生效了。

以下是一些更具体的 gofmt 和 gofumpt 的区别例子。能够很好的帮助大家识别其中的差异。

赋值运算符后无空行

原本由 gofmt 格式化后:

go 复制代码
func foo() string {
	foo :=
		"脑子进煎鱼了!"
	return foo
}

改为 gofumpt 格式化后:

go 复制代码
func foo() string {
	foo := "脑子进煎鱼了!"
	return foo
}

函数体周围无空行

原本由 gofmt 格式化后:

go 复制代码
func foo() {

	println("煎鱼进脑子了!")

}

改为 gofumpt 格式化后:

go 复制代码
func foo() {
	println("煎鱼进脑子了!")
}

函数应分隔 ) { ,缩进有助于提高可读性

原本由 gofmt 格式化后:

go 复制代码
func foo(s string,
	i int) {
	println("煎鱼!!!")
}

// 使用空行会稍微好一些,但仍然不够好
func bar(s string,
	i int) {

	println("煎鱼!!!")
}

改为 gofumpt 格式化后:

go 复制代码
func foo(s string,
	i int,
) {
	println("煎鱼!!!")
}

func bar(s string,
	i int,
) {
	println("煎鱼!!!")
}

代码块中的单独语句(或注释)周围没有空行

原本由 gofmt 格式化后:

go 复制代码
if err != nil {

	return err
}

改为 gofumpt 格式化后:

go 复制代码
if err != nil {
	return err
}

简单错误检查前无空行

原本由 gofmt 格式化后:

go 复制代码
foo, err := processFoo()

if err != nil {
	return err
}

改为 gofumpt 格式化后:

go 复制代码
foo, err := processFoo()
if err != nil {
	return err
}

复合字面量应统一使用换行符

原本由 gofmt 格式化后:

go 复制代码
var ints = []int{1, 2,
	3, 4}

var matrix = [][]int{
	{1},
	{2}, {
		3,
	},
}

改为 gofumpt 格式化后:

go 复制代码
var ints = []int{
	1, 2,
	3, 4,
}

var matrix = [][]int{
	{1},
	{2},
	{
		3,
	},
}

空字段列表应使用单行

原本由 gofmt 格式化后:

go 复制代码
var V interface {
} = 3

type T struct {
}

func F(
)

改为 gofumpt 格式化后:

go 复制代码
var V interface{} = 3

type T struct{}

func F()

标准库导入必须在顶部单独分组

原本由 gofmt 格式化后:

go 复制代码
import (
	"foo.com/bar"

	"io"

	"io/ioutil"
)

改为 gofumpt 格式化后:

go 复制代码
import (
	"io"
	"io/ioutil"

	"foo.com/bar"
)

短 case 子句应占一行

原本由 gofmt 格式化后:

go 复制代码
switch c {
case 'a', 'b',
	'c', 'd':
}

改为 gofumpt 格式化后:

go 复制代码
switch c {
case 'a', 'b', 'c', 'd':
}

多行顶层声明必须用空行隔开

原本由 gofmt 格式化后:

go 复制代码
func foo() {
	println("煎鱼!")
}
func bar() {
	println("煎鱼!")
}

改为 gofumpt 格式化后:

go 复制代码
func foo() {
	println("煎鱼!")
}

func bar() {
	println("煎鱼!")
}

单个 var 声明不应使用括号分组

原本由 gofmt 格式化后:

go 复制代码
var (
	foo = "煎鱼!"
)

改为 gofumpt 格式化后:

go 复制代码
var foo = "煎鱼!"

连续的顶层声明应归为一组

原本由 gofmt 格式化后:

go 复制代码
var nicer = "x"
var with = "y"
var alignment = "z"

改为 gofumpt 格式化后:

go 复制代码
var (
	nicer     = "x"
	with      = "y"
	alignment = "z"
)

简单的 var 声明语句应使用短赋值

原本由 gofmt 格式化后:

go 复制代码
var s = "煎鱼进脑子了"

改为 gofumpt 格式化后:

go 复制代码
s := "煎鱼进脑子了"

默认启用 -s 代码简化标记。

非 Go 指令的注释应以空格开头

原本由 gofmt 格式化后:

csharp 复制代码
//go:noinline

//Foo is awesome.
func Foo() {}

改为 gofumpt 格式化后:

go 复制代码
//go:noinline

// Foo is awesome.
func Foo() {}

VSCode 配置

可以直接在 IDE 中进行配置。例如 VSCode,可以配置对应的 settings.json 为如下:

json 复制代码
{
    "go.useLanguageServer": true,
    "gopls": {
        "formatting.gofumpt": true,
    },
}

就可以直接在 Go 应用中用起来了。

总结

之前我有一个朋友,接手了一个老项目。那位同学,几乎没有什么代码规范的风格。全靠 gofmt 来帮他格式化。

但你们也看到,gofmt 只做了最基本的。这种时候如果有更严格的 Go 代码格式化工具 gofumpt 是非常不错的。(也需要引导这位同学,但容易撕逼)

像是前面提到的 "多行顶层声明必须用空行隔开" 是非常有价值的。我是真的见过一大坨不加空行都挤一起的。看起来非常难受。

希望这个更严格的 gofumpt,对大家格式化 Go 代码能有所帮助!

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

相关推荐
研究司马懿1 天前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大2 天前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰2 天前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘2 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤2 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto4 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto6 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室7 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题7 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo