命令go env
用于打印Go語言的環(huán)境信息。其中的一些信息我們在之前已經(jīng)多次提及,但是卻沒有進(jìn)行詳細(xì)的說明。在本小節(jié),我們會(huì)對(duì)這些信息進(jìn)行深入介紹。我們先來看一看go env
命令情況下都會(huì)打印出哪些Go語言通用環(huán)境信息。
表0-25 go env
命令可打印出的Go語言通用環(huán)境信息
名稱 | 說明 |
---|---|
CGO_ENABLED | 指明cgo工具是否可用的標(biāo)識(shí)。 |
GOARCH | 程序構(gòu)建環(huán)境的目標(biāo)計(jì)算架構(gòu)。 |
GOBIN | 存放可執(zhí)行文件的目錄的絕對(duì)路徑。 |
GOCHAR | 程序構(gòu)建環(huán)境的目標(biāo)計(jì)算架構(gòu)的單字符標(biāo)識(shí)。 |
GOEXE | 可執(zhí)行文件的后綴。 |
GOHOSTARCH | 程序運(yùn)行環(huán)境的目標(biāo)計(jì)算架構(gòu)。 |
GOOS | 程序構(gòu)建環(huán)境的目標(biāo)操作系統(tǒng)。 |
GOHOSTOS | 程序運(yùn)行環(huán)境的目標(biāo)操作系統(tǒng)。 |
GOPATH | 工作區(qū)目錄的絕對(duì)路徑。 |
GORACE | 用于數(shù)據(jù)競爭檢測的相關(guān)選項(xiàng)。 |
GOROOT | Go語言的安裝目錄的絕對(duì)路徑。 |
GOTOOLDIR | Go工具目錄的絕對(duì)路徑。 |
下面我們對(duì)這些環(huán)境信息進(jìn)行逐一說明。
CGO_ENABLED
通過上一小節(jié)的介紹,相信讀者對(duì)cgo工具已經(jīng)很熟悉了。我們提到過,標(biāo)準(zhǔn)go命令可以自動(dòng)的使用cgo工具對(duì)導(dǎo)入了代碼包C的代碼包和源碼文件進(jìn)行處理。這里所說的“自動(dòng)”并不是絕對(duì)的。因?yàn)楫?dāng)環(huán)境變量CGO_ENABLED被設(shè)置為0時(shí),標(biāo)準(zhǔn)go命令就不能處理導(dǎo)入了代碼包C的代碼包和源碼文件了。請看下面的示例:
hc@ubt:~/golang/goc2p/src/basic/cgo$ export CGO_ENABLED=0
hc@ubt:~/golang/goc2p/src/basic/cgo$ go build -x
WORK=/tmp/go-build775234613
我們臨時(shí)把環(huán)境變量CGO_ENABLED的值設(shè)置為0,然后執(zhí)行go build
命令并加入了標(biāo)記-x
。標(biāo)記-x
會(huì)讓命令程序?qū)⑦\(yùn)行期間所有實(shí)際執(zhí)行的命令都打印到標(biāo)準(zhǔn)輸出。但是,在執(zhí)行命令之后沒有任何命令被打印出來。這說明對(duì)代碼包basic/cgo
的構(gòu)建操作并沒有被執(zhí)行。這是因?yàn)?,?gòu)建這個(gè)代碼包需要用到cgo工具,但cgo工具已經(jīng)被禁用了。下面,我們再來運(yùn)行調(diào)用了代碼包basic/cgo
中函數(shù)的命令源碼文件cgo_demo.go。也就是說,命令源碼文件cgo_demo.go間接的導(dǎo)入了代碼包C
。還記得嗎?這個(gè)命令源碼文件被存放在goc2p項(xiàng)目的代碼包basic/cgo
中。示例如下:
hc@ubt:~/golang/goc2p/src/basic/cgo$ export CGO_ENABLED=0
hc@ubt:~/golang/goc2p/src/basic/cgo$ go run -work cgo_demo.go
WORK=/tmp/go-build856581210
# command-line-arguments
./cgo_demo.go:4: can't find import: "basic/cgo/lib"
在上面的示例中,我們在執(zhí)行go run
命令時(shí)加入了兩個(gè)標(biāo)記——-a
和-work
。標(biāo)記-a
會(huì)使命令程序強(qiáng)行重新構(gòu)建所有的代碼包(包括涉及到的標(biāo)準(zhǔn)庫),即使它們已經(jīng)是最新的了。標(biāo)記-work
會(huì)使命令程序?qū)⑴R時(shí)工作目錄的絕對(duì)路徑打印到標(biāo)準(zhǔn)輸出。命令程序輸出的錯(cuò)誤信息顯示,命令程序沒有找到代碼包basic/cgo
。其原因是由于代碼包basic/cgo
無法被構(gòu)建。所以,命令程序在臨時(shí)工作目錄和工作區(qū)中都找不到代碼包basic/cgo對(duì)應(yīng)的歸檔文件cgo.a。如果我們使用命令ll /tmp/go-build856581210
查看臨時(shí)工作目錄,也找不到名為basic的目錄。
不過,如果我們在環(huán)境變量CGO_ENABLED的值為1的情況下生成代碼包basic/cgo
對(duì)應(yīng)的歸檔文件cgo.a,那么無論我們之后怎樣改變環(huán)境變量CGO_ENABLED的值也都可以正確的運(yùn)行命令源碼文件cgo_demo.go。即使我們在執(zhí)行go run
命令時(shí)加入標(biāo)記-a
也是如此。因?yàn)槊畛绦蛞廊豢梢栽诠ぷ鲄^(qū)中找到之前在我們執(zhí)行go install
命令時(shí)生成的歸檔文件cgo.a。示例如下:
hc@ubt:~/golang/goc2p/src/basic/cgo$ export CGO_ENABLED=1
hc@ubt:~/golang/goc2p/src/basic/cgo$ go install ../basic/cgo
hc@ubt:~/golang/goc2p/src/basic/cgo$ export CGO_ENABLED=0
hc@ubt:~/golang/goc2p/src/basic/cgo$ go run -a -work cgo_demo.go
WORK=/tmp/go-build130612063
The square root of 2.330000 is 1.526434.
ABC
CFunction1() is called.
GoFunction1() is called.
由此可知,只要我們事先成功安裝了引用了代碼包C的代碼包,即生成了對(duì)應(yīng)的代碼包歸檔文件,即使cgo工具在之后被禁用,也不會(huì)影響到其它Go語言代碼對(duì)該代碼包的使用。當(dāng)然,命令程序首先會(huì)到臨時(shí)工作目錄中尋找需要的代碼包歸檔文件。
關(guān)于cgo工具還有一點(diǎn)需要特別注意,即:當(dāng)存在交叉編譯的情況時(shí),cgo工具一定是不可用的。在標(biāo)準(zhǔn)go命令的上下文環(huán)境中,交叉編譯意味著程序構(gòu)建環(huán)境的目標(biāo)計(jì)算架構(gòu)的標(biāo)識(shí)與程序運(yùn)行環(huán)境的目標(biāo)計(jì)算架構(gòu)的標(biāo)識(shí)不同,或者程序構(gòu)建環(huán)境的目標(biāo)操作系統(tǒng)的標(biāo)識(shí)與程序運(yùn)行環(huán)境的目標(biāo)操作系統(tǒng)的標(biāo)識(shí)不同。在這里,我們可以粗略認(rèn)為交叉編譯就是在當(dāng)前的計(jì)算架構(gòu)和操作系統(tǒng)下編譯和構(gòu)建Go語言代碼并生成針對(duì)于其他計(jì)算架構(gòu)或/和操作系統(tǒng)的編譯結(jié)果文件和可執(zhí)行文件。
GOARCH
GOARCH的值的含義是程序構(gòu)建環(huán)境的目標(biāo)計(jì)算架構(gòu)的標(biāo)識(shí),也就是程序在構(gòu)建或安裝時(shí)所對(duì)應(yīng)的計(jì)算架構(gòu)的名稱。在默認(rèn)情況下,它會(huì)與程序運(yùn)行環(huán)境的目標(biāo)計(jì)算架構(gòu)一致。即它的值會(huì)與GOHOSTARCH的值是相同。但如果我們顯式的設(shè)置了環(huán)境變量GOARCH,則它的值就會(huì)是這個(gè)環(huán)境變量的值。
GOBIN
GOBIN的值為存放可執(zhí)行文件的目錄的絕對(duì)路徑。它的值來自環(huán)境變量GOBIN。在我們使用go tool install
命令安裝命令源碼文件時(shí)生成的可執(zhí)行文件會(huì)存放于這個(gè)目錄中。
GOCHAR
GOCHAR的值是程序構(gòu)建環(huán)境的目標(biāo)計(jì)算架構(gòu)的單字符標(biāo)識(shí)。它的值會(huì)根據(jù)GOARCH的值來設(shè)置。當(dāng)GOARCH的值為386時(shí),GOCHAR的值就是8。當(dāng)GOARCH的值為amd64時(shí)GOCHAR的值就是6。而GOCHAR的值5與GOARCH的值arm相對(duì)應(yīng)。
GOCHAR主要有兩個(gè)用途,列舉如下:
Go語言官方的平臺(tái)相關(guān)的工具的名稱會(huì)以它的值為前綴。的名稱會(huì)以GOCHAR的值為前綴。比如,在amd64計(jì)算架構(gòu)下,用于編譯Go語言代碼的編譯器的名稱是6g,鏈接器的名稱是6l。用于編譯C語言代碼的編譯器的名稱是6c。而用于編譯匯編語言代碼的編譯器的名稱為6a。
GOEXE
GOEXE的值會(huì)被作為可執(zhí)行文件的后綴。它的值與GOOS的值存在一定關(guān)系,即只有GOOS的值為“windows”時(shí)GOEXE的值才會(huì)是“.exe”,否則其值就為空字符串“”。這與在各個(gè)操作系統(tǒng)下的可執(zhí)行文件的默認(rèn)后綴是一致的。
GOHOSTARCH
GOHOSTARCH的值的含義是程序運(yùn)行環(huán)境的目標(biāo)計(jì)算架構(gòu)的標(biāo)識(shí),也就是程序在運(yùn)行時(shí)所在的計(jì)算機(jī)系統(tǒng)的計(jì)算架構(gòu)的名稱。在通常情況下,它的值不需要被顯式的設(shè)置。因?yàn)橛脕戆惭bGo語言的二進(jìn)制分發(fā)文件和MSI(Microsoft軟件安裝)軟件包文件都是平臺(tái)相關(guān)的。所以,對(duì)于不同計(jì)算架構(gòu)的Go語言環(huán)境來說,它都會(huì)是一個(gè)常量。
GOHOSTOS
GOHOSTOS的值的含義是程序運(yùn)行環(huán)境的目標(biāo)操作系統(tǒng)的標(biāo)識(shí),也即程序在運(yùn)行時(shí)所在的計(jì)算機(jī)系統(tǒng)的操作系統(tǒng)的名稱。與GOHOSTARCH類似,它的值在不同的操作系統(tǒng)下是固定不變的,同樣不需要顯式的設(shè)置。
GOPATH
這個(gè)環(huán)境信息我們在之前已經(jīng)提到過很多次。它的值指明了Go語言工作區(qū)目錄的絕對(duì)路徑。我們需要顯式的設(shè)置環(huán)境變量GOPATH。如果有多個(gè)工作區(qū),那么多個(gè)工作區(qū)的絕對(duì)路徑之間需要用分隔符分隔。在windows操作系統(tǒng)下,這個(gè)分隔符為“;”。在其它操作系統(tǒng)下,這個(gè)分隔符為“:”。注意,GOPATH的值不能與GOROOT的值相同。
GORACE
GORACE的值包含了用于數(shù)據(jù)競爭檢測的相關(guān)選項(xiàng)。數(shù)據(jù)競爭是在并發(fā)程序中最常見和最難調(diào)試的一類bug。數(shù)據(jù)競爭會(huì)發(fā)生在多個(gè)Goroutine爭相訪問相同的變量且至少有一個(gè)Goroutine中的程序在對(duì)這個(gè)變量進(jìn)行寫操作的情況下。
數(shù)據(jù)競爭檢測需要被顯式的開啟。還記得標(biāo)記-race
嗎?我們可以通過在執(zhí)行一些標(biāo)準(zhǔn)go命令時(shí)加入這個(gè)標(biāo)記來開啟數(shù)據(jù)競爭檢測。在這種情況下,GORACE的值就會(huì)被使用到了。支持-race
標(biāo)記的標(biāo)準(zhǔn)go命令包括:go test
命令、go run
命令、go build
命令和go install
命令。
GORACE的值形如“option1=val1 option2=val2”,即:選項(xiàng)名稱與選項(xiàng)值之間以等號(hào)“=”分隔,多個(gè)選項(xiàng)之間以空格“ ”分隔。數(shù)據(jù)競爭檢測的選項(xiàng)包括log_path、exitcode、strip_path_prefix和history_size。為了設(shè)置GORACE的值,我們需要設(shè)置環(huán)境變量GORACE?;蛘?,我們也可以在執(zhí)行g(shù)o命令時(shí)臨時(shí)設(shè)置它,像這樣:
hc@ubt:~/golang/goc2p/src/cnet/ctcp$ GORACE="log_path=/home/hc/golang/goc2p /race/report strip_path_prefix=home/hc/golang/goc2p/" go test -race
關(guān)于數(shù)據(jù)競爭檢測的更多細(xì)節(jié)我們將會(huì)在本書的第三部分予以說明。
GOROOT
GOROOT會(huì)是我們在安裝Go語言時(shí)第一個(gè)碰到Go語言環(huán)境變量。它的值指明了Go語言的安裝目錄的絕對(duì)路徑。但是,只有在非默認(rèn)情況下我們才需要顯式的設(shè)置環(huán)境變量GOROOT。這里所說的默認(rèn)情況是指:在Windows操作系統(tǒng)下我們把Go語言安裝到c:\Go目錄下,或者在其它操作系統(tǒng)下我們把Go語言安裝到/usr/local/go目錄下。另外,當(dāng)我們不是通過二進(jìn)制分發(fā)包來安裝Go語言的時(shí)候,也不需要設(shè)置環(huán)境變量GOROOT的值。比如,在Windows操作系統(tǒng)下,我們可以使用MSI軟件包文件來安裝Go語言。
GOTOOLDIR
GOTOOLDIR的值指明了Go工具目錄的絕對(duì)路徑。根據(jù)GOROOT、GOHOSTOS和GOHOSTARCH來設(shè)置。其值為$GOROOT/pkg/tool/$GOOS_$GOARCH。關(guān)于這個(gè)目錄,我們在之前也提到過多次。
除了上面介紹的這些通用的Go語言環(huán)境信息,還兩個(gè)針對(duì)于非Plan 9操作系統(tǒng)的環(huán)境信息。它們是CC和GOGCCFLAGS。環(huán)境信息CC的值是操作系統(tǒng)默認(rèn)的C語言編譯器的命令名稱。環(huán)境信息GOGCCFLAGS的值則是Go語言在使用操作系統(tǒng)的默認(rèn)C語言編譯器對(duì)C語言代碼進(jìn)行編譯時(shí)加入的參數(shù)。
如果我們要有針對(duì)性的查看上述的一個(gè)或多個(gè)環(huán)境信息,可以在go env
命令的后面加入它們的名字并執(zhí)行之。在go env
命令和環(huán)境信息名稱之間需要用空格分隔,多個(gè)環(huán)境信息名稱之間也需要用空格分隔。示例如下:
hc@ubt:~$ go env GOARCH GOCHAR
386
8
上例的go env
命令的輸出信息中,每一行對(duì)一個(gè)環(huán)境信息的值,且其順序與我們輸入的環(huán)境信息名稱的順序一致。比如,386為環(huán)境信息GOARCH,而8則是環(huán)境信息GOCHAR的值。
go env
命令能夠讓我們對(duì)當(dāng)前的Go語言環(huán)境進(jìn)行簡要的了解。通過它,我們也可以對(duì)當(dāng)前安裝的Go語言的環(huán)境設(shè)置進(jìn)行簡單的檢查。