首頁 > 軟體

Go語言套件和包管理詳解

2022-09-02 18:02:27

1 包簡介

1.1 工作空間

go語言的工作空間必須由 bin、pkg、src三個目錄組成,可以在GOPATH環境變數中新增多個工作空間,但不能和GOROOT相同。通常go get使用第一個工作空間儲存下載的第三方庫

workspace
	|
	+--- bin // go install 安裝目錄。
	|	  |
	| 	  +--- learn
	|
	|
	+--- pkg // go build ⽣成靜態庫 (.a) 存放目錄。
	| 	  |
	|	  +--- darwin_amd64
	| 			|
	| 			+--- mylib.a
	| 					|
	| 					+--- mylib
	|						 |
	|						 +--- sublib.a
	|
	+--- src // 專案原始碼目錄。
		  |
		  +--- learn
		  | 	 |
		  | 	 +--- main.go
		  |
		  |
		  +--- mylib
				 |
				 +--- mylib.go
				 |
				 +--- sublib
						|
						+--- sublib.g

1.2 原始檔

  • 編碼:原始碼⽂件必須是 UTF-8 格式,否則會導致編譯器出錯。
  • 結束:語句以 “;” 結束,多數時候可以省略。
  • 註釋:⽀持 “//”、 “/**/” 兩種註釋⽅式,不能巢狀。
  • 命名:採⽤ camelCasing ⻛格,不建議使⽤下劃線。

1.3 包命名

::: tip 包命名慣例

  • 給包命名的慣例是使用包所在目錄的名字。這讓使用者在匯入包的時候,就能清晰地知道包名。
  • 儘量使用簡介明瞭的名字,但要避免衝突
  • 包名一般使用單數的形式,但是避免衝突的用的複數比如bytes,errors,strings等
  • 要避免包名有其他含義。比如 temp這種
  • 命名時考慮包名和成員如何配合,儘量減少包名和成員有重複 :::

1.4 main 包

  • 所有用 Go 語言編譯的可執行程式都必須有一個名叫 main 的包。 go語言的編譯器會將這種名字的包編譯為二進位制可執行檔案。
  • main包下肯定會有名為main()的函數,main()是程式的入口。
  • 編譯完會使用宣告 main 包的程式碼所在的目錄的目錄名作為二進位制可執行檔案的檔名

2導包

關鍵字 Import ,進行導包。未使用的匯入包,會編譯錯誤。

2.1 兩種方式

import a import b,…多次匯入,以及import(a b c) 批次匯入,如果匯入的包不使用會報錯。

import "fmt"
//或者
import(
	"fmt"
    "time"
)

2.2 包的別名

import(
	io "fmt"
)
io.Println("hello world") //別名可以直接用,在包重名時很有用

2.3 簡潔模式

import (
	. "fmt"  //但是為了別人好看,一般還是不用這種
)
func main(){
	Println("hello")
}

2.4非匯入模式(匿名匯入)

即匯入一個包並不使用它。如果不加_,就會出現編譯錯誤。 在這裡用下劃線 _ 重新命名匯入的包。只匯入,不使用。 但是這個包它進行了初始化,一般在init函數呼叫,這樣做的好處是,有些包我們不顯示使用它,但是有可能用到它,或者由使用者選擇使用哪個。比如 對特定影象驅動包的初始化,在我們格式化轉換圖片用到。還有 database/sql包,可以先都初始化,讓使用者選擇不同的資料庫驅動。

import _ "test"     //非匯入模式:僅讓該包執行初始化函數

2.5 導包的路徑

一般情況下是包的相對路徑。比如import "learn/test",標準庫中的包會在安裝 Go 的位置找到,即GOROOT。 Go 開發者建立的包會在 GOPATH 環境變數指定的目錄裡查詢。GOPATH 指定的這些目錄就是開發者的個人工作空間。

2.6 遠端匯入

目前的大勢所趨是,使用分散式版本控制系統(Distributed Version Control Systems, DVCS) 來分享程式碼,如 GitHubLaunchpad 還有 Bitbucket。 Go 語言的工具鏈本身就支援從這些網站及 類似網站獲取原始碼。 Go 工具鏈會使用匯入路徑確定需要獲取的程式碼在網路的什麼地方。

比如:import "github.com/xxxx/xxx",用匯入路徑編譯程式時, go build 命令會使用 GOPATH的設定,在磁碟上搜尋這個包。事實上, 這個匯入路徑代表一個URL,指向 GitHub上的程式碼庫。如果路徑包含 URL,可以使用 Go 工具鏈從 DVCS 獲取包,並把包的原始碼儲存在GOPATH指向的路徑裡與 URL 匹配的目錄裡。這個獲取過程 使用 go get 命令完成。

go get 將獲取任意指定的 URL 的包,或者一個已經匯入的包所依賴的其 他包。由於 go get的這種遞迴特性,這個命令會掃描某個包的原始碼樹,獲取能找到的所有依賴包。

3 初始化 init

每個包可以包含任意多個 init 函數,這些函數都會在程式執行開始的時候被呼叫。所有被編譯器發現的 init 函數都會安排在 main 函數之前執行。 init 函數用在設定包、初始化變數或者其他要在程式執行前優先完成的引導工作。舉例如下

 package postgres
 import (
	 "database/sql"
 )
 func init() { //初始化函數
     //這裡省略。。
	 sql.Register("postgres", new(PostgresDriver))
 }

3.1 init總結

  • 每個源⽂件都可以定義⼀個或多個初始化函數。
  • 編譯器不保證多個初始化函數執行次序。
  • 初始化函數在單⼀執行緒被呼叫,僅執行⼀次。
  • 初始化函數在包所有全域性變數初始化後執行。
  • 在所有初始化函數結束後才執行 main.main。
  • 無法呼叫初始化函數。

4 包管理

4.1 演變過程

  • 2013年:Gedep,社群第一個包管理工具
  • 2015年:vendor,Golang官方(golang1.5)
  • 2016、2017 年:dep、manul、Godep、Govendor、godm (Govendor勝出)
  • go module是Go1.11版本之後官方推出的版本管理工具,並且從Go1.13版本開始,go module將是Go語言預設的依賴管理工具。

4.2 Go Model優點

  • 不必須將專案目錄放在GOPATH中
  • 不使用vendor目錄,而是統一安裝到$GOPATH/pkg/mod/cache
  • build/run時,自動析出專案import的包並安裝

4.3 啟用go module

要啟用go module支援首先要設定環境變數GO111MODULE,通過它可以開啟或關閉模組支援,它有三個可選值:off、on、auto,預設值是auto。 設定GO111MODULE=on之後就可以使用go module了,以後就沒有必要在GOPATH中建立專案了,並且還能夠很好的管理專案依賴的第三方包資訊。 使用 go module 管理依賴後會在專案根目錄下生成兩個檔案go.modgo.sum

  • GO111MODULE=off禁用模組支援,編譯時會從GOPATHvendor資料夾中查詢包。
  • GO111MODULE=on啟用模組支援,編譯時會忽略GOPATHvendor資料夾,只根據 go.mod下載依賴。
  • GO111MODULE=auto,當專案在$GOPATH/src外且專案根目錄有go.mod檔案時,開啟模組支援。

4.4 GOPROXY

Go1.13之後GOPROXY預設值為proxy.golang.org,在國內是無法存取的,所以十分建議大家設定GOPROXY

5 go mod詳解

5.1 go mod命令

常用的go mod命令如下:

go mod命令描述
go mod download下載依賴的module到本地cache(預設為$GOPATH/pkg/mod目錄)
go mod edit編輯go.mod檔案
go mod graph列印模組依賴圖
go mod init初始化當前資料夾, 建立go.mod檔案
go mod tidy增加缺少的module,刪除無用的module
go mod vendor將依賴複製到vendor下
go mod verify校驗依賴
go mod why解釋為什麼需要依賴

5.2 go.mod說明

go.mod檔案記錄了專案所有的依賴資訊,其結構大致如下:

module github.com/ourlang/studygo/myblog
go 1.13
require (
	github.com/DeanThompson/ginpprof v0.0.0-20190408063150-3be636683586
	github.com/gin-gonic/gin v1.4.0
	github.com/go-sql-driver/mysql v1.4.1
	github.com/jmoiron/sqlx v1.2.0
	github.com/satori/go.uuid v1.2.0
	google.golang.org/appengine v1.6.1 // indirect
)
  • module用來定義包名
  • require用來定義依賴包及版本
  • indirect表示間接參照

5.2.1 依賴的版本

go mod支援語意化版本號,比如go get foo@v1.2.3,也可以跟git的分支或tag,比如go get foo@master,當然也可以跟git提交雜湊,比如go get foo@e3702bed2。關於依賴的版本支援以下幾種格式:

gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
gopkg.in/vmihailenco/msgpack.v2 v2.9.1
gopkg.in/yaml.v2 <=v2.2.1
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
latest

5.2.2 replace

在國記憶體取golang.org/x的各個包都需要翻牆,你可以在go.mod中使用replace替換成github上對應的庫。

replace (
	golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac
	golang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d
	golang.org/x/text v0.3.0 => github.com/golang/text v0.3.0
)

5.3 go get

::: tip 在專案中執行go get命令可以下載依賴包,並且還可以指定下載的版本。

  • 執行go get -u將會升級到最新的次要版本或者修訂版本(x.y.z, z是修訂版本號, y是次要版本號)
  • 執行go get -u=patch將會升級到最新的修訂版本
  • 執行go get package@version將會升級到指定的版本號version
  • 如果下載所有依賴可以使用go mod download命令。 :::

5.3.1 整理依賴

我們在程式碼中刪除依賴程式碼後,相關的依賴庫並不會在go.mod檔案中自動移除。這種情況下我們可以使用go mod tidy命令更新go.mod中的依賴關係

5.4 go mod edit

5.4.1 格式化

因為我們可以手動修改go.mod檔案,所以有些時候需要格式化該檔案。Go提供了一下命令:

go mod edit -fmt

5.4.2 新增依賴項

go mod edit -require=golang.org/x/text

5.4.3 移除依賴項

如果只是想修改go.mod檔案中的內容,那麼可以執行go mod edit -droprequire=package path,比如要在go.mod中移除golang.org/x/text包,可以使用如下命令

go mod edit -droprequire=golang.org/x/text

6 專案中使用go module

6.1 現有專案

如果需要對一個已經存在的專案啟用go module,可以按照以下步驟操作:

  • 在專案目錄下執行go mod init,生成一個go.mod檔案。
  • 執行go get,查詢並記錄當前專案的依賴,同時生成一個go.sum記錄每個依賴庫的版本和雜湊值

6.2 新專案

對於一個新建立的專案,我們可以在專案資料夾下按照以下步驟操作:

  • 執行go mod init 專案名命令,在當前專案資料夾下建立一個go.mod檔案。
  • 手動編輯go.mod中的require依賴項或執行go get自動發現、維護依賴。

以上就是Go語言套件和包管理詳解的詳細內容,更多關於Go語言套件及管理的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com