包是go最小的分發(fā)單位。
包是函數(shù)和數(shù)據(jù)的集合缤骨,將有相關(guān)特性的函數(shù)和數(shù)據(jù)放在統(tǒng)一的文件/目錄進(jìn)行管理爱咬,每個(gè)包都可以作為獨(dú)立的單元維護(hù)并提供給其他項(xiàng)目進(jìn)行使用。
包聲明
Go 源文件都需要在開頭使用 package
聲明所在包绊起,包名告知編譯器哪些是包的源代碼用于編譯庫文件精拟,其次包名用于限制包內(nèi)成員對(duì)外的可見性,最后包名用于在包外對(duì)公開成員的訪問。
包名使用簡短的小寫字母蜂绎,常與所在目錄名保持一致栅表,一個(gè)包中可以由多個(gè) Go 源文件,但必須使用相同包名师枣。
導(dǎo)入
在使用包時(shí)需要使用 import 將包按路徑名導(dǎo)入怪瓶,再通過包名調(diào)用成員。
可通過 import 每行導(dǎo)入一個(gè)包践美,也可使用括號(hào)包含所有包并使用一個(gè) import 導(dǎo)入洗贰。
工作目錄結(jié)構(gòu):
-
bin
: 用于放置發(fā)布的二進(jìn)制程序 -
pkg
: 用于放置發(fā)布的庫文件 -
src
: 用于放置源代碼
運(yùn)行:
- 將 源碼 目錄添加到 GOPATH 環(huán)境變量中
- 編譯&運(yùn)行
使用 go build 編譯二進(jìn)制文件
命令:go build gpkgmain
說明:編譯路徑 gpkgmain 下的包,main 包拨脉,則在當(dāng)前目錄產(chǎn)生以 pkgmain 命名的二進(jìn)制程序
使用 go run 運(yùn)行二進(jìn)制文件
命令:go run gpkgmain
使用 go install 編譯并發(fā)布二進(jìn)制文件
命令:go install gpkgmain
說明:編譯并發(fā)布路徑 gpkgmain 下的包哆姻,main 包,則在將編譯后的以 pkgmain 命名的二進(jìn)制程序拷貝到 bin 目錄
使用 go install 編譯發(fā)布庫文件
命令:go install gpkgname/pkg01
說明:編譯并發(fā)布路徑 gpkgname/pkg01 下的包玫膀,非 main 包矛缨,則在將編譯的以包名命名的庫文件拷貝到 pkg/GOOS_GOARCH 目錄下
使用 go install 編譯發(fā)布所有二進(jìn)制和庫文件
命令:go install ./…
說明:編譯并發(fā)布當(dāng)前路徑下的所有二進(jìn)制程序和庫文件
注意:Go 語言不允許交叉導(dǎo)入包
1. go get
go get 下載目錄到gopath的第一個(gè)路徑中
go env
echo $GOPATH
go get github.com/WPFS/gopkg
*/
2. 包的導(dǎo)入方式
/*
(1) 絕對(duì)導(dǎo)入
import (
"fmt"
"github.com/WPFS/gopkg"
)
(2) 相對(duì)導(dǎo)入,不建議使用
import (
"fmt"
"./github.com/WPFS/gopkg"
)
(3) 別名導(dǎo)入解決多個(gè)包或者包內(nèi)函數(shù)名沖突
import (
lgopkg "gopkg"
"github.com/WPFS/gopkg"
)
(4) 點(diǎn)導(dǎo)入 調(diào)用函數(shù)帖旨,可省略包名. 不建議使用
import (
"fmt"
. "github.com/WPFS/gopkg"
)
(5) 下劃線導(dǎo)入 (使用下劃線作為別名)調(diào)用包的初始化函數(shù)init箕昭。
init函數(shù)是初始化包使用,無返回值解阅,無參數(shù)落竹。建議每個(gè)包只定義一個(gè)
init函數(shù)在import包時(shí)自動(dòng)被調(diào)用(const-->var-->init)
import (
"fmt"
_"gopkg"
"github.com/WPFS/gopkg"
)
*/
3. 包-成員可見性
/*
Go語言使用名稱首字母大小寫來判斷對(duì)象(常量、變量货抄、函數(shù)述召、類型、結(jié)構(gòu)體蟹地、方法等)的訪問權(quán)限积暖,
首字母大寫標(biāo)識(shí)包外可見(公開的),否則僅包內(nèi)可訪問(內(nèi)部的)
*/
4. main包和main函數(shù)
/*
main包用于聲明告知編譯器將包編譯為二進(jìn)制可執(zhí)行文件
在main包中的main函數(shù)是程序的入口怪与,無返回值夺刑,無參數(shù)
*/
5. 包管理
/*
(1)gopath
(2)gopath+vendor
將項(xiàng)目依賴包拷貝到項(xiàng)目下的vendor目錄,在編譯時(shí)使用項(xiàng)目下vendor目錄中的包進(jìn)行編譯
解決的問題依賴包過多,在使用第三方包時(shí)需要使用go get進(jìn)行下載
第三方包在go get下載后不能保證開發(fā)和編譯時(shí)版本的兼容性
查找順序
當(dāng)前包下的vender目錄查找
向上級(jí)目錄查找,直到gopath/src/vender目錄
在gopath目錄查找
在goroot目錄查找
go get常用參數(shù)
-d 僅下載依賴包
-u 更新包并安裝
-x 打印執(zhí)行的命令
-v 打印構(gòu)建的包
-insecure 允許使用http協(xié)議下載包
第三方包查找地址
https://godoc.org
https://gowalker.org
(3)go modules機(jī)制
a)優(yōu)勢
不用設(shè)置GOPATH分别,代碼可任意放置
自動(dòng)下載依賴管理
版本控制
不允許使用相對(duì)導(dǎo)入
replace機(jī)制
1. 初始化 go mod init [module name]
2. 編寫main程序
3. go build
4. 包管理 go mod tidy
5. go mod edit -replace=golang.org/x/crypto=github.com/golang/crypto@latest
6. go build
第三方包:
在使用 go mod tidy遍愿、go build、go test耘斩、go list命令會(huì)自動(dòng)將第三方依賴包寫入到go.mod文件中同時(shí)下載第三方依賴包到GOPATH/pkg/mod/cache目錄沼填,
并在當(dāng)前模塊目錄生成一個(gè)構(gòu)建狀態(tài)跟蹤文件go.sum,文件中記錄當(dāng)前module所有的頂層和間接依賴,以及這些依賴的檢驗(yàn)和
常用命令
go mod tidy 整理依賴模塊
go mod vendor 將依賴模塊拷貝到模塊中vendor目錄
go build 編譯當(dāng)前模塊
go build ./... 編譯當(dāng)前目錄下的所有模塊
go build -mod=vendor 使用當(dāng)前模塊下的vendor目錄中的包進(jìn)行編譯
go mod download 僅下載第三方模塊
go mod grapha 打印所有第三方模塊
go list -m -json all 顯示所有模塊信息
go mod edit 修改go.mod文件
-require=package@version
-replace=old_package@version=new_package@version
replace (
golang.org/x/crypto => github.com/golang/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/net => github.com/golang/net v0.0.0-20190628185345-da137c7871d7
golang.org/x/sync => github.com/golang/sync v0.0.0-20190423024810-112230192c58
golang.org/x/sys => github.com/golang/sys v0.0.0-20190626221950-04f50cda93cb
golang.org/x/text => github.com/golang/text v0.3.2
golang.org/x/tools => github.com/golang/tools v0.0.0-20190706070813-72ffa07ba3db
)
6. testing 單元測試和基準(zhǔn)測試(性能)
a) 創(chuàng)建testcalc/calc目錄
b) 運(yùn)行g(shù)o mod init testcalc
b) 編寫calc.go文件
package calc
func Add(x, y int) int {
if x > 0 {
return x + y
} else {
return x
}
}
func Fact(n int) int {
if n == 0 {
return 1
}
return n * Fact(n-1)
}
c) 編寫calc_test.go
package calc
import "testing"
func TestAdd(t *testing.T) {
if 4 != Add(1, 3) {
t.Errorf("1+3 = 4")
}
}
func TestFlag(t *testing.T) {
if -1 != Add(-1, 3) {
t.Errorf("-1 + any != -1")
}
}
func BenchmarkFact(b *testing.B) {
for i := 1; i <= 10; i++ {
Fact(i)
}
}
d) go test testcalc/calc
go test testcalc/calc --coverprofile=cover.out # 測試覆蓋率
go tool cover -html cover.out
go test testcalc/calc -bench .
}