鍍金池/ 教程/ GO/ go run
go install
go clean
go list
go test
go doc與godoc
go build
go fix與go tool fix
go tool pprof
go run
go env
go tool cgo
標準命令詳解
go get
go vet與go tool vet

go run

在《Go并發(fā)編程實戰(zhàn)》的第二章中,我介紹了Go源碼文件的分類。Go源碼文件包括:命令源碼文件、庫源碼文件和測試源碼文件。其中,命令源碼文件總應該屬于main代碼包,且在其中有無參數(shù)聲明、無結(jié)果聲明的main函數(shù)。單個命令源碼文件可以被單獨編譯,也可以被單獨安裝(可能需要設置環(huán)境變量GOBIN)。當然,命令源碼文件也可以被單獨運行。我們想要運行命令源碼文件就需要使用命令go run。

go run命令可以編譯并運行命令源碼文件。由于它其中包含了編譯動作,因此它也可以接受所有可用于go build命令的標記。除了標記之外,go run命令只接受Go源碼文件作為參數(shù),而不接受代碼包。與go build命令和go install命令一樣,go run命令也不允許多個命令源碼文件作為參數(shù),即使它們在同一個代碼包中也是如此。而原因也是一致的,多個命令源碼文件會都有main函數(shù)聲明。

如果命令源碼文件可以接受參數(shù),那么在使用go run命令運行它的時候就可以把它的參數(shù)放在它的文件名后面,像這樣:

hc@ubt:~/golang/goc2p/src/helper/ds$ go run showds.go -p ~/golang/goc2p

在上面的示例中,我們使用go run命令運行命令源碼文件showds.go。這個命令源碼文件可以接受一個名稱為“p”的參數(shù)。我們用“-p”這種形式表示“p”是一個參數(shù)名而不是參數(shù)值。它與源碼文件名之間需要用空格隔開。參數(shù)值會放在參數(shù)名的后面,兩者成對出現(xiàn)。它們之間也要用空格隔開。如果有第二個參數(shù),那么第二個參數(shù)的參數(shù)名與第一個參數(shù)的參數(shù)值之間也要有一個空格。以此類推。

go run命令只能接受一個命令源碼文件以及若干個庫源碼文件(必須同屬于main包)作為文件參數(shù),且不能接受測試源碼文件。它在執(zhí)行時會檢查源碼文件的類型。如果參數(shù)中有多個或者沒有命令源碼文件,那么go run命令就只會打印錯誤提示信息并退出,而不會繼續(xù)執(zhí)行。

在通過參數(shù)檢查后,go run命令會將編譯參數(shù)中的命令源碼文件,并把編譯后的可執(zhí)行文件存放到臨時工作目錄中。

編譯和運行過程

為了更直觀的體現(xiàn)出go run命令中的操作步驟,我們在執(zhí)行命令時加入標記-n,用于打印相關(guān)命令而不實際執(zhí)行?,F(xiàn)在讓我們來模擬運行g(shù)oc2p項目中的代碼包helper/ds的命令源碼文件showds.go。示例如下:

hc@ubt:~/golang/goc2p/src/helper/ds$ go run -n showds.go

#
# command-line-arguments
#

mkdir -p $WORK/command-line-arguments/_obj/
mkdir -p $WORK/command-line-arguments/_obj/exe/
cd /home/hc/golang/goc2p/src/helper/ds
/usr/local/go1.5/pkg/tool/linux_amd64/compile -o $WORK/command-line-arguments.a -trimpath $WORK -p main -complete -buildid df49387da030ad0d3bebef3f046d4013f8cb08d3 -D _/home/hc/golang/goc2p/src/helper/ds -I $WORK -pack ./showds.go
cd .
/usr/local/go1.5/pkg/tool/linux_amd64/link -o $WORK/command-line-arguments/_obj/exe/showds -L $WORK -w -extld=clang -buildmode=exe -buildid=df49387da030ad0d3bebef3f046d4013f8cb08d3 $WORK/command-line-arguments.a
$WORK/command-line-arguments/_obj/exe/showds

在上面的示例中并沒有顯示針對命令源碼文件showds.go的依賴包進行編譯和運行的相關(guān)打印信息。這是因為該源碼文件的所有依賴包已經(jīng)在之前被編譯過了。

現(xiàn)在,我們來逐行解釋這些被打印出來的信息。

以前綴“#”開始的是注釋信息。我們看到信息中有三行注釋信息,并在中間行出現(xiàn)了內(nèi)容“command-line-arguments”。我們在講go build命令的時候說過,編譯命令在分析參數(shù)的時候如果發(fā)現(xiàn)第一個參數(shù)是Go源碼文件而不是代碼包時,會在內(nèi)部生成一個名為“command-line-arguments”的虛擬代碼包。所以這里的注釋信息就是要告訴我們下面的幾行信息是關(guān)于虛擬代碼包“command-line-arguments”的。

打印信息中的“$WORK”表示臨時工作目錄的絕對路徑。為了存放對虛擬代碼包“command-line-arguments”的編譯結(jié)果,命令在臨時工作目錄中創(chuàng)建了名為command-line-arguments的子目錄,并在其下又創(chuàng)建了_obj子目錄和_obj/exe子目錄。

然后,命令程序使用Go語言工具目錄compile命令對命令源碼文件showds.go進行了編譯,并把結(jié)果文件存放到了$WORK目錄下,名為command-line-arguments.a。其中,compile是Go語言自帶的編程工具。

在編譯成功之后,命令程序使用鏈接命令link生成最終的可執(zhí)行文件,并將其存于$WORK/command-line-arguments/_obj/exe/目錄中。打印信息中的最后一行表示,命令運行了生成的可執(zhí)行文件。

通過對這些打印出來的命令的解讀,我們了解了臨時工作目錄的用途以和內(nèi)容。

在上面的示例中,我們只是讓go run命令打印出運行命令源碼文件showds.go過程中需要執(zhí)行的命令,而沒有真正運行它。如果我們想真正運行命令源碼文件showds.go并且想知道臨時工作目錄的位置,就需要去掉標記-n并且加上標記-work。當然,如果依然想看到過程中執(zhí)行的命令,可以加上標記-x。如果讀者已經(jīng)看過之前我們對go build命令的介紹,就應該知道標記-x與標記-n一樣會打印出過程執(zhí)行的命令,但不同的這些命令會被真正的執(zhí)行。調(diào)整這些標記之后的命令就像這樣:

hc@ubt:~/golang/goc2p/src/helper/ds$ go run -x -work showds.go

當命令真正執(zhí)行后,臨時工作目錄中就會出現(xiàn)實實在在的內(nèi)容了,像這樣:

/tmp/go-build604555989:
  command-line-arguments/
    _obj/
      exe/
        showds
  command-line-arguments.a

由于上述命令中包含了-work標記,所以我們可以從其輸出中找到實際的工作目錄(這里是/tmp/go-build604555989)。有意思的是,我們恰恰可以通過運行命令源碼文件showds.go來查看這個臨時工作目錄的目錄樹:

hc@ubt:~/golang/goc2p/src/helper/ds$ go run showds.go -p /tmp/go-build604555989

讀者可以自己試一試。

我們在前面介紹過,命令源碼文件如果可以接受參數(shù),則可以在執(zhí)行go run命令運行這個命令源碼文件時把參數(shù)名和參數(shù)值成對的追加在后面。實際上,如果在命令后追加參數(shù),那么在最后執(zhí)行生成的可執(zhí)行文件的時候也會追加一致的參數(shù)。例如,如果這樣執(zhí)行命令:

hc@ubt:~/golang/goc2p/src/helper/ds$ go run -n showds.go -p ~/golang/goc2p

那么帶-x-n標記的命令程序打印的最后一個命令就是:

$WORK/command-line-arguments/_obj/exe/showds -p /home/hc/golang/goc2p

可見,go run命令會把追加到命令源碼文件后面的參數(shù)原封不動的傳給對應的可執(zhí)行文件。

以上簡要展示了一個命令源碼文件從編譯到運行的全過程。請記住,go run命令包含了兩個動作:編譯命令源碼文件和運行對應的可執(zhí)行文件。

上一篇:go get下一篇:go tool pprof