Go語(yǔ)言包和包管理詳解
1 包簡(jiǎn)介
1.1 工作空間
go語(yǔ)言的工作空間必須由 bin、pkg、src三個(gè)目錄組成,可以在GOPATH
環(huán)境變量中添加多個(gè)工作空間,但不能和GOROOT
相同。通常go get
使用第一個(gè)工作空間保存下載的第三方庫(kù)
workspace | +--- bin // go install 安裝目錄。 | | | +--- learn | | +--- pkg // go build ?成靜態(tài)庫(kù) (.a) 存放目錄。 | | | +--- darwin_amd64 | | | +--- mylib.a | | | +--- mylib | | | +--- sublib.a | +--- src // 項(xiàng)目源碼目錄。 | +--- learn | | | +--- main.go | | +--- mylib | +--- mylib.go | +--- sublib | +--- sublib.g
1.2 源文件
- 編碼:源碼?件必須是 UTF-8 格式,否則會(huì)導(dǎo)致編譯器出錯(cuò)。
- 結(jié)束:語(yǔ)句以 “;” 結(jié)束,多數(shù)時(shí)候可以省略。
- 注釋:?持 “//”、 “/**/” 兩種注釋?式,不能嵌套。
- 命名:采? camelCasing ?格,不建議使?下劃線。
1.3 包命名
::: tip 包命名慣例
- 給包命名的慣例是使用包所在目錄的名字。這讓用戶在導(dǎo)入包的時(shí)候,就能清晰地知道包名。
- 盡量使用簡(jiǎn)介明了的名字,但要避免沖突
- 包名一般使用單數(shù)的形式,但是避免沖突的用的復(fù)數(shù)比如bytes,errors,strings等
- 要避免包名有其他含義。比如 temp這種
- 命名時(shí)考慮包名和成員如何配合,盡量減少包名和成員有重復(fù) :::
1.4 main 包
- 所有用 Go 語(yǔ)言編譯的可執(zhí)行程序都必須有一個(gè)名叫 main 的包。 go語(yǔ)言的編譯器會(huì)將這種名字的包編譯為二進(jìn)制可執(zhí)行文件。
- main包下肯定會(huì)有名為main()的函數(shù),main()是程序的入口。
- 編譯完會(huì)使用聲明 main 包的代碼所在的目錄的目錄名作為二進(jìn)制可執(zhí)行文件的文件名
2導(dǎo)包
關(guān)鍵字 Import ,進(jìn)行導(dǎo)包。未使用的導(dǎo)入包,會(huì)編譯錯(cuò)誤。
2.1 兩種方式
import a import b,…多次導(dǎo)入,以及import(a b c) 批量導(dǎo)入,如果導(dǎo)入的包不使用會(huì)報(bào)錯(cuò)。
import "fmt" //或者 import( "fmt" "time" )
2.2 包的別名
import( io "fmt" ) io.Println("hello world") //別名可以直接用,在包重名時(shí)很有用
2.3 簡(jiǎn)潔模式
import ( . "fmt" //但是為了別人好看,一般還是不用這種 ) func main(){ Println("hello") }
2.4非導(dǎo)入模式(匿名導(dǎo)入)
即導(dǎo)入一個(gè)包并不使用它。如果不加_,就會(huì)出現(xiàn)編譯錯(cuò)誤。 在這里用下劃線 _ 重命名導(dǎo)入的包。只導(dǎo)入,不使用。 但是這個(gè)包它進(jìn)行了初始化,一般在init
函數(shù)調(diào)用,這樣做的好處是,有些包我們不顯示使用它,但是有可能用到它,或者由用戶選擇使用哪個(gè)。比如 對(duì)特定圖像驅(qū)動(dòng)包的初始化,在我們格式化轉(zhuǎn)換圖片用到。還有 database/sql
包,可以先都初始化,讓用戶選擇不同的數(shù)據(jù)庫(kù)驅(qū)動(dòng)。
import _ "test" //非導(dǎo)入模式:僅讓該包執(zhí)行初始化函數(shù)
2.5 導(dǎo)包的路徑
一般情況下是包的相對(duì)路徑。比如import "learn/test"
,標(biāo)準(zhǔn)庫(kù)中的包會(huì)在安裝 Go 的位置找到,即GOROOT
。 Go 開(kāi)發(fā)者創(chuàng)建的包會(huì)在 GOPATH
環(huán)境變量指定的目錄里查找。GOPATH
指定的這些目錄就是開(kāi)發(fā)者的個(gè)人工作空間。
2.6 遠(yuǎn)程導(dǎo)入
目前的大勢(shì)所趨是,使用分布式版本控制系統(tǒng)(Distributed Version Control Systems, DVCS)
來(lái)分享代碼,如 GitHub
、 Launchpad
還有 Bitbucket
。 Go 語(yǔ)言的工具鏈本身就支持從這些網(wǎng)站及 類似網(wǎng)站獲取源代碼。 Go 工具鏈會(huì)使用導(dǎo)入路徑確定需要獲取的代碼在網(wǎng)絡(luò)的什么地方。
比如:import "github.com/xxxx/xxx"
,用導(dǎo)入路徑編譯程序時(shí), go build 命令會(huì)使用 GOPATH
的設(shè)置,在磁盤上搜索這個(gè)包。事實(shí)上, 這個(gè)導(dǎo)入路徑代表一個(gè)URL,指向 GitHub
上的代碼庫(kù)。如果路徑包含 URL,可以使用 Go 工具鏈從 DVCS
獲取包,并把包的源代碼保存在GOPATH
指向的路徑里與 URL 匹配的目錄里。這個(gè)獲取過(guò)程 使用 go get 命令完成。
go get 將獲取任意指定的 URL 的包,或者一個(gè)已經(jīng)導(dǎo)入的包所依賴的其 他包。由于 go get的這種遞歸特性,這個(gè)命令會(huì)掃描某個(gè)包的源碼樹(shù),獲取能找到的所有依賴包。
3 初始化 init
每個(gè)包可以包含任意多個(gè) init 函數(shù),這些函數(shù)都會(huì)在程序執(zhí)行開(kāi)始的時(shí)候被調(diào)用。所有被編譯器發(fā)現(xiàn)的 init 函數(shù)都會(huì)安排在 main 函數(shù)之前執(zhí)行。 init 函數(shù)用在設(shè)置包、初始化變量或者其他要在程序運(yùn)行前優(yōu)先完成的引導(dǎo)工作。舉例如下
package postgres import ( "database/sql" ) func init() { //初始化函數(shù) //這里省略。。 sql.Register("postgres", new(PostgresDriver)) }
3.1 init總結(jié)
- 每個(gè)源?件都可以定義?個(gè)或多個(gè)初始化函數(shù)。
- 編譯器不保證多個(gè)初始化函數(shù)執(zhí)行次序。
- 初始化函數(shù)在單?線程被調(diào)用,僅執(zhí)行?次。
- 初始化函數(shù)在包所有全局變量初始化后執(zhí)行。
- 在所有初始化函數(shù)結(jié)束后才執(zhí)行 main.main。
- 無(wú)法調(diào)用初始化函數(shù)。
4 包管理
4.1 演變過(guò)程
- 2013年:Gedep,社區(qū)第一個(gè)包管理工具
- 2015年:vendor,Golang官方(golang1.5)
- 2016、2017 年:dep、manul、Godep、Govendor、godm (Govendor勝出)
- go module是Go1.11版本之后官方推出的版本管理工具,并且從Go1.13版本開(kāi)始,go module將是Go語(yǔ)言默認(rèn)的依賴管理工具。
4.2 Go Model優(yōu)點(diǎn)
- 不必須將項(xiàng)目目錄放在GOPATH中
- 不使用vendor目錄,而是統(tǒng)一安裝到$GOPATH/pkg/mod/cache
- build/run時(shí),自動(dòng)析出項(xiàng)目import的包并安裝
4.3 啟用go module
要啟用go module
支持首先要設(shè)置環(huán)境變量GO111MODULE
,通過(guò)它可以開(kāi)啟或關(guān)閉模塊支持,它有三個(gè)可選值:off、on、auto,默認(rèn)值是auto。 設(shè)置GO111MODULE=on
之后就可以使用go module
了,以后就沒(méi)有必要在GOPATH
中創(chuàng)建項(xiàng)目了,并且還能夠很好的管理項(xiàng)目依賴的第三方包信息。 使用 go module
管理依賴后會(huì)在項(xiàng)目根目錄下生成兩個(gè)文件go.mod
和go.sum
。
GO111MODULE=off
禁用模塊支持,編譯時(shí)會(huì)從GOPATH
和vendor
文件夾中查找包。GO111MODULE=on
啟用模塊支持,編譯時(shí)會(huì)忽略GOPATH
和vendor
文件夾,只根據(jù)go.mod
下載依賴。GO111MODULE=auto
,當(dāng)項(xiàng)目在$GOPATH/src
外且項(xiàng)目根目錄有go.mod
文件時(shí),開(kāi)啟模塊支持。
4.4 GOPROXY
Go1.13之后GOPROXY
默認(rèn)值為proxy.golang.org,在國(guó)內(nèi)是無(wú)法訪問(wèn)的,所以十分建議大家設(shè)置GOPROXY
5 go mod詳解
5.1 go mod命令
常用的go mod命令如下:
go mod命令 | 描述 |
---|---|
go mod download | 下載依賴的module到本地cache(默認(rèn)為$GOPATH/pkg/mod目錄) |
go mod edit | 編輯go.mod文件 |
go mod graph | 打印模塊依賴圖 |
go mod init | 初始化當(dāng)前文件夾, 創(chuàng)建go.mod文件 |
go mod tidy | 增加缺少的module,刪除無(wú)用的module |
go mod vendor | 將依賴復(fù)制到vendor下 |
go mod verify | 校驗(yàn)依賴 |
go mod why | 解釋為什么需要依賴 |
5.2 go.mod說(shuō)明
go.mod
文件記錄了項(xiàng)目所有的依賴信息,其結(jié)構(gòu)大致如下:
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用來(lái)定義包名
- require用來(lái)定義依賴包及版本
- indirect表示間接引用
5.2.1 依賴的版本
go mod
支持語(yǔ)義化版本號(hào),比如go get foo@v1.2.3
,也可以跟git的分支或tag,比如go get foo@master
,當(dāng)然也可以跟git提交哈希,比如go get foo@e3702bed2
。關(guān)于依賴的版本支持以下幾種格式:
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
在國(guó)內(nèi)訪問(wèn)golang.org/x
的各個(gè)包都需要翻墻,你可以在go.mod
中使用replace
替換成github
上對(duì)應(yīng)的庫(kù)。
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 在項(xiàng)目中執(zhí)行g(shù)o get命令可以下載依賴包,并且還可以指定下載的版本。
- 運(yùn)行
go get -u
將會(huì)升級(jí)到最新的次要版本或者修訂版本(x.y.z, z是修訂版本號(hào), y是次要版本號(hào)) - 運(yùn)行
go get -u=patch
將會(huì)升級(jí)到最新的修訂版本 - 運(yùn)行
go get package@version
將會(huì)升級(jí)到指定的版本號(hào)version
- 如果下載所有依賴可以使用
go mod download
命令。 :::
5.3.1 整理依賴
我們?cè)诖a中刪除依賴代碼后,相關(guān)的依賴庫(kù)并不會(huì)在go.mod
文件中自動(dòng)移除。這種情況下我們可以使用go mod tidy
命令更新go.mod
中的依賴關(guān)系
5.4 go mod edit
5.4.1 格式化
因?yàn)槲覀兛梢允謩?dòng)修改go.mod文件,所以有些時(shí)候需要格式化該文件。Go提供了一下命令:
go mod edit -fmt
5.4.2 添加依賴項(xiàng)
go mod edit -require=golang.org/x/text
5.4.3 移除依賴項(xiàng)
如果只是想修改go.mod
文件中的內(nèi)容,那么可以運(yùn)行go mod edit -droprequire=package path
,比如要在go.mod
中移除golang.org/x/text
包,可以使用如下命令
go mod edit -droprequire=golang.org/x/text
6 項(xiàng)目中使用go module
6.1 現(xiàn)有項(xiàng)目
如果需要對(duì)一個(gè)已經(jīng)存在的項(xiàng)目啟用go module
,可以按照以下步驟操作:
- 在項(xiàng)目目錄下執(zhí)行
go mod init
,生成一個(gè)go.mod
文件。 - 執(zhí)行
go get
,查找并記錄當(dāng)前項(xiàng)目的依賴,同時(shí)生成一個(gè)go.sum
記錄每個(gè)依賴庫(kù)的版本和哈希值
6.2 新項(xiàng)目
對(duì)于一個(gè)新創(chuàng)建的項(xiàng)目,我們可以在項(xiàng)目文件夾下按照以下步驟操作:
- 執(zhí)行
go mod init 項(xiàng)目名
命令,在當(dāng)前項(xiàng)目文件夾下創(chuàng)建一個(gè)go.mod
文件。 - 手動(dòng)編輯
go.mod
中的require
依賴項(xiàng)或執(zhí)行go get
自動(dòng)發(fā)現(xiàn)、維護(hù)依賴。
以上就是Go語(yǔ)言包和包管理詳解的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言包及管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go語(yǔ)言單元測(cè)試的實(shí)現(xiàn)及用例
在日常開(kāi)發(fā)中,我們通常需要針對(duì)現(xiàn)有的功能進(jìn)行單元測(cè)試,以驗(yàn)證開(kāi)發(fā)的正確性,本文主要介紹了Go語(yǔ)言單元測(cè)試的實(shí)現(xiàn)及用例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01關(guān)于升級(jí)go1.18的goland問(wèn)題詳解
作為一個(gè)go語(yǔ)言程序員,覺(jué)得自己有義務(wù)為go新手開(kāi)一條更簡(jiǎn)單便捷的上手之路,下面這篇文章主要給大家介紹了關(guān)于升級(jí)go1.18的goland問(wèn)題的相關(guān)資料,需要的朋友可以參考下2022-11-11Go計(jì)算某段代碼運(yùn)行所耗時(shí)間簡(jiǎn)單實(shí)例
這篇文章主要給大家介紹了關(guān)于Go計(jì)算某段代碼運(yùn)行所耗時(shí)間的相關(guān)資料,主要介紹了Golang記錄計(jì)算函數(shù)執(zhí)行耗時(shí)、運(yùn)行時(shí)間的一個(gè)簡(jiǎn)單方法,文中給出了詳細(xì)的代碼示例,需要的朋友可以參考下2023-11-11golang time包下定時(shí)器的實(shí)現(xiàn)方法
定時(shí)器的實(shí)現(xiàn)大家應(yīng)該都遇到過(guò),最近在學(xué)習(xí)golang,所以下面這篇文章主要給大家介紹了關(guān)于golang time包下定時(shí)器的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-12-12使用Go語(yǔ)言實(shí)現(xiàn)在項(xiàng)目中隱藏敏感信息
在開(kāi)發(fā)項(xiàng)目是,用戶信息管理是一個(gè)非常常見(jiàn)的場(chǎng)景,特別是當(dāng)我們需要存儲(chǔ)和處理敏感信息時(shí),本文主要介紹了如何使用Go語(yǔ)言實(shí)現(xiàn)隱藏敏感信息,需要的可以參考下2024-11-11golang復(fù)制文件夾移動(dòng)到另一個(gè)文件夾實(shí)現(xiàn)方法詳解
這篇文章主要為大家介紹了golang復(fù)制文件夾并移動(dòng)到另一個(gè)文件夾實(shí)現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07golang的匿名函數(shù)和普通函數(shù)的區(qū)別解析
匿名函數(shù)是不具名的函數(shù),可以在不定義函數(shù)名的情況下直接使用,通常用于函數(shù)內(nèi)部的局部作用域中,這篇文章主要介紹了golang的匿名函數(shù)和普通函數(shù)的區(qū)別,需要的朋友可以參考下2023-03-03