Go 學習筆記(2)—安裝目錄、工作區、源碼文件和標準命令


Go 學習筆記(2)—安裝目錄、工作區、源碼文件和標準命令

更多內容請關注WX 公眾號 【程序員的自我進化】

1. GOROOT 安裝目錄說明

GOROOT 的值是 Go 安裝目錄。安裝目錄如下所示:

<code>wohu@wohu:/usr/local/go$ ls
api bin CONTRIBUTORS favicon.ico LICENSE PATENTS README.md src VERSION
AUTHORS CONTRIBUTING.md doc lib misc pkg robots.txt test
wohu@wohu:/usr/local/go$/<code>


目錄說明

1.api 用於存放依照 Go 版本順序的 API 增量列表文件。這裡所說的 API 包含公開的變量,常量,函數等

2.bin 用於存放主要的標準命令文件,包括 go,godoc 和gofmt doc 用於存放標準庫的 HTML 格式的程序文檔。我們可以通過 godoc 命令啟動一個 Web 程序展現這些文檔

3.lib 用於存放一些特殊的庫文件

4.misc 用於存放一些輔助類的說明和工具

5.pkg 用於存放安裝 Go 標準庫的所有歸檔文件

6.src 用於存放 Go 本身,Go 標準工具以及標準庫的所有源碼文件

7.test 存放用來測試和驗證Go本身的所有相關文件


  • pkg 目錄:
<code>wohu@wohu:/usr/local/go$ ls pkg/
include linux_amd64 linux_amd64_race tool/<code>

你會發現其中有名稱為 “linux_amd64” 的文件夾,我們稱為平臺相關目錄。這類文件夾的名稱由對應的操作系統和計算架構的名稱組合而成。

通過 go install 命令,Go 程序(這裡是標準庫中的程序)會被編譯成平臺相關的歸檔文件存放到其中。另外,“pkg/tool/linux_amd64”文件夾存放了使用 Go 製作軟件時用到的很多強大的命令和工具。

<code>wohu@wohu:/usr/local/go$ ls pkg/linux_amd64
archive context.a encoding fmt.a html.a io math.a os reflect.a sort.a syscall.a unicode
bufio.a crypto encoding.a go image io.a mime os.a regexp strconv.a testing unicode.a
bytes.a crypto.a errors.a hash image.a log mime.a path regexp.a strings.a testing.a
compress database expvar.a hash.a index log.a net path.a runtime sync text
container debug flag.a html internal math net.a plugin.a runtime.a sync.a time.a
wohu@wohu:/usr/local/go$/<code>


2. GOPATH 工作區間說明

GOPATH 為自己項目的工作區間, 在學習筆記(1)中我們已經進行了設置。通過 go env 可以看到 GO 的全部環境變量。

<code>wohu@wohu:~/gocode$ go env
GOARCH="amd64"
GOBIN="/home/wohu/gocode/bin"
GOCACHE="/home/wohu/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/wohu/gocode"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build076028171=/tmp/go-build -gno-record-gcc-switches"/<code>

GOPATH 是作為編譯後二進制的存放目的地和 import 包時的搜索路徑 (其實也是你的工作目錄,可以在 src 下創建你自己的 Go 源文件, 然後開始工作),一般情況下,Go 源碼文件必須放在工作區中。

GOPATH 之下主要包含三個目錄: bin、pkg、src

<code>wohu@wohu:~/gocode$ echo $GOPATH
/home/wohu/gocode
wohu@wohu:~/gocode$ ls
bin pkg src
wohu@wohu:~/gocode$/<code>

我們需要將工作區的目錄路徑添加到環境變量 GOPATH 中。否則,即使處於同一工作區(事實上,未被加入 GOPATH 中的目錄不用管成為工作區),代碼之間也無法通過絕對代碼包路徑調用。

在實際開發環境中,工作區可以只有一個,也可以由多個,這些工作區的目錄路徑都需要添加到 GOPATH 中。與 GOROOT 一樣,我們應確保 GOPATH 一直有效。

<code>GOPATH="/home/wohu/gocode"/<code>


2.1 src 目錄

  • src 目錄:主要存放 Go 的源碼文件

用於以代碼包的形式組織並保存 Go 源碼文件,這裡的代碼包與 src 下子目錄一一對應。例如,若一個源碼文件被聲明屬於代碼包 log,那麼它就應當保存在 “src/log” 目錄中。當然,你也可以把 Go 源碼文件直接放在 src 目錄下,但這樣的 Go 源碼文件就只能被聲明屬於 main 代碼包了

除非用於臨時測試或演示,一般還是建議把 Go 源碼文件存入特定的代碼包中。


2.2 pkg 目錄

  • pkg 目錄:存放編譯好的庫文件, 主要是 *.a 文件

用於存放通過 go install 命令安裝後的代碼包的歸檔文件。前提是代碼包中必需包含 Go 庫源碼文件。歸檔文件是指那些名稱以 “.a” 結尾的文件。

該目錄與 GOROOT 目錄下的 pkg 目錄功能類似。區別在於,工作區中的 pkg 目錄專門用來存放用戶代碼的歸檔文件

編譯和安裝用戶代碼的過程一般會以代碼包為單位進行。比如 log 包被編譯安裝後,將生成一個名為 log.a 的歸檔文件,並存放在當前工作區的 pkg 目錄下的平臺相關目錄中。


2.3 bin 目錄

  • bin 目錄:主要存放可執行文件

與 pkg 目錄類似,在通過 go install 命令完成安裝後,保存由 Go 命令源碼文件生成的可執行文件。在類 Unix 操作系統下,這個可執行文件一般來說名稱與源碼文件的主文件名相同。

而在 windows 操作系統下,這個可執行文件的名稱則是源碼文件主文件名加 “.exe” 後綴。

需要把 GOPATH 中的可執行目錄 bin 也配置到環境變量中,否則自行下載的第三方 go 工具就無法使用了。

<code>GOBIN="/home/wohu/gocode/bin"/<code>

注意:GOPATH 中不要包含 Go 語言的安裝目錄,以便將 Go 語言本身的工作區同用戶工作區嚴格分開。通過 Go 工具中的代碼獲取命令 go get ,可以指定項目的代碼下載到我們在 GOPATH 中設定的第一個工作區中,並在其中完成編譯和安裝。

三個目錄下的文件如下所示:

<code>wohu@wohu:~/gocode$ ls bin/
dlv gocode godef golint go-outline gopkgs goplay gorename goreturns go-symbols guru impl
wohu@wohu:~/gocode$ ls pkg/
linux_amd64 mod
wohu@wohu:~/gocode$ ls src/
github.com golang.org hello hello.go/<code>


3. 源碼文件

Go 源碼文件有分 3 種,即命令源碼文件,庫源碼文件和測試源碼文件。


3.1 命令源碼文件

聲明為屬於 main 代碼包,並且包含無參數聲明和結果聲明的 main 函數的源碼文件。

這類源碼是程序的入口,可以獨立運行(使用 go run 命令),也可以被 go build 或 go install 命令轉換為可執行文件。

同一個代碼包中的所有源碼文件,其所屬代碼包的名稱必須一致。如果命令源碼文件和庫源碼文件處於同一代碼包中,該包就無法正確執行 go build 和 go install 命令。換句話說,這些源碼文件也就無法被編譯和安裝。因此,命令源碼文件通常會單獨放在一個代碼包中。一般情況下,一個程序模塊或軟件的啟動入口只有一個。

同一個代碼包中可以有多個命令源碼文件,可通過 go run 命令分別運行它們。但通過 go build 和 go install 命令無法編譯和安裝該代碼包。所以一般情況下,不建議把多個命令源碼文件放在同一個代碼包中。

當代碼包中有且僅有一個命令源碼文件時,在文件所在目錄中執行 go build 命令,即可在該目錄下生成一個與目錄同名的可執行文件;若使用 go install 命令,則可在當前工作區的 bin 目錄下生成相應的可執行文件。


3.2 庫源碼文件

存在於某個代碼包中的普通源碼文件。通常,庫源碼文件聲明的包名會與它實際所屬的代碼包(目錄)名一致,且庫源碼文件中不包含無參數聲明和無結果聲明的 main 函數。如在 basic/set 目錄下執行 go install 命令,成功地安裝了 basic/set 包,並生成一個名為 set.a 的歸檔文件。歸檔文件的存放目錄由以下規則產生:

  • 安裝庫源碼文件時所生成的歸檔文件會被存放到當前工作區的 pkg 目錄中。
  • 根據被編譯的目標計算機架構,歸檔文件會被放置在 pkg 目錄下的平臺相關目錄中。如上的 set.a 在 64 位 window 系統上就是 pkg/windows_amd64 目錄中。
  • 存放歸檔文件的目錄的相對路徑與被安裝的代碼包的上一級代碼包的相對路徑是一致的。

第一個相對路徑就是相對於工作區的 pkg 目錄下的平臺相關目錄而言的,而第二個相對路徑是相對於工作區的 src 目錄而言的。如果被安裝的代碼包沒有上一級代碼包(也就是說它的父目錄就是工作的 src 目錄),那麼它的歸檔文件就會被直接存放到當前工作區的 pkg 目錄的平臺相關目錄下。如 basic 包的歸檔文件 basic.a 總會被直接存放到 pkg/windows_amd64 目錄下,而 basic/set 包的歸檔文件 set.a 則會被存放到 pkg/windows_amd64/basic 目錄下。


3.3 測試源碼文件

這是一種特殊的庫文件,可以通過執行 go test 命令運行當前代碼包下的所有測試源碼文件。成為測試源碼文件的充分條件有兩個:

  • 文件名需要以 ”_test.go” 結尾
  • 文件中需要至少包含該一個名稱為 Test 開頭或 Benchmark 開頭,擁有一個類型為 *testing.T 或 testing.B 的參數的函數。類型 testing.T 或 testing.B 是兩個結構體類型。

當在某個代碼包中執行 go test 命令,該代碼包中的所有測試源碼文件就會被找到並運行。

注意:存儲 Go 代碼的文本文件需要以 UTF-8 編碼存儲。如果源碼文件中出現了非 UTF-8 編碼的字符,則在運行、編譯或安裝時,Go 會拋出 “illegal UTF-8 sequence” 的錯誤。

代碼示例 :

<code>wohu@wohu:~/GoCode/src$ tree -L  3
.
├── download
│ └── download_demo.go
├── main.go
└── upload
└── upload_demo.go/<code>

download_demo.go 代碼內容:

<code>package download

import "fmt"
// Download_imge 方法名首字母大寫,表示外部可以調用
func Download_imge() {
\tfmt.Println("This is download image demo")
}/<code>

upload_demo.go 代碼內容:

<code>package upload

import "fmt"
// Upload_imge 方法名首字母大寫,表示外部可以調用
func Upload_imge() {
\tfmt.Println("This is upload image demo")
}/<code>

main.go 代碼內容:

<code>package main

import (
\t"download"
\t"upload"
)

func main() {
\tupload.Upload_imge()
\tdownload.Download_imge()
}/<code>

分別執行 go run , go build , go install 命令, 可以看到能有正常的輸出、會生成二進制文件 main,並且在 bin 目錄下有對應的二進制文件。

<code>wohu@wohu:~/GoCode/src$ go run main.go 
This is upload image demo
This is download image demo
wohu@wohu:~/GoCode/src$ ls

download main.go upload
wohu@wohu:~/GoCode/src$ go build main.go
wohu@wohu:~/GoCode/src$ ls
download main main.go upload
wohu@wohu:~/GoCode/src$ ./main
This is upload image demo
This is download image demo
wohu@wohu:~/GoCode/src$ go install main.go
wohu@wohu:~/GoCode/src$ ls ../bin/
main
wohu@wohu:~/GoCode/src$ ls ../pkg/
wohu@wohu:~/GoCode/src$ /<code>


4. 標準命令簡述

Go 本身包含來大量用於處理 Go 程序的命令和工具。

4.1 常用命令

  • build

用於編譯指定的代碼包或 Go 語言源碼文件。命令源碼文件會被編譯成可執行文件,並存放到命令執行的目錄或指定目錄下。而庫源碼文件被編譯後,則不會在非臨時目錄中留下任何文件。

  • clean

用於清除因執行其他 go 命令而遺留下來的臨時目錄和文件。

  • doc

用於顯示打印 Go 語言代碼包以及程序實體的文檔。

  • env

用於打印 Go 語言相關的環境信息。

  • fix

用於修正指定代碼的源碼文件中包含的過時語法和代碼調用。這使得我們在升級 Go 語言版本時,可以非常方便地同步升級程序。

  • fmt

用於格式化指定代碼包中的 Go 源碼文件。實際上,它是通過執行 gofmt 命令來實現功能的。

  • generate

用於識別指定代碼中資源文件中的 “go:generate” 註釋,並執行其攜帶的任意命令。該命令獨立於 Go 語言標準的編譯和安裝體系。如果你有需要解析的 “go:generate” 註釋,就單獨運行它。這個命令非常有用,我常用它自動生成或改動 Go 源碼文件。

  • get

用於下載,編譯並安裝指定改動代碼包及其依賴包。從我們自己的代碼中轉站或第三方代碼庫上自動拉取代碼,就全靠它了。

  • install

用於編譯並安裝指定的代碼包及其依賴包。安裝命令源碼文件後,代碼包所在的工作區目錄的 bin 子目錄,或者當前環境變量 GOBIN 指向的目錄中會生成相應的可執行文件。安裝源碼文件後,會在代碼包所在的工作目錄的 pkg 子目錄中生成相應的歸檔文件。

  • list

用於顯示指定代碼包的信息,它可謂是代碼包分析的一大便利工具。利用 Go 語言標準代碼庫代碼包 “text/template” 中規定的模版語法,你可以非常靈活的控制輸出信息。

  • run

用於編譯並運行指定的代碼源碼文件。當你想不生成可執行文件而直接運行命令源碼文件時,就需要用到它。

  • test

用於測試指定的代碼包,前提是該代碼包目錄中必須存在測試源代碼文件。

  • tool

用於運行 Go 語言的特殊工具。

  • vet

如果開發人員已經寫了一些代碼,vet 命令會幫開發人員檢測代碼的常見錯誤。讓我們看看 vet 捕獲哪些類型的錯誤。

  • Printf類函數調用時,類型匹配錯誤的參數。
  • 定義常用的方法時,方法簽名的錯誤。
  • 錯誤的結構標籤。
  • 沒有指定字段名的結構字面量。

用於檢查指定代碼包中的 Go 語言代碼,並報告發現可疑代碼問題。該命令提供了除編譯之外的又一個程序檢查方法,可用於找到程序中的潛在錯誤。

<code>govetmain.go/<code>
  • version

用於顯示當前安裝的 Go 語言的版本信息以及計算環境。


4.2 附加參數

執行上述命令時,可以通過附加一些額外的標記來定製命令的執行過程。下面是一個比較通用的標記。

  • -n

使命令僅打印其執行過程中用到的所有命令,而不真正執行它們。如果只想查看或驗證命令的執行過程,而不想改變任何東西,使用它正合適。

  • -race

用於檢測並報告指定 Go 語言程序中存在的數據競爭問題。當用 Go 語言編寫併發程序時,這是很重要的檢測手段之一。

  • -v

用於打印命令執行過程中涉及的代碼包。這一定包括我們指定的目標代碼包,並且有時還會包括該代碼包直接或間接依賴的那些代碼包。這會讓你知道哪些代碼包被命令處理過了。

  • -work

用於打印命令執行時生成和使用的臨時工作目錄的名字,且命令執行完成後不刪除它。這個目錄下的文件可能會對你有用,也可以從側面瞭解命令的執行過程。如果不添加此標記,那麼臨時工作目錄會在命令執行完畢前刪除。

  • -x:

使命令打印其執行過程中用到的所有命令,同時執行它們。

我們可以把這些標記看作命令的特殊參數,他們都可以添加到命令名稱和命令的真正參數中間。用於編譯, 安裝,運行和測試 Go 語言代碼包或源碼文件的命令都支持它們。上面提到了 tool 這個子命令,它用來運行一些特殊的 Go 語言工具。直接執行 go tool 命令,可以看到這些特殊工具。它們有的是其他 Go 標準命令的底層支持,有的規則是可以獨當一面的利器。其中有兩個工具值得特別介紹一下。

  • pprof

用於以交互的方式訪問一些性能概要文件。命令將會分析給定的概要文件,並根據要求提供高可讀性的輸出信息。這個工具可以分析的概要文件包括 CPU 概要文件,內存概要文件和程序阻塞概要文件。這些包含 Go 程序運行信息的概要文件,可以通過標準庫代碼 runtime 和runtime/pprof 中的程序來生成。

  • trace

用於讀取 Go 程序蹤跡文件,並以圖形化的方式展現出來。它能夠讓我們深入瞭解 Go 程序在運行過程中的內部情況。比如,當前進程中堆的大小及使用情況。又比如,程序中的多個 goruntime 是怎樣調度的,以及它們在某個時刻被調度的原因。Go 程序蹤跡文件可以通過標準代碼包 “runtime/trace” 和 “net/http/pprof” 中的程序來生成。

上述的兩個特殊的工具對 Go 程序調優非常有用。如果想探究程序運行的過程,或者想讓程序跑的更快,更穩定,那麼這兩個工具是必知必會的。另外,這兩個工具都受到 go test 命令的直接支持。因此你可以很方便地把它們融入到程序測試當中。


分享到:


相關文章: