Part1

Part1

.GO 語言安裝的時候主要有三個環境變量:
GOROOT、GOPATH 和 GOBIN
通過 go env 可以查看go語言的一系列的環境變量的配置.

go env
GOROOT:代表go的安裝路徑,一般你安裝完go語言之後就有了。

GOPATH:一個目錄路徑,也可以包含多個目錄路徑,每個目錄都代表了go語言的一個“工作區”。目錄下面有三個目錄,src,bin,pkg。

src: 用來存放源代碼文件。

bin: 目錄裏面存放的都是通過 go install 命令安裝後,由 Go 命令源碼文件生成的可執行文件。
有兩種情況下,bin 目錄會變得沒有意義。
當設置了有效的 GOBIN 環境變量以後,bin 目錄就變得沒有意義。
如果 GOPATH 裏面包含多個工作區路徑的時候,必須設置 GOBIN 環境變量,否則就無法安裝 Go 程序的可執行文件。

pkg:用來存放通過 go install 命令安裝後的代碼包的歸檔文件(.a 文件)
GOBIN:存放可執行文件的文件目錄。

Go 的源碼文件分類:

(1)命令源碼文件:

    聲明自己屬於 main 代碼包、包含無參數聲明和結果聲明的 main 函數。
    命令源碼文件被安裝以後,GOPATH 如果只有一個工作區,那麼相應的
    可執行文件會被存放當前工作區的 bin 文件夾下;如果有多個工作區,
    就會安裝到 GOBIN 指向的目錄下。

(2)庫源碼文件

   庫源碼文件就是不具備命令源碼文件上述兩個特徵的源碼文件。存在於某個代碼包中的普通的源碼文件。

(3)測試源碼文件

    名稱以 _test.go 爲後綴的代碼文件,並且必須包含 Test 或者 Benchmark 名稱前綴的函數。

詳情可以參照
理解內容

  1. pkg 目錄是用來存放通過 go install 命令安裝後的代碼包的歸檔文件(.a 文件)。歸檔文件的名字就是代碼包的名字。所有歸檔文件都會被存放到該目錄下的平臺相關目錄中,即在$GOPATH/pkg/$GOOS_$GOARCH中,同樣以代碼包爲組織形式。同時這裏有兩個隱藏的環境變量,GOOSGOARCH。這兩個環境變量是不用我們設置的,系統就默認的。GOOS是 Go 所在的操作系統類型,GOARCH 是 Go 所在的計算架構。平臺相關目錄是以$GOOS_$GOARCH命名的,Mac 平臺上這個目錄名就是 darwin_amd64。
  2. 命令源碼文件並不一定必須放在 src 文件夾中的。
    這裏需要糾正一個錯誤的觀點:“所有的 Go 的代碼都要放在 GOPATH 目錄下”(這個觀點是錯誤的)
    go源碼文件
    其中go源碼文件包含以下三種:
  • 命令源碼文件:聲明自己屬於 main 代碼包、包含無參數聲明和結果聲明的 main 函數。----main包
    兩個main包的go文件可以單獨go run運行, 但是不能go build 運行,因爲go run時只運行當前文件,go build會編譯當前包內所有文件。所以 go install 也不可以。
  • 庫源碼文件:庫源碼文件就是不具備命令源碼文件上述兩個特徵的源碼文件。存在於某個代碼包中的普通的源碼文件。庫源碼文件被安裝後,相應的歸檔文件(.a 文件)會被存放到當前工作區的 pkg 的平臺相關目錄下。
  • 測試源碼文件
    名稱以 _test.go 爲後綴的代碼文件,並且必須包含 Test 或者 Benchmark 名稱前綴的函數。
func TestXXX( t *testing.T) {

}

名稱以 Test 爲名稱前綴的函數,只能接受 *testing.T 的參數,這種測試函數是功能測試函數。

func BenchmarkXXX( b *testing.B) {

}

名稱以 Benchmark 爲名稱前綴的函數,只能接受 *testing.B 的參數,這種測試函數是性能測試函數。

因此:命令源碼文件是可以單獨運行的。可以使用 go run 命令直接運行,也可以通過 go build 或 go install 命令得到相應的可執行文件。所以命令源碼文件是可以在機器的任何目錄下運行的。

包名 main 則告訴我們它是一個可獨立運行的包,它在編譯後會產生可執行文件。除了 main 包之外,其它的包最後都會生成 *.a 文件(也就是包文件)並放置在 $GOPATH/pkg/$GOOS_$GOARCH中(以 Mac 爲例就是$GOPATH/pkg/darwin_amd64)。

go run

image
中間產生兩個臨時文件。

go build

go build 用於編譯我們指定的源碼文件或代碼包以及它們的依賴包。,但是注意如果用來編譯非命令源碼文件,即庫源碼文件,go build 執行完是不會產生任何結果的。這種情況下,go build 命令只是檢查庫源碼文件的有效性,只會做檢查性的編譯,而不會輸出任何結果文件。

go build 編譯命令源碼文件,則會在該命令的執行目錄中生成一個可執行文件
go run 和go build的前幾步都一樣,只是最後go run 執行可執行文件,go build 不執行。

  • 如果構建的是庫源碼文件,那麼操作的結果文件只會存在於臨時目錄中。這里的構建的主要意義在於檢查和驗證。也就是構建了臨時目錄,然後就丟棄了。如果有問題就會報出來,如果沒問題就相當於一頓操作後什麼都沒變化,就是上面說的加和驗證。
  • 如果構建的是命令源碼文件,那麼操作的結果文件會被搬運到那個源碼文件所在的目錄中。一般構建就是用來做這個事情的。

image

go install

go install 命令是用來編譯並安裝代碼包或者源碼文件的。

安裝操作會先執行構建,然後還會進行鏈接操作,並且把結果文件搬運到指定目錄。

前面幾步依舊和 go run 、go build 完全一致,只是最後一步的差別,go install 會把命令源碼文件安裝到當前工作區的 bin 目錄(如果 GOPATH 下有多個工作區,就會放在 GOBIN 目錄下)。如果是庫源碼文件,就會被安裝到當前工作區的 pkg 的平臺相關目錄下。
例如:go install github.com/labstack/echo

  • 如果是命令源碼文件會安裝在當前工作區GOPATH的bin下echo的可執行文件。
  • 如果是庫源碼文件則安裝到當前工作區GOPATH/pkg/當前平臺/github.com/labstack/echo.a 文件。

image
go install 命令不支持針對庫源碼文件的安裝操作。

go get

go get 命令會把當前的代碼包下載到 $GOPATH 中的第一個工作區的 src 目錄中,並安裝。
如果在 go get 下載過程中加入-d 標記,那麼下載操作只會執行下載動作,而不執行安裝動作。
-u標記,加上它可以利用網絡來更新已有的代碼包及其依賴包。
image

小結

  • 命令源碼文件,通過構建或安裝都可以完成編譯,只是生成的可執行文件的目錄不同。一般就用構建了,可以帶參數指定位置。
  • 庫源碼文件,只有通過安裝才能在pkg中生成包文件。
  • 一般就是構建源碼文件。庫文件的話就是進行安裝。

問題

  1. Go 語言在多個工作區中查找依賴包的時候是以怎樣的順序進行的?
  • 如果有多個工作區,那麼是按照GOPATH裏面的先後順序查找的
  1. 如果在多個工作區中都存在導入路徑相同的代碼包會產生衝突嗎?
  • 不會衝突,像上面說的會按照順序查找執行
  1. 如果我的src下面的文件夾名字叫做hello,但package的名字叫做HelloGO
package HelloGo

import "fmt"

func PrintHello(){
    fmt.Println("Hello Go")
}

這時候如果你想調用這個包,代碼應該怎麼寫,

    import HelloGo?
    還是import hello

答案肯定是import hello的,因爲GOPATH的特性,只會按照目錄來查找包,但你調用的時候就不能用目錄名字來調用了:

package main

import "fmt"
import "hello"

func main() {
    fmt.Println("Hello, world!")
    HelloGo.PrintHello() //導入包的時候用文件夾名字,調用函數用package的名字
}

go build 命令

在運行go build命令的時候,默認不會編譯目標代碼包所依賴的那些代碼包,如果歸檔文件已經存在的話。如果被依賴的代碼包的歸檔文件不存在,或者源碼文件有了變化,那它還是會被編譯。常用參數說明:

-a : 可以強制編譯依賴的代碼包
-i : 不但要編譯依賴的代碼包,還要安裝它們的歸檔文件
-x : 查看go build命令具體執行了哪些操作
-n : 同上,只查看操作,但是不實際執行
-v : 可以看到go build命令編譯的代碼包的名稱。搭配-a參數使用時很有用

go get 命令

命令go get會自動下載代碼包,並把它們安裝到環境變量GOPATH包含的第1工作區的相應目錄中。如果存在環境變量GOBIN,那麼僅包含命令源碼文件的代碼包會被安裝到GOBIN指向的那個目錄。常用參數說明:

-u : 下載並安裝代碼包,不論是否已存在
-d : 只下載代碼包,不安裝代碼包
-fix : 在下載代碼包後先運行一個用於根據當前Go語言版本修正代碼的工具,然後再安裝代碼包
-t : 同時下載測試所需的代碼包
-insecure : 允許通過非安全的網絡協議下載和安裝代碼包。比如:HTTP。

自定義代碼包遠程導入路徑

如果你想把你編寫的(被託管在不同的代碼託管網站上的)代碼包的遠程導入路徑統一起來,或者不希望讓你的代碼包中夾雜某個代碼託管網站的域名,那麼你可以選擇自定義你的代碼包遠程導入路徑。這種自定義的實現手段叫做“導入註釋”。
比如代碼實際存儲的位置是:github.com/golang/sync/
但是安裝的時候實際使用的命令是:go get golang.org/x/sync。這裏就隱藏了github.com的域名,以及後面的部分路徑golang。

導入註釋

導入註釋必須出現在源碼文件的代碼包聲明語句的右邊,是一條單行註釋。被雙引號包裹的是一個符合導入路徑語法規則的字符串。下面是 github.com/golang/sync 下 semaphore/semaphore.go 裏的導入註釋:

package semaphore // import “golang.org/x/sync/semaphore”
這樣加入導入註釋後,就無法用github的地址來下載這個包了。但是也無法用自定義的路徑來下載這個包,應該自定義的路徑的網址還不能響應這個請求

編寫網站的處理請求

編寫一個可處理HTTP請求的程序。將對這個url響應的請求頭中加入如下的一行內容:

這行內容會被視爲HTML文檔的元數據。這個就是go get命令的文檔中要求的寫法。它的模式是這樣的: content屬性中的import-prefix的位置上填入自定義的遠程代碼包導入路徑的前綴。而vsc代表與版本控制系統有關的標識,比如git。至於repo-root,它應該是與該處理程序關聯的路徑對應的Github網站的URL,即實際網址。

這麼做的好處是,可以強化你的品牌,而不是某個代碼託管網站的。順便還可以隱藏掉用戶ID,也就是域名後的部分路徑。
最主要的是,使你的代碼包導入路徑整齊劃一,如果代碼包分散在不同的遠程路徑的話。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章