今天在看一個程序代碼,發現里面用到了grpc,程序的目錄結構是這樣的
onlineClean | 包名main | ||
---|---|---|---|
main.go | |||
go.mod | |||
proto | |||
structs.go | 包名proto | ||
rpcClient | 包名main | ||
test.go |
其中rpcCleint/test.go里面有這樣的代碼
import (
"fmt"
pb "onlineClean/proto"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
當時我覺得有點奇怪,在rpcClient里面這樣引用onlineClean/proto,可以編譯過嗎?
於是試驗了一下,在rpcCleint下執行go build(go 版本是1.14),發現還真可以編譯成功。
當時我就在想,go build尋找import的包過程是怎么樣的呢? 它是怎么發現onlineClean/proto這個包的
很明顯,這里go build時應該是從rpcClient的上層目錄開始找onlineClean/proto的,那為啥它是從上層目錄找而不是當前目錄找呢?
上網找了一下,網上文章是這樣說的:
在我們引入第三方的時候,其會在三個地方區查找
1、GOROOT路徑
2、GOPATH路徑
3、在原目錄中的vendor目錄下進行查找
里面沒提到會從上級目錄找。
我檢查了一下GOROOT和GOPATH變量(go env GOROOT和go env GOPATH),發現都沒有包含onlineClean或者../目錄
感覺網上說的可能不太全,或者網上的資料太舊了,不適合1.14。
后來,偶然間,我發現把rpcClient復制到其它目錄(與onlineClean並列),就編譯不了。編譯提示“go: cannot find main module; see 'go help modules'”
然后我對比了在onlineClean/rpcClient和rpcClient兩個目錄執行go env的區別,發現主要是GOMOD環境變量的區別:
在onlineClean/rpcClient,會輸出set GOMOD=D:\ht\軟件部\數據質量管控平台\代碼\華為雲\go\onlineClean\go.mod
而在rpcClient則沒有輸出這個環境變量。
於是我猜測,開啟go mod時go build時會向上找go.mod,找到后使用這個go.mod進行第三方包管理,查了一下go mod的幫助文檔,證實了我這個猜測。
go helo go.mod
A module version is defined by a tree of source files, with a go.mod
file in its root. When the go command is run, it looks in the current
directory and then successive parent directories to find the go.mod
marking the root of the main (current) module.
這段話大概是說:當go命令運行,會先查找當前目錄有沒有go.mod,如果沒有會一直向上找,直到找到go.mod,並以找到go.mod的目錄做為根目錄進行第三方包引用 。