Go 更強的代碼潔癖,可以把 gofmt 給換了!

大家好,我是煎魚。

我們從一開始寫 Go 代碼和應用,就會被各種官方和民間教程,甚至 IDE 教導我們必須配一個 gofmt 工具。他能夠格式化 Go 程序的代碼。會使用製表符表示縮進,空白表示對齊。

這解決了程序員屆的老大難問題之一,代碼格式上的規範問題。有效的提高了 Go 代碼的閱讀的友好度和減少了同事間的 ****。非常值得認可。

但有時候,還是會看到一些糟心的代碼,總會覺得 gofmt,還是格式化的不夠。

今天給大家分享我發現的一個更狠的工具:gofumpt,例子主要基於官方文檔。

更強的格式化:gofumpt

Gofumpt 會執行比 gofmt 更嚴格的 Go 格式規範。同時確保向後兼容。

該工具是 Go 1.21 的 gofmt 分支,需要 Go 1.20 或更高版本。它可以直接替代現有的 Go 代碼格式化,也就是在 gofumpt 之後運行 gofmt 不會產生任何新的變化。

安裝命令:

$ go install mvdan.cc/gofumpt@latest

執行命令:

$ gofumpt -l -w .
main.go

再查看對應被格式化的文件就已經生效了。

以下是一些更具體的 gofmt 和 gofumpt 的區別例子。能夠很好的幫助大家識別其中的差異。

賦值運算符後無空行

原本由 gofmt 格式化後:

func foo() string {
 foo :=
  "腦子進煎魚了!"
 return foo
}

改爲 gofumpt 格式化後:

func foo() string {
 foo := "腦子進煎魚了!"
 return foo
}

函數體周圍無空行

原本由 gofmt 格式化後:

func foo() {

 println("煎魚進腦子了!")

}

改爲 gofumpt 格式化後:

func foo() {
 println("煎魚進腦子了!")
}

函數應分隔 ) { ,縮進有助於提高可讀性

原本由 gofmt 格式化後:

func foo(s string,
 i int) {
 println("煎魚!!!")
}

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

 println("煎魚!!!")
}

改爲 gofumpt 格式化後:

func foo(s string,
 i int,
) {
 println("煎魚!!!")
}

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

代碼塊中的單獨語句(或註釋)周圍沒有空行

原本由 gofmt 格式化後:

if err != nil {

 return err
}

改爲 gofumpt 格式化後:

if err != nil {
 return err
}

簡單錯誤檢查前無空行

原本由 gofmt 格式化後:

foo, err := processFoo()

if err != nil {
 return err
}

改爲 gofumpt 格式化後:

foo, err := processFoo()
if err != nil {
 return err
}

複合字面量應統一使用換行符

原本由 gofmt 格式化後:

var ints = []int{1, 2,
 3, 4}

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

改爲 gofumpt 格式化後:

var ints = []int{
 1, 2,
 3, 4,
}

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

空字段列表應使用單行

原本由 gofmt 格式化後:

var V interface {
} = 3

type T struct {
}

func F(
)

改爲 gofumpt 格式化後:

var V interface{} = 3

type T struct{}

func F()

標準庫導入必須在頂部單獨分組

原本由 gofmt 格式化後:

import (
 "foo.com/bar"

 "io"

 "io/ioutil"
)

改爲 gofumpt 格式化後:

import (
 "io"
 "io/ioutil"

 "foo.com/bar"
)

短 case 子句應占一行

原本由 gofmt 格式化後:

switch c {
case 'a''b',
 'c''d':
}

改爲 gofumpt 格式化後:

switch c {
case 'a''b''c''d':
}

多行頂層聲明必須用空行隔開

原本由 gofmt 格式化後:

func foo() {
 println("煎魚!")
}
func bar() {
 println("煎魚!")
}

改爲 gofumpt 格式化後:

func foo() {
 println("煎魚!")
}

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

單個 var 聲明不應使用括號分組

原本由 gofmt 格式化後:

var (
 foo = "煎魚!"
)

改爲 gofumpt 格式化後:

var foo = "煎魚!"

連續的頂層聲明應歸爲一組

原本由 gofmt 格式化後:

var nicer = "x"
var with = "y"
var alignment = "z"

改爲 gofumpt 格式化後:

var (
 nicer     = "x"
 with      = "y"
 alignment = "z"
)

簡單的 var 聲明語句應使用短賦值

原本由 gofmt 格式化後:

var s = "煎魚進腦子了"

改爲 gofumpt 格式化後:

s := "煎魚進腦子了"

默認啓用 -s 代碼簡化標記。

非 Go 指令的註釋應以空格開頭

原本由 gofmt 格式化後:

//go:noinline

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

改爲 gofumpt 格式化後:

//go:noinline

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

VSCode 配置

可以直接在 IDE 中進行配置。例如 VSCode,可以配置對應的 settings.json 爲如下:

{
    "go.useLanguageServer": true,
    "gopls"{
        "formatting.gofumpt": true,
    },
}

就可以直接在 Go 應用中用起來了。

總結

之前我有一個朋友,接手了一個老項目。那位同學,幾乎沒有什麼代碼規範的風格。全靠 gofmt 來幫他格式化。

但你們也看到,gofmt 只做了最基本的。這種時候如果有更嚴格的 Go 代碼格式化工具 gofumpt 是非常不錯的。(也需要引導這位同學,但容易撕逼)

像是前面提到的 “多行頂層聲明必須用空行隔開” 是非常有價值的。我是真的見過一大坨不加空行都擠一起的。看起來非常難受。

希望這個更嚴格的 gofumpt,對大家格式化 Go 代碼能有所幫助!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/dnF3bxT0H_OfAsml9m976w