Go:我的 CLI 工具語言
過去的一兩週裏,被公司的大佬安利了 Go,用來寫一個代碼、架構分析和自動化重構的工具。經過這麼一週對於 Go 語言的實戰,我算是有底氣來寫一篇文章來介紹(吐槽)一下 Go 語言。
優點 1:跨平臺支持(交叉編譯)
對於習慣了創造輪子的我而言,起先我覺得使用 Go,又或者是其它語言並沒有多大的區別。直到我看到了,大佬在 macOS 下構建出了 Windows、GNU/Linux 和 macOS 等系統的可執行文件的時候,我覺得 NBility現在,我已經把 Go 列爲了 我的 CLI 工具的首選語言 。
如果你和我一樣,嘗試過開發一系列的跨平臺應用,那麼就會心累於跨平臺開發。如:
- 使用 Electron 開發跨平臺應用 。除了開發機器,你還需要一個目標操作系統(如 Windows),以及對應的開發套件(Git、Node.js、Python 等)你才能完成目標操作系統上的構建。
- 使用 Java 開發 GUI 應用 。我需要在目標機器上配置 Java 環境,才能運行 jar 包。雖然大部分操作系統已經安裝有了 Java 環境,但是誰還會用它來開發 GUI 應用。
- 使用JavaScript / TypeScript 開發 CLI 工具 。嗯,我需要先安裝有一個 Node.js 或者是 Deno,才能運行起我的代碼,還有對應的 Node.js 的版本管理工具。
- 使用 Shell 來編寫 CLI 。不好意思,我還沒學會怎麼編寫 Windows 上的 BAT 工具。
- ……
當然了,有了 Docker 上面的都是問題,不過你還得先安裝一下 Docker。從這種角度上來說,它和我們使用的 Cordova、React Native、Flutter 相近,只是 Go 更高級一些。因爲前三者目前都不能在 Windows 上編譯出 iOS 應用。而對於 Go 來說,你只需要運行:
GOOS=windows GOARCH=amd64 go build fanta_cli.go
你就能得到一份在目標操作系統上的可執行文件。其中的 $GOARCH
是指目標平臺(編譯後的目標平臺)的處理器架構(386、amd64、arm), $GOOS
是指目標平臺(編譯後的目標平臺)的操作系統(darwin、freebsd、linux、windows)
根據官方的 syslist.go
顯示,它支持這麼一些操作系統和處理器架構:
const goosList = "aix android darwin dragonfly freebsd hurd illumos js linux nacl netbsd openbsd plan9 solaris windows zos " const goarchList = "386 amd64 amd64p32 arm armbe arm64 arm64be ppc64 ppc64le mips mipsle mips64 mips64le mips64p32 mips64p32le ppc riscv riscv64 s390 s390x sparc sparc64 wasm "
是的,你可以嘗試使用 Go 來玩轉 WebAssembly 了。
優點 2:部署簡單
使用 Go 語言編寫應用時,你的目標是一個可執行的二進制文件,只需要直接 blabla 就可以運行了。
而,如果你想使用一個在 GitHub 運行的軟件時,你也可以直接運行命令來獲取,就可以直接構建了,如:
go get github.com/phodal/coca
理想情況下,就可以獲得一個可執行的 coca
命令。不過,我這個項目由於使用的是相對路徑,導入有一點問題。
優點 3:原生支持併發
還沒體會到,我先去玩 WebAssembly。
缺點 1:依賴管理
Go 有依賴管理,哦,不 Go 沒有依賴管理。
go dep go vendor go modules
嗯,感覺一下,我要這麼引用自己項目中的依賴:
import ( . "github.com/phodal/coca/refactor/move_class" . "github.com/phodal/coca/refactor/rename" . "github.com/phodal/coca/refactor/unused" )
Java 有包依賴衝突,JavaScript 有依賴地獄。但是 Python 和 Go 官方一直沒能解決好依賴問題。
缺點 2:語法設計
好吧, 這個問題每個語言都有,Go 語言最麻煩的是去構建一個函數,因爲 Go 沒有構建函數。所以,你需要這麼去寫你的類:
type RemoveUnusedImportApp struct { ... } var nodes []JMoveStruct func (j *RemoveUnusedImportApp) Analysis() { { ... }
但是用起來嘛,也不方便,我還是習慣 New 一下,然後直接調用:
func NewRemoveUnusedImportApp(config string, pPath string) *RemoveUnusedImportApp { return &RemoveUnusedImportApp{} }
其它的語法還都好, 還好。
其它
好吧,我知道 Go 還有其它優點,如性能更好,但是這都是相對來說的。除非你的語言庫裏只有一種語言,這纔會成爲你所謂的優點。
沒有銀彈。