go標準命令詳解0 9 go fmt與gofmt

2021-07-09 06:27:34 字數 4339 閱讀 9229

go fmt命令會按照go語言**規範格式化指定**包中的所有go語言原始碼檔案的**,所有go語言原始碼檔案即包括命令原始碼檔案、庫原始碼檔案和測試原始碼檔案。注意,當**包還有子**包時,子**包中的go語言原始碼檔案是不包含在內的。也就是說,go fmt命令只會格式化被直接儲存在指定**包對應目錄下的go語言原始碼檔案。

go doc命令與godoc命令的關係一樣,go fmt命令也是gofmt命令的簡單封裝。go fmt命令本身可以接受兩個標記。標記-n僅僅列印出內部使用的gofmt命令及其標記和引數而不真正執行它。 標記-x則既列印又執行這個命令。在go fmt命令程式內部,會在其呼叫的gofmt命令加上標記-l-w,並以指定**包中的所有go語言原始碼檔案的路徑作為引數,就像這樣:

hc@ubt:~$ go fmt -n pkgtool

gofmt -l -w golang/goc2p/src/pkgtool/envir.go golang/goc2p/src pkgtoolenvir_test.go golang/goc2p/src/pkgtool/fpath.go golang/goc2p/src/pkgtool ipath.go golang/goc2p/src/pkgtool/pnode.go golang/goc2p/src/pkgtool/util.go golang/goc2p/src/pkgtool/util_test.go

注意,作為gofmt命令引數的go語言原始碼檔案的路徑是相對的,而不是絕對的。不過這只是為了讓引數看起來更短一些而已。所以,當我們直接執行gofmt命令的時候,使用原始碼檔案的絕對路徑作為引數也是沒有問題的。實際上,任何go原始碼檔案或包含有go語言原始碼檔案的目錄的相對路徑或絕對路徑都可以作為gofmt命令的引數。當使用包含有go語言原始碼檔案的目錄的絕對路徑或相對路徑作為引數時,gofmt命令會把被直接儲存在這個目錄下的go語言原始碼檔案作為目標原始碼檔案。

go fmt命令程式內部在執行gofmt命令時加入的標記是固定的。如果我們想使用與之不同的標記集合就必須直接使用gofmt命令了。現在我們來看一下gofmt命令可接受的所有標記。如下表。

表0-13gofmt命令的標記說明

| 標記名稱 | 標記描述 |

| -l | 僅把那些不符合格式化規範的、需要被命令程式改寫的原始碼檔案的絕對路徑列印到標準輸出。而不是把改寫後的全部內容都列印到標準輸出。 |

| -w | 把改寫後的內容直接寫入到檔案中,而不是作為結果列印到標準輸出。 |

| -r | 新增形如「a[b:len(a)] -> a[b:]」的重寫規則。如果我們需要自定義某些額外的格式化規則,就需要用到它。 |

| -s | 簡化檔案中的**。 |

| -d | 只把改寫前後的內容的對比資訊作為結果列印到標準輸出。而不是把改寫後的全部內容都列印到標準輸出。命令程式將使用diff命令對內容進行比對。在windows作業系統下可能沒有diff命令,需要另行安裝。 |

| -e | 列印所有的語法錯誤到標準輸出。如果不使用此標記,則只會列印每行的第1個錯誤且只列印前10個錯誤。 |

| -comments | 是否保留原始碼檔案中的注釋。在預設情況下,此標記會被隱式的使用,並且值為true。 |

| -tabwidth | 此標記用於設定**中縮排所使用的空格數量,預設值為8。要使此標記生效,需要使用「-tabs」標記並把值設定為false。 |

| -tabs | 是否使用tab(』\t』)來代替空格表示縮排。在預設情況下,此標記會被隱式的使用,並且值為true。 |

| -cpuprofile | 是否開啟cpu使用情況記錄,並將記錄內容儲存在此標記值所指的檔案中。 |

看過上表中的資訊,我們就很容易理解go fmt命令的行為了。因為它在內部執行了gofmt命令,並加入了標記-l-w。這會使命令程式列印需要改寫的檔案的絕對路徑到標準輸出,並且直接把改寫的內容寫入到檔案中。在預設情況下,gofmt命令會把改寫後內容直接列印到標準輸出上。

實際上,命令程式會把目標原始碼檔案中的內容解析成抽象語法樹。當在解析過程中發現語法錯誤時,命令程式就會顯示錯誤提示資訊並退出。在預設情況下,目標原始碼檔案中的語法錯誤不會全部被顯示出來。我們可以加入標記-e以使命令程式列印出全部錯誤到標準輸出。

自定義改寫操作

在預設情況下,gofmt命令對go語言原始碼檔案的改寫操作包括如下幾個方面:

如果想自定義額外的改寫操作,需要使用-r標記。-r標記的值中必須包含「->」,比如a[b:len(a)] -> a[b:]。「->」的左邊應該是需要被替代的表示式的示例,而右邊則應該是用來替代「->」左邊表示式的表示式的示例。

如果我們使用標記-r,那麼命令程式是在解析原始碼檔案之前,會將此標記值中的被替換表示式和替換表示式分別解析為抽象語法樹的表示式節點。如果解析不成功,也就意味著無法進行後續的替換操作,命令程式會在列印錯誤提示資訊後退出。如果解析成功,那麼命令程式會在解析原始碼檔案成功之後進行表示式替換操作。命令程式會尋找該原始碼檔案的抽象語法樹中與被替換表示式相匹配的節點,並用替換表示式替換之。gofmt命令已支援但不限於如下自定義替換操作:

**簡化操作

當我們在執行gofmt命令時加入了標記-s,命令程式會在目標原始碼檔案中尋找可以簡化的**並簡化它。簡化操作包括:

這些操作基本上都是出於盡量使用go語言的語法糖已達到減少**量的目的。我們在編寫go語言**的時候應該直接使用這些語法糖而不應該依賴使用gofmt命令來簡化。這裡所說的go語言的語法糖,我們在第3章中已經有所介紹。

我們在本小節中詳細介紹了go fmt命令和gofmt命令。下面我們再彙總一下這兩個命令可以為我們做的事情。如下表。

表0-14go fmt命令和gofmt命令的功能

| 功能 |go fmt命令 |gofmt命令 |

| 格式化**。 | √ | √ |

| 列出不規範的原始碼檔案。 | √ | √ |

| 自動改寫原始碼檔案。 | √ | √ |

| 顯示對比資訊。 | × | √ |

| 提示全部編譯錯誤。 | × | √ |

| 清除注釋。 | × | √ |

| 自定義縮排。 | × | √ |

| 簡化**。 | × | √ |

| 自定義替換/重構輔助。 | × | √ |

| cpu使用情況記錄。 | × | √ |

最後,值得一提的是,當我們執行gofmt命令且沒有加任何引數的時候,該命令將會進入到互動模式。在這種模式下,我們可以直接在命令列介面中輸入原始碼,並以ctrl-d結束。在linux作業系統下,ctrl-d代表eof(end of file,中文譯為檔案結束符)。需要注意的是,如果在一行的中間按下ctrl-d,則表示輸出「標準輸入」的快取區,所以這時必須連續按兩次ctrl-d。另外,在windows作業系統下,ctrl-z代表eof,所以需要以ctrl-z結束。在這之後,gofmt命令會像從原始碼檔案中讀取原始碼那樣從命令列介面(也稱為標準輸入)讀取原始碼,並在格式化後將結果列印到命令列介面(也稱為標準輸出)中。示例如下:

hc@ubt:~$ gofmt -r='fmt.println(a)->fmt.printf("%s\n", a)'

ifa=="print"

warning: rewrite ignored for incomplete programs

ifa == "print"

由上述示例可知,我們可以使用gofmt命令的互動模式格式化任意的**片段。雖然會顯示一行警告資訊,但是格式化後的結果仍然會被列印出來。並且,在互動模式下,當我們輸入的**片段不符合go語言的語法規則時,命令程式也會列印出錯誤提示資訊。在其它方面,命令程式在互動模式與普通模式下的行為也是基本一致的。

Go命令教程 1 標準命令詳解

go 語言的 1.5 版本在標準命令方面有了重大變更。這倒不是說它們的用法有多大的變化,而是說它們的底層支援已經大變樣了。讓我們先來對比一下 goroot pkg tool 平台相關目錄 中的內容。以下簡稱此目錄為 go 工具目錄。插播 平台相關目錄即以 命名的目錄,用於存放因特定平台的不同而不同的...

Go標準命令

1.bug 在瀏覽器中開啟github的golang專案,可以提交bug報告。go bug 2.build 編譯專案和檔案 交叉編譯 cgo enabled 0 goos darwin goarch amd64 go build o demo.darwin.amd64 cgo enabled 0 g...

go標準命令詳解0 4 go clean

執行go clean命令會刪除掉執行其它命令時產生的一些檔案和目錄,包括 在使用go build命令時在當前 包下生成的與包名同名或者與go原始碼檔案同名的可執行檔案。在windows下,則是與包名同名或者go原始碼檔案同名且帶有 exe 字尾的檔案。在執行go test命令並加入 c標記時在當前 ...