導讀
- 隨著 2022 年 3 月 15 日 go 1.18 正式釋出,新版本除了對效能的提升之外,還引入了很多新功能,其中就有 go 期盼已久的功能泛型(Generics),同時還引入的多模組工作區(Workspaces)和模糊測試(Fuzzing)。
- 關於泛型網上已經有很多介紹的教程了,這裡我介紹一個實用的功能,多模組工作區的使用方法和教程。
Go 多模組工作區能夠使開發者能夠更容易地同時處理多個模組的工作,如:
方便進行依賴的程式碼除錯(打斷點、修改程式碼)、排查依賴程式碼 bug
方便同時進行多個倉庫/模組並行開發除錯
目錄
多模組工作區
說明
- go 使用的是多模組工作區,可以讓開發者更容易同時處理多個模組的開發。在 Go 1.17 之前,只能使用
go.mod replace
指令來實現,如果你正巧是同時進行多個模組的開發,使用它可能是很痛苦的。每次當你想要提交程式碼的時候,都不得不刪除掉 go.mod 中的replace
才能使模組穩定的釋出版本。 - 在使用 go 1.18 多模組工作區功能的時候,就使用這項工作變得簡單容易處理。下面我來介紹怎麼使用這一功能。
- Go 多模組工作區文件、程式碼示例獲取地址 https://github.com/link1st/li...
使用條件
- 首先 我們需要 go 1.18 或更高版本 go 安裝
# 檢視 go 版本
> go version
go version go1.18 darwin/amd64
go work
支援命令
- 通常情況下,建議不要提交 go.work 檔案到 git 上,因為它主要用於原生程式碼開發。
- 推薦在:
$GOPATH
路徑下執行,生成 go.work 檔案 go work init
初始化工作區檔案,用於生成 go.work 工作區檔案初始化並寫入一個新的 go.work 到當前路徑下,可以指定需要新增的程式碼模組
示例:go work init ./hello
將本地倉庫 hello 新增到工作區
hello 倉庫必須是 go mod 依賴管理的倉庫(./hello/go.mod 檔案必須存在)go work use
新增新的模組到工作區命令示例:
go work use ./example
新增一個模組到工作區go work use ./example ./example1
新增多個模組到工作區go work use -r ./example
遞迴 ./example 目錄到當前工作區
刪除命令使用go work edit -dropuse=./example
功能go work edit
用於編輯 go.work 檔案可以使用
edit
命令編輯和手動編輯go.work
檔案效果是相同的
示例:go work edit -fmt go.work
重新格式化 go.work 檔案go work edit -replace=github.com/link1st/example=./example go.work
替換程式碼模組go work edit -dropreplace=github.com/link1st/example
刪除替換程式碼模組go work edit -use=./example go.work
新增新的模組到工作區go work edit -dropuse=./example go.work
從工作區中刪除模組go work sync
將工作區的構建列表同步到工作區的模組go env GOWORK
檢視環境變數,檢視當前工作區檔案路徑
可以排查工作區檔案是否設定正確,go.work 路徑找不到可以使用 GOWORK 指定
> go env GOWORK
$GOPATH/src/link1st/link1st/workspaces/go.work
go.work 檔案結構
- 檔案結構和 go.mod 檔案結構類似,支援 Go 版本號、指定工作區和需要替換的倉庫
- 檔案結構示例:
go 1.18
use (
./hello
./example
)
replace (
github.com/link1st/example => ./example1
)
use
指定使用的模組目錄
- 可以使用
go work use hello
新增模組,也可以手動修改 go.work 工作區新增新的模組 - 在工作區中新增了模組路徑,編譯的時候會自動使用 use 中的原生程式碼進行程式碼編譯,和
replaces
功能類似。
# 單模組結構
use ./hello
# 多模組結構
use (
./hello
./example
)
replaces
替換依賴倉庫地址
replaces
命令與 go.mod 指令相同,用於替換專案中依賴的倉庫地址- 需要注意的是
replaces
和use
不能同時指定相同的本地路徑
同時指定報錯資訊:
go: workspace module github.com/link1st/example is replaced at all versions in the go.work file. To fix, remove the replacement from the go.work file or specify the version at which to replace the module.
- 錯誤示例
同時在use
和replace
指定相同的本地路徑
go 1.18
use (
./hello
./example
)
replace (
github.com/link1st/example => ./example
)
go.work 檔案優先順序高於 go.mod 中定義
- 在同時使用 go.work 和 go.mod
replace
功能的的時候分別指定不同的程式碼倉庫路徑,go.work 優先順序高於 go.mod 中定義
go.mod 中定義替換為本地倉庫 example
replace (
github.com/link1st/example => ./example1
)
go.work 中定義替換為本地倉庫 example1
replace (
github.com/link1st/example => ./example1
)
- 在程式碼構建時候使用的是 go.work 指定的 example1 倉庫的程式碼,go.work 優先順序別更高
如何使用
- 在 Go 1.18
go run
和go build
都會預設使用工作區功能 GOWORK
也可以指定配置 go.work 檔案位置
export GOWORK="~/go/src/test/go.18/workspace/go.work"
如何禁用工作區
Go 全域性變數
GOWORK
設定off
則可以禁用工作區功能export GOWORK=off
開發流程演示
- 演示如何使用多模組工作區功能。在現在微服務盛行的年代,一個人會維護多個程式碼倉庫,很多的時候是多個倉庫進行同時開發
- 假設我們現在進行 hello 倉庫開發,實現的功能是,實現將輸入的字串反轉並輸出,字串反轉功能依賴於 github.com/link1st/example (下文統稱 example)公共倉庫實現
- 新建 hello 專案
mkdir hello
cd hello
# 程式碼倉庫啟動 go mod 依賴管理,生成 go.mod 檔案
go mod init github.com/link1st/link1st/workspaces/hello
# 下載依賴包
go get github.com/link1st/example
# 編寫 main 檔案
vim main.go
- main.go 程式碼
// Package main main 檔案,go 多模組工作區演示程式碼
// 實現將輸入的字串反轉輸出並輸出
package main
import (
"flag"
"fmt"
"github.com/link1st/example/stringutil"
)
var (
str = ""
)
func init() {
flag.StringVar(&str, "str", str, "輸入字元")
flag.Parse()
}
func main() {
if str == "" {
fmt.Println("示例: go run main.go -str hello")
fmt.Println("str 引數必填")
flag.Usage()
return
}
// 呼叫公共倉庫,進行字串反轉
str = stringutil.Reversal(str)
// 輸出反轉後的字串
fmt.Println(str)
return
}
- 執行程式碼
go run main.go -str "hello world"
或go run github.com/link1st/link1st/workspaces/hello -str "hello world"
可以看到輸出了 hello world 反轉以後的字串
> go run main.go -str "hello world"
dlrow olleh
- 到這裡,最初的功能已經完成,但是後續需求變動,不僅需要輸出反轉以後的字串,還需要將字串大寫
- 我們則需要去 example 倉庫中新增開發 將字串大寫的功能
# 回到工作根目錄,將 common 程式碼下載到本地進行新增新的功能
# 下載依賴的 example 包
git clone git@github.com:link1st/example.git
# 在 example 包中新增 字串大學的功能
- vim example/stringutil/to_upper.go 程式碼如下
// Package stringutil stringutil
package stringutil
import (
"unicode"
)
// ToUpper 將字串進行大寫
func ToUpper(s string) string {
r := []rune(s)
for i := range r {
r[i] = unicode.ToUpper(r[i])
}
return string(r)
}
- 由於程式碼還在本地除錯,未提交 git 倉庫中,這個時候就需要用到 Go 多模組工作區的功能了。
- 進入專案根目錄,初始化我們現在正在開發的模組
# 初始化 go.work 檔案
go work init ./hello ./example
# 檢視 go.work 檔案內容
cat go.work
- 檔案結構如下
go 1.18
use (
./example
./hello
)
- 回到 hello 專案,
vim main.go
將字串大寫的功能新增上。
func main() {
...
// 呼叫公共倉庫,進行字串反轉
str = stringutil.Reversal(str)
// 增加字元大寫的功能
str = stringutil.ToUpper(str)
// 輸出反轉後的字串
fmt.Println(str)
...
}
執行程式碼
可以看到輸出了反轉並 大寫 的字串,大寫的函式功能只在本地,未提交到 git 上,這樣我們就實現了可以同時在兩個模組上並行開發
go run main.go -str "hello world"
DLROW OLLEH
- 到這裡,演示的程式碼已經全部完成
總結
- 使用 Go 多模組工作區的功能,可以讓我們輕鬆在多個模組之間切換工作,更能適應現代微服務架構開發。