今天在看一個程序代碼,發現裏面用到了grpc,程序的目錄結構是這樣的golang
onlineClean | 包名main | ||
---|---|---|---|
main.go | |||
go.mod | |||
proto | |||
structs.go | 包名proto | ||
rpcClient | 包名main | ||
test.go |
其中rpcCleint/test.go裏面有這樣的代碼ui
import ( "fmt" pb "onlineClean/proto" "golang.org/x/net/context" "google.golang.org/grpc" )
當時我以爲有點奇怪,在rpcClient裏面這樣引用onlineClean/proto,能夠編譯過嗎?google
因而試驗了一下,在rpcCleint下執行go build(go 版本是1.14),發現還真能夠編譯成功。code
當時我就在想,go build尋找import的包過程是怎麼樣的呢? 它是怎麼發現onlineClean/proto這個包的文檔
很明顯,這裏go build時應該是從rpcClient的上層目錄開始找onlineClean/proto的,那爲啥它是從上層目錄找而不是當前目錄找呢?rpc
上網找了一下,網上文章是這樣說的:it
在咱們引入第三方的時候,其會在三個地方區查找
一、GOROOT路徑
二、GOPATH路徑
三、在原目錄中的vendor目錄下進行查找io
裏面沒提到會從上級目錄找。編譯
我檢查了一下GOROOT和GOPATH變量(go env GOROOT和go env GOPATH),發現都沒有包含onlineClean或者../目錄table
感受網上說的可能不太全,或者網上的資料太舊了,不適合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的目錄作爲根目錄進行第三方包引用 。