Go Wiki:GOPATH
GOPATH 變數
使用標準函式庫以外的相依性進行 Go 開發是 使用 Go 模組 進行的。使用 Go 模組時,GOPATH 變數(在 Unix 上預設為 $HOME/go
,在 Windows 上預設為 %USERPROFILE%\go
)用於下列目的
go install
指令將二進位檔安裝到$GOBIN
,其預設值為$GOPATH/bin
。go get
指令會將下載的模組快取至$GOMODCACHE
,其預設值為$GOPATH/pkg/mod
。go get
指令會將下載的檢查總和資料庫狀態快取至$GOPATH/pkg/sumdb
。
有關 GOPATH 變數的完整詳細資訊,請參閱 go 指令文件。本頁面其餘部分與現在已不建議使用的 GOPATH 開發模式有關。
GOPATH 開發模式
在 Go 模組之前,使用相依性的 Go 開發會使用「GOPATH 開發模式」,簡稱為「GOPATH 模式」。在 GOPATH 模式中,go
指令會將 GOPATH 變數用於下列目的
go install
指令會將二進位檔案安裝至$GOBIN
,其預設值為$GOPATH/bin
。go install
指令會將import "example.com/y/z"
的已編譯套件檔案安裝至$GOPATH/pkg/example.com/y/z.a
。go get
指令會將滿足import "example.com/y/z"
的原始程式碼下載至$GOPATH/src/example.com/y/z
。
不建議使用並移除 GOPATH 開發模式
Go 模組是 GOPATH 開發模式的替代方案,用於在整個 Go 生態系統中新增套件版本的概念。
從 GOPATH 開發模式轉換至 Go 模組的過程是漸進式的,分佈在許多 Go 版本中
-
Go 1.11(2018 年 8 月)引入了
GO111MODULE
變數,預設為auto
。使用GO111MODULE=off
時,go
指令會持續使用 GOPATH 模式。使用GO111MODULE=on
時,go
指令會持續使用模組模式。使用GO111MODULE=auto
(或不設定GO111MODULE
)時,go
指令會根據目前目錄決定模式。如果目前目錄在$GOPATH/src
之外,且在根目錄中有一個go.mod
檔案的原始碼樹中,則go
指令會使用 Go 模組模式。否則,go
指令會使用 GOPATH 模式。此規則確保在auto
模式下,所有在$GOPATH/src
中執行的指令都不會受到影響,但讓使用者可以在其他目錄中實驗模組。 -
Go 1.13(2019 年 8 月)調整
GO111MODULE=auto
模式,移除$GOPATH/src
限制:如果$GOPATH/src
內的目錄有一個go.mod
檔案,則在該目錄中或其下層執行的指令現在會使用模組模式。這讓使用者可以繼續在基於匯入的階層中組織其簽出的程式碼,但對個別簽出使用模組。 -
Go 1.16(2021 年 2 月)會將預設變更為
GO111MODULE=on
,持續使用模組模式。也就是說,GOPATH 模式預設會完全停用。需要使用 GOPATH 模式再進行一次發行的使用者可以明確設定GO111MODULE=auto
或GO111MODULE=off
。 -
Go 1.NN(???)會移除
GO111MODULE
設定和 GOPATH 模式,持續使用模組模式。
請注意,移除 GOPATH 開發模式並非表示移除 GOPATH 變數。它仍會用於本頁頂端所列的目的。
常見問題
GOPATH 變數是否會被移除?
否。GOPATH 變數(在環境中設定或透過 go env -w
設定)不會被移除。它仍會用於決定預設二進位檔安裝位置、模組快取位置和雜湊資料庫快取位置,如本頁頂端所述。
我是否仍可在 GOPATH/src/import/path 中撰寫程式碼?
可以。許多 Go 開發人員欣賞此慣例提供的結構,並將其模組儲存庫簽出至其中。所有程式碼都只需要一個 go.mod
檔案即可開始使用模組。請參閱 go mod init
。
我如何編譯 GOPATH/src 中的一個儲存庫,以針對在另一個儲存庫中所做的變更?
如果要在建置另一個模組時使用一個模組中的未發布變更,可以在另一個模組的 go.mod
中新增 replace
行。
例如,如果您已將 golang.org/x/website
和 golang.org/x/tools
簽出至 $GOPATH/src/golang.org/x/website
和 $GOPATH/src/golang.org/x/tools
,那麼要讓您本機建置的 website
自動使用 tools
中的變更,您會將這行新增至 $GOPATH/src/golang.org/x/website/go.mod
replace golang.org/x/tools => ../tools
當然,replace
指令不了解 $GOPATH
。如果您已將這兩個檔案簽出至 $HOME/mycode/website
和 $HOME/mycode/tools
,相同的行也會正常運作。
為何要移除 GOPATH 開發模式?
GOPATH 開發模式的核心本質上會自動提供所有這些類型的 replace
行,因此您為相依項建置的程式碼就是您碰巧在電腦上簽出的程式碼。這表示您的建置會受到您碰巧保留在電腦上、但您可能已忘記的舊簽出版本影響。這表示您在一部機器上取得的建置可能與另一部機器上的建置不同,即使從相同頂層儲存庫的相同版本開始。這也表示您取得的建置可能與同一個專案中另一位開發人員取得的建置不同。Go 模組可解決所有這些可重製性問題。所有這些問題的根本原因是 GOPATH 模式沒有任何套件版本的概念。
除了可重製性之外,Go 模組還提供一個明確的方法來處理代理和安全下載。當你使用 git clone
複製專案並取得其相依項時,這些相依項會使用 go.sum
檔案進行密碼檢查,以確保它們與原始開發人員使用的位元相同。唯一受信任的部分是頂層的 git clone
。這再次說明,這只可能發生在 Go 模組中,因為與 GOPATH 模式不同,Go 模組具有套件版本的概念。
對於 Go 本身的未來演進,模組清楚地標示特定檔案樹是以哪個版本的 Go 語言撰寫的。這使得我們可以在 Go 的後續版本中停用有問題的功能,例如 string(1)
,許多人認為它會產生 "1"
,但實際上會產生 "\x01"
(Ctrl-A),同時讓舊程式繼續建置 (因為它們明確標示為針對舊版本的 Go 撰寫)。
還有更多類似的範例。
在目前的情況下,這些都不可能在 GOPATH 開發模式中實現。我們無法讓生態系向前邁進,也無法開始真正依賴 Go 模組的這些重要特性,除非我們捨棄 GOPATH 模式。
(你可能也會問:為什麼不直接將這些東西新增到 GOPATH 模式中?答案是:我們已經這樣做了,而結果就是 Go 模組。)
決定捨棄 GOPATH 開發模式的時間點為何?
原先計畫在 Go 1.13 中棄用 GOPATH 模式,但我們希望花更多時間讓模組對更多 Go 使用者更強固,因此將棄用時間延後。在 問題 #41330 和 golang-tools 群組中的討論未找出任何棄用 GOPATH 的阻礙,因此目前計畫在 Go 1.16 中棄用,並在之後的版本中移除,如上方的時程表所述。
如果我對從 GOPATH 開發模式轉移到 Go 模組還有更多問題,該怎麼辦?
請參閱 golang.org/help 以取得資源清單。如果這些資源都不適合,請隨時在此 提交問題。我們希望每個人都能成功採用 Go 模組。
此內容是 Go Wiki 的一部分。