1.前言
網上的文章魚龍混雜,且都只是給結論,你根本不知道誰說的是對的,誰是錯的,為了得到可信的結論,于是有了這篇文章,所謂——實踐出真知。
2.實驗過程
前期準備
在GOPAHT外部建立目錄 my-app:
midir my-app
進入my-app,編寫程序, vim main.go:
package main
import "github.com/astaxie/beego"
func main() {
beego.Run()
}
1. GO111MODULE="on":
1.1 不在$GOPATH/src目錄下
- 開啟GO MOD:
go env -w GO111MODULE="on"
- 生成go.mod :
go mod init my-app
-
執行
go mod tidy
,自動下載包到$GOPATH/pkg/mod:
image.png vim $GOPATH/pkg/mod/github.com/astaxie/beego@v1.12.3/beego.go
增加一行 (58行) :
fmt.Println("mod")
當然記得要引入包:import "fmt"
-
執行
go run main.go
image.png
可以證明確實讀取了 $GOPATH/pkg/mod的beego。 生成 vendor,執行
go mod vendor
my-app下執行
vim vendor/github.com/astaxie/beego/beego.go
,
還是增加一行 (58行) :
fmt.Println("vendor")
如圖所示:
- 執行
go run main.go
image.png
可以看到此時優先讀取了 vendor里面的外部包
1.2 在$GOPATH/src目錄下
- 復制my-app的目錄到$GOPATH/src目錄下
- 執行
go run main.go
image.png
可以看到優先讀取的還是vendor - 執行
rm -rf vendor
- 再次 執行
go run main.go
image.png
依然讀的是mod的。
2. GO111MODULE="off"
先執行命令:
go env -w GO111MODULE="off"
此時我的配置如下:
2.1 GO111MODULE="off"且項目不在 $GOPATH/src下
-
還是之前在
GOPATH/src下面:
image.png 執行
vim $GOPATH/src/github.com/astaxie/beego/beego.go
還是之前的位置,改為
fmt.Println("src")
- 執行
go run main.go
image.png
直接讀取的是 $GOPATH/src下面的包。
2.2 GO111MODULE="off"且項目在 $GOPATH/src下
- 還是之前在
GOPATH/src;
- 在 $GOPATH/src/my-app 執行
go run main.go
image.png
發現竟然讀的是vendor的。 - 執行:
mv vendor vendor_bak
即去除vendor的影響,再執行go run main.go
image.png
這回讀取的就是src的了。
3. GO111MODULE="auto"
執行:
go env -w GO111MODULE="auto"
修改后環境變量如下:
3.1 沒有go.mod 且項目在$GOPATH/src下
注意:記得要在:GOPATH/pkg/mod, vendor里面的beego包加入了之前的調試語句:
fmt.Println("src")
fmt.Println("mod")
fmt.Println("vendor")
-
目錄文件如下:
image.png -
執行
go run main.go
居然報錯了:
image.png -
看看$GOPATH/src是否有包,
ls /mnt/d/GoProjects/src/github.com/astaxie/beego
:
image.png
包是有的。 -
執行一下:
go get -v github.com/astaxie/beego
image.png -
再運行:
go run main.go
,發現可以了:
image.png -
猜想走的是
$GOPATH/pkg/mod
里面的包,改了一下,vim /mnt/d/GoProjects/pkg/mod/github.com/astaxie/beego@v1.12.3/beego.go
:
image.png -
再運行:
go run main.go
,證實了:
image.png -
開啟vendor,目錄結構如下:
image.png
image.png -
運行:
go run main.go
image.png
還是走mod。
查閱資料發現,只要main.go依賴的包用了go.mod,則默認會啟用GOMODULE來下載依賴。
3.2 沒有go.mod 且項目不在$GOPATH/src下
按3.1的流程跑了一遍,測試結果同上。
-
目錄結構:
image.png - 運行:
go run main.go
image.png
走的是mod -
開啟vendor,目錄結構:
image.png - 運行:
go run main.go
image.png
還是走的是mod。
意味著,GO111MODULE="auto" 的情況下,只要依賴包包含了go.mod,那么無論有沒有vendor,無論在不在$GOPATH/src下,都會開啟mod,并走mod的外部引入包。
3.3 有go.mod 且項目不在$GOPATH/src下
-
目錄結構:
image.png -
運行:
go run main.go
image.png
即有vendor情況下走的是vendor -
我們執行以下命令
mv vendor vendor_bak
去除vendor影響,目錄結構:
image.png -
運行:
go run main.go
image.png
走的是mod。
3.4 有go.mod 且項目在$GOPATH/src下
-
目錄結構:
image.png -
運行:
go run main.go
image.png
即有vendor是直接走vendor -
我們執行以下命令
mv vendor vendor_bak
去除vendor影響,目錄結構:
image.png -
運行:
go run main.go
image.png
走的是mod。
3.結論
1.GO111MODULE="on"
1.1 GO111MODULE="on" 且項目不在 $GOPATH/src下
- 當vendor目錄存在,優先讀取vendor的外部包
- 當vendor目錄不存在,讀取$GOPATH/pkg/mod下的外部包
1.2 GO111MODULE="on" 且項目在 $GOPATH/src下
跟上面情況(GO111MODULE="on" 且項目不在 $GOPATH/src下)一致。
2. GO111MODULE="off"
2.1.GO111MODULE="off" 且項目不在 $GOPATH/src下
- 無論有沒有vendor,直接讀取$GOPATH/src里面的外部引入包,即不會讀取vendor里面的包
2.2.GO111MODULE="off" 且項目在 $GOPATH/src下
- 有vendor則讀取vendor的外部引入包
- 沒有vendor則讀取$GOPATH/src里面的外部引入包
3.GO111MODULE="auto"
3.1 沒有go.mod 且項目不在$GOPATH/src下
- 沒有vendor,且依賴的包里面有go.mod,直接走$GOPATH/pkg/mod
- 沒有vendor,且依賴的包里面都沒有go.mod,直接走$GOPATH/src (待驗證)
- 有vendor,也沒有用,只要依賴的包里面有go.mod,還是走$GOPATH/pkg/mod
- 有vendor,且依賴的包里面都沒有go.mod,走$GOPATH/src (待驗證)
3.2 沒有go.mod 且項目在$GOPATH/src下
- 沒有vendor,且依賴的包里面有go.mod,直接走$GOPATH/pkg/mod
- 沒有vendor,且依賴的包里面都沒有go.mod,直接走$GOPATH/src (待驗證)
- 有vendor,也沒有用,只要依賴的包里面有go.mod,還是走$GOPATH/pkg/mod
- 有vendor,且依賴的包里面都沒有go.mod,走vendor (待驗證)
3.3 有go.mod 且項目不在$GOPATH/src下
- 有vendor, 則讀取vendor的外部引入包
- 沒有vendor則讀取$GOPATH/pkg/mod里面的外部引入包
3.4 有go.mod 且項目在$GOPATH/src下
與上面的情況(有go.mod 且項目不在$GOPATH/src下)一致。