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 天前
Go语言中的defer,panic,recover 与错误处理
golang·go
桃园码工2 天前
1-Gin介绍与环境搭建 --[Gin 框架入门精讲与实战案例]
go·gin·环境搭建
云中谷2 天前
Golang 神器!go-decorator 一行注释搞定装饰器,v0.22版本发布
go·敏捷开发
苏三有春3 天前
五分钟学会如何在GitHub上自动化部署个人博客(hugo框架 + stack主题)
git·go·github
我是前端小学生3 天前
Go语言中的方法和函数
go
探索云原生3 天前
在 K8S 中创建 Pod 是如何使用到 GPU 的: nvidia device plugin 源码分析
ai·云原生·kubernetes·go·gpu
自在的LEE4 天前
当 Go 遇上 Windows:15.625ms 的时间更新困局
后端·kubernetes·go
Gvto5 天前
使用FakeSMTP创建本地SMTP服务器接收邮件具体实现。
go·smtp·mailtrap
白泽来了5 天前
【Go进阶】手写 Go websocket 库(一)|WebSocket 通信协议
开源·go
witton5 天前
将VSCode配置成Goland的视觉效果
ide·vscode·编辑器·go·字体·c/c++·goland