管理依賴
當你的程式碼使用外部包時,這些包(以模組形式分發)就成為依賴項。隨著時間的推移,你可能需要升級或替換它們。Go 提供了依賴管理工具,幫助你在引入外部依賴時確保 Go 應用程式的安全。
本主題介紹瞭如何執行管理程式碼中依賴項的任務。你可以使用 Go 工具完成大部分任務。本主題還介紹瞭如何執行其他一些你可能會覺得有用的依賴項相關任務。
另請參閱
- 如果你是模組化依賴項的新手,請參閱入門教程以獲取簡要介紹。
- 使用
go
命令管理依賴項有助於確保你的要求保持一致,並且你的 go.mod 檔案內容有效。有關命令的參考,請參閱命令 go。你還可以透過鍵入go help
command-name(例如go help mod tidy
)從命令列獲取幫助。 - 你用於更改依賴項的 Go 命令會編輯你的 go.mod 檔案。有關檔案內容的更多資訊,請參閱go.mod 檔案參考。
- 讓你的編輯器或 IDE 瞭解 Go 模組可以使管理它們的工作變得更容易。有關支援 Go 的編輯器的更多資訊,請參閱編輯器外掛和 IDE。
- 本主題不描述如何開發、釋出和版本化供他人使用的模組。有關這方面的更多資訊,請參閱開發和釋出模組。
使用和管理依賴項的工作流程
你可以使用 Go 工具獲取和使用有用的包。在 pkg.go.dev 上,你可以搜尋你可能會覺得有用的包,然後使用 go
命令將這些包匯入到你自己的程式碼中以呼叫它們的函式。
以下列出了最常見的依賴管理步驟。有關每個步驟的更多資訊,請參閱本主題中的各部分。
- 在 pkg.go.dev 上定位有用的包。
- 在你的程式碼中匯入你想要的包。
- 將你的程式碼新增到模組中以進行依賴項跟蹤(如果它尚未在模組中)。請參閱啟用依賴項跟蹤
- 新增外部包作為依賴項,以便你可以管理它們。
- 隨著時間的推移,根據需要升級或降級依賴項版本。
將依賴項作為模組管理
在 Go 中,你將匯入的包作為模組來管理依賴項。此過程由以下各項支援:
- 一個用於釋出模組和檢索其程式碼的去中心化系統。開發人員從自己的儲存庫中提供他們的模組供其他開發人員使用,併發布帶有版本號的模組。
- 一個包搜尋引擎和文件瀏覽器 (pkg.go.dev),你可以在其中找到模組。請參閱定位和匯入有用的包。
- 一個模組版本號約定,可幫助你瞭解模組的穩定性和向後相容性保證。請參閱模組版本號。
- Go 工具,讓你更容易管理依賴項,包括獲取模組源、升級等。有關更多資訊,請參閱本主題的各部分。
定位和匯入有用的包
你可以搜尋 pkg.go.dev 來查詢你可能會覺得有用的包。
當你找到一個你想在程式碼中使用的包時,找到頁面頂部的包路徑,然後點選“複製路徑”按鈕將路徑複製到剪貼簿。在你的程式碼中,將路徑貼上到 import 語句中,如以下示例所示:
import "rsc.io/quote"
你的程式碼匯入包後,啟用依賴跟蹤並獲取包的程式碼以進行編譯。有關更多資訊,請參閱在程式碼中啟用依賴跟蹤和新增依賴。
在程式碼中啟用依賴跟蹤
要跟蹤和管理你新增的依賴項,首先要將你的程式碼放入自己的模組中。這會在你的原始碼樹的根目錄下建立一個 go.mod 檔案。你新增的依賴項將在此檔案中列出。
要將你的程式碼新增到自己的模組中,請使用go mod init
命令。例如,從命令列中,切換到你的程式碼的根目錄,然後執行命令,如以下示例所示:
$ go mod init example/mymodule
go mod init
命令的引數是你的模組的模組路徑。如果可能,模組路徑應該是你原始碼的倉庫位置。
如果你一開始不知道模組最終的倉庫位置,請使用安全的替代品。這可能是你擁有的域名或你控制的其他名稱(例如你的公司名稱),以及模組名稱或源目錄之後的路徑。有關更多資訊,請參閱命名模組。
當你使用 Go 工具管理依賴項時,這些工具會更新 go.mod 檔案,使其保持當前依賴項列表。
當你新增依賴項時,Go 工具還會建立一個 go.sum 檔案,其中包含你所依賴模組的校驗和。Go 使用它來驗證下載的模組檔案的完整性,特別是對於在你的專案上工作的其他開發人員。
在你的倉庫中包含 go.mod 和 go.sum 檔案以及你的程式碼。
有關更多資訊,請參閱go.mod 參考。
命名模組
當你執行 go mod init
建立一個用於跟蹤依賴項的模組時,你需要指定一個模組路徑作為模組的名稱。模組路徑成為模組中包的匯入路徑字首。請務必指定一個不會與其他模組的模組路徑衝突的模組路徑。
至少,模組路徑只需要指示其來源的一些資訊,例如公司、作者或所有者名稱。但路徑也可以更具描述性,說明模組是什麼或做什麼。
模組路徑通常採用以下形式:
<prefix>/<descriptive-text>
-
字首通常是部分描述模組的字串,例如描述其來源的字串。這可能是
-
Go 工具可以找到模組原始碼的儲存庫位置(如果你要釋出模組,則必需)。
例如,它可能是
github.com/<project-name>/
。如果你認為你可能會發布模組供他人使用,請使用此最佳實踐。有關釋出的更多資訊,請參閱開發和釋出模組。
-
你控制的名稱。
如果你不使用倉庫名稱,請務必選擇一個你確信不會被他人使用的字首。一個不錯的選擇是你的公司名稱。避免使用
widgets
、utilities
或app
等常用術語。
-
-
對於描述性文字,一個不錯的選擇是專案名稱。請記住,包名承載了描述功能的大部分重要性。模組路徑為這些包名建立了一個名稱空間。
保留模組路徑字首
Go 保證以下字串不會用於包名中。
-
test
– 你可以使用test
作為模組路徑字首,用於其程式碼旨在本地測試另一個模組中的函式的模組。對於作為測試一部分建立的模組,請使用
test
路徑字首。例如,你的測試本身可能會執行go mod init test
,然後以某種特定方式設定該模組,以便使用 Go 原始碼分析工具進行測試。 -
example
– 在某些 Go 文件中用作模組路徑字首,例如在教程中,你只是建立一個模組來跟蹤依賴項。請注意,Go 文件也使用
example.com
來說明示例何時可能是已釋出的模組。
新增依賴項
一旦你從已釋出的模組匯入包,你就可以使用go get
命令將該模組新增為要管理的依賴項。
該命令執行以下操作:
-
如果需要,它會為命令列上命名的包構建所需的模組向你的 go.mod 檔案新增
require
指令。require
指令跟蹤你的模組所依賴的模組的最低版本。有關更多資訊,請參閱go.mod 參考。 -
如果需要,它會下載模組原始碼,以便你可以編譯依賴它們的包。它可以從諸如 proxy.golang.org 這樣的模組代理下載模組,也可以直接從版本控制倉庫下載。原始碼會本地快取。
你可以設定 Go 工具下載模組的位置。有關更多資訊,請參閱指定模組代理伺服器。
以下描述了一些示例。
-
要新增模組中包的所有依賴項,請執行如下命令(“.”指當前目錄中的包)
$ go get .
-
要新增特定的依賴項,請將其模組路徑指定為命令的引數。
$ go get example.com/theirmodule
該命令還會對下載的每個模組進行身份驗證。這確保了它與模組釋出時沒有變化。如果模組自發布以來發生了變化——例如,開發人員更改了提交內容——Go 工具將顯示安全錯誤。此身份驗證檢查可以保護你免受可能被篡改的模組的影響。
獲取特定的依賴項版本
你可以透過在 go get
命令中指定依賴模組的版本來獲取特定版本。該命令會更新你的 go.mod 檔案中的 require
指令(儘管你也可以手動更新)。
你可能想要這樣做,如果:
- 你想要獲取特定預釋出版本模組進行嘗試。
- 你發現當前要求的版本對你不起作用,因此你想要獲取一個你知道可以依賴的版本。
- 你想要升級或降級你已經需要的模組。
以下是使用go get
命令的示例
-
要獲取特定編號版本,請在模組路徑後附加一個 @ 符號,後跟你想要的版本
$ go get example.com/theirmodule@v1.3.4
-
要獲取最新版本,請在模組路徑後附加
@latest
$ go get example.com/theirmodule@latest
以下 go.mod 檔案 require
指令示例(有關更多資訊,請參閱go.mod 參考)說明了如何要求特定版本號
require example.com/theirmodule v1.3.4
發現可用更新
你可以檢查你當前模組中正在使用的依賴項是否有更新版本。使用 go list
命令顯示你的模組的依賴項列表,以及該模組可用的最新版本。一旦你發現可用的升級,你就可以用你的程式碼嘗試它們,以決定是否升級到新版本。
有關 go list
命令的更多資訊,請參閱go list -m
。
以下是幾個示例。
-
列出當前模組的所有依賴模組,以及每個模組可用的最新版本
$ go list -m -u all
-
顯示特定模組可用的最新版本
$ go list -m -u example.com/theirmodule
升級或降級依賴項
你可以透過使用 Go 工具發現可用版本,然後新增不同的版本作為依賴項來升級或降級依賴模組。
同步程式碼的依賴項
你可以確保為程式碼的所有匯入包管理依賴項,同時移除不再匯入的包的依賴項。
當你在程式碼和依賴項上進行更改時,這會很有用,可能會建立一組受管依賴項和下載模組,這些依賴項和模組不再與程式碼中匯入的包專門所需的一組匹配。
為了保持託管依賴項集的整潔,請使用 go mod tidy
命令。此命令使用程式碼中匯入的包集來編輯 go.mod 檔案,以新增必要但缺少的模組。它還會移除不提供任何相關包的未使用模組。
該命令除了一個標誌 -v(列印有關已刪除模組的資訊)之外,沒有其他引數。
$ go mod tidy
開發和測試未釋出的模組程式碼
你可以指定你的程式碼應該使用可能未釋出的依賴模組。這些模組的程式碼可能位於其各自的倉庫中,這些倉庫的一個分支中,或者在與使用它們的當前模組相同的驅動器上。
你可能希望這樣做,當:
- 你想要對外部模組的程式碼進行自己的更改,例如在分支和/或克隆它之後。例如,你可能想要準備對模組的修復,然後將其作為拉取請求傳送給模組的開發人員。
- 你正在構建一個新模組,但尚未釋出它,因此它在
go get
命令無法訪問的倉庫上不可用。
需要本地目錄中的模組程式碼
你可以指定所需模組的程式碼位於與需要它的程式碼相同的本地驅動器上。當你進行以下操作時,你可能會發現這很有用:
- 開發你自己的獨立模組並希望從當前模組進行測試。
- 修復外部模組中的問題或新增功能,並希望從當前模組進行測試。(請注意,你也可以從你自己的倉庫分支中引用外部模組。有關更多資訊,請參閱從你自己的倉庫分支引用外部模組程式碼。)
要告訴 Go 命令使用模組程式碼的本地副本,請在 go.mod 檔案中使用 replace
指令替換 require
指令中給定的模組路徑。有關指令的更多資訊,請參閱go.mod 參考。
在以下 go.mod 檔案示例中,當前模組需要外部模組 example.com/theirmodule
,使用不存在的版本號(v0.0.0-unpublished
)以確保替換正常工作。然後 replace
指令將原始模組路徑替換為 ../theirmodule
,這是一個與當前模組目錄處於同一級別的目錄。
module example.com/mymodule
go 1.23.0
require example.com/theirmodule v0.0.0-unpublished
replace example.com/theirmodule v0.0.0-unpublished => ../theirmodule
設定 require
/replace
對時,使用 go mod edit
和 go get
命令以確保檔案中描述的需求保持一致
$ go mod edit -replace=example.com/theirmodule@v0.0.0-unpublished=../theirmodule
$ go get example.com/theirmodule@v0.0.0-unpublished
注意:當你使用 replace 指令時,Go 工具不會對外部模組進行身份驗證,如新增依賴項中所述。
有關版本號的更多資訊,請參閱模組版本號。
從你自己的倉庫分支引用外部模組程式碼
當你分支了一個外部模組的倉庫(例如為了修復模組程式碼中的問題或新增功能)時,你可以讓 Go 工具使用你的分支作為模組的源。這對於從你自己的程式碼測試更改很有用。(請注意,你也可以在與引用它的模組位於同一本地驅動器上的目錄中引用模組程式碼。有關更多資訊,請參閱引用本地目錄中的模組程式碼。)
你可以透過在 go.mod 檔案中使用 replace
指令將外部模組的原始模組路徑替換為倉庫中分支的路徑來完成此操作。這指示 Go 工具在編譯時使用替換路徑(分支的位置),例如,同時允許你保持 import
語句與原始模組路徑不變。
有關 replace
指令的更多資訊,請參閱go.mod 檔案參考。
在以下 go.mod 檔案示例中,當前模組需要外部模組 example.com/theirmodule
。然後 replace
指令將原始模組路徑替換為 example.com/myfork/theirmodule
,這是該模組自身倉庫的一個分支。
module example.com/mymodule
go 1.23.0
require example.com/theirmodule v1.2.3
replace example.com/theirmodule v1.2.3 => example.com/myfork/theirmodule v1.2.3-fixed
設定 require
/replace
對時,請使用 Go 工具命令來確保檔案中描述的需求保持一致。使用 go list
命令獲取當前模組正在使用的版本。然後使用 go mod edit
命令用分支替換所需的模組。
$ go list -m example.com/theirmodule
example.com/theirmodule v1.2.3
$ go mod edit -replace=example.com/theirmodule@v1.2.3=example.com/myfork/theirmodule@v1.2.3-fixed
注意:當你使用 replace
指令時,Go 工具不會像新增依賴項中所述那樣對外部模組進行身份驗證。
有關版本號的更多資訊,請參閱模組版本號。
使用倉庫識別符號獲取特定提交
你可以使用 go get
命令從其倉庫中的特定提交新增未釋出的模組程式碼。
為此,你需要使用 go get
命令,並用 @
符號指定你想要的程式碼。當你使用 go get
時,該命令將向你的 go.mod 檔案新增一個 require
指令,該指令要求外部模組,並使用基於提交詳細資訊的偽版本號。
以下示例提供了一些說明。這些示例基於其原始碼位於 Git 倉庫中的模組。
-
要獲取特定提交的模組,請附加 @commithash 形式
$ go get example.com/theirmodule@4cf76c2
-
要獲取特定分支的模組,請附加 @branchname 形式
$ go get example.com/theirmodule@bugfixes
移除依賴項
當你的程式碼不再使用模組中的任何包時,你可以停止將該模組作為依賴項進行跟蹤。
要停止跟蹤所有未使用的模組,請執行go mod tidy
命令。此命令還可能新增構建模組中包所需的缺失依賴項。
$ go mod tidy
要刪除特定的依賴項,請使用go get
命令,指定模組的模組路徑並附加 @none
,如以下示例所示
$ go get example.com/theirmodule@none
go get
命令還會降級或移除依賴於已移除模組的其他依賴項。
工具依賴
工具依賴允許你管理用 Go 編寫並在處理你的模組時使用的開發工具。例如,你可能將 stringer
與 go generate
一起使用,或者使用特定的 linter 或格式化工具作為準備提交更改的一部分。
在 Go 1.24 及更高版本中,你可以新增工具依賴項,使用
$ go get -tool golang.org/x/tools/cmd/stringer
這將向你的 go.mod
檔案新增一個 tool
指令,並確保存在必要的 require 指令。新增此指令後,你可以透過將工具匯入路徑的最後一個非主要版本元件傳遞給 go tool
來執行該工具
$ go tool stringer
如果多個工具共享最後一個路徑片段,或者路徑片段與 Go 發行版中附帶的工具之一匹配,則你必須傳遞完整的包路徑
$ go tool golang.org/x/tools/cmd/stringer
要檢視所有當前可用工具的列表,請不帶引數執行 go tool
$ go tool
你可以手動向 go.mod
新增 tool
指令,但你必須確保存在定義該工具的模組的 require
指令。新增任何缺失的 require
指令最簡單的方法是執行
$ go mod tidy
滿足工具依賴項所需的需求與模組圖中的任何其他需求行為相同。它們參與最小版本選擇並遵守 require
、replace
和 exclude
指令。由於模組剪枝,當你依賴一個自身具有工具依賴項的模組時,僅為滿足該工具依賴項而存在的求通常不會成為你的模組的需求。
tool
元模式提供了一種同時對所有工具執行操作的方法。例如,你可以使用 go get -u tool
升級所有工具,或者使用 go install tool
將它們全部安裝到 $GOBIN。
在 Go 1.24 之前的版本中,你可以透過將一個空白匯入新增到模組中一個使用構建約束從構建中排除的 Go 檔案中來實現類似於 tool
指令的效果。如果這樣做,你就可以使用 go run
和完整的包路徑來執行該工具。
指定模組代理伺服器
當你使用 Go 工具處理模組時,工具預設從 proxy.golang.org(由 Google 運營的公共模組映象)或直接從模組的倉庫下載模組。你可以指定 Go 工具應改用另一個代理伺服器來下載和驗證模組。
如果你(或你的團隊)已經設定或選擇了要使用的不同模組代理伺服器,你可能希望這樣做。例如,有些設定模組代理伺服器是為了更好地控制依賴項的使用方式。
要為 Go 工具指定另一個模組代理伺服器,請將 GOPROXY
環境變數設定為一個或多個伺服器的 URL。Go 工具將按你指定的順序嘗試每個 URL。預設情況下,GOPROXY
首先指定一個由 Google 運營的公共模組代理,然後直接從模組的倉庫下載(如其模組路徑中指定)
GOPROXY="https://proxy.golang.org,direct"
有關 GOPROXY
環境變數的更多資訊,包括支援其他行為的值,請參閱go
命令參考。
你可以將變數設定為其他模組代理伺服器的 URL,用逗號或豎線分隔 URL。
-
當你使用逗號時,Go 工具只有在當前 URL 返回 HTTP 404 或 410 時才會嘗試列表中的下一個 URL。
GOPROXY="https://proxy.example.com,https://proxy2.example.com"
-
當你使用豎線時,Go 工具無論 HTTP 錯誤程式碼如何都會嘗試列表中的下一個 URL。
GOPROXY="https://proxy.example.com|https://proxy2.example.com"
Go 模組通常在版本控制伺服器和公共網際網路上不可用的模組代理上開發和分發。你可以設定 GOPRIVATE
環境變數來配置 go
命令,以從私有源下載和構建模組。然後 go 命令可以從私有源下載和構建模組。
GOPRIVATE
或 GONOPROXY
環境變數可以設定為與私有且不應從任何代理請求的模組字首匹配的全域性模式列表。例如
GOPRIVATE=*.corp.example.com,*.research.example.com