包是go最小的分发单位。
包是函数和数据的集合,将有相关特性的函数和数据放在统一的文件/目录进行管理,每个包都可以作为独立的单元维护并提供给其他项目进行使用。
包声明
Go 源文件都需要在开头使用 package
声明所在包,包名告知编译器哪些是包的源代码用于编译库文件,其次包名用于限制包内成员对外的可见性,最后包名用于在包外对公开成员的访问。
包名使用简短的小写字母,常与所在目录名保持一致,一个包中可以由多个 Go 源文件,但必须使用相同包名。
导入
在使用包时需要使用 import 将包按路径名导入,再通过包名调用成员。
可通过 import 每行导入一个包,也可使用括号包含所有包并使用一个 import 导入。
工作目录结构:
-
bin
: 用于放置发布的二进制程序 -
pkg
: 用于放置发布的库文件 -
src
: 用于放置源代码
运行:
- 将 源码 目录添加到 GOPATH 环境变量中
- 编译&运行
使用 go build 编译二进制文件
命令:go build gpkgmain
说明:编译路径 gpkgmain 下的包,main 包,则在当前目录产生以 pkgmain 命名的二进制程序
使用 go run 运行二进制文件
命令:go run gpkgmain
使用 go install 编译并发布二进制文件
命令:go install gpkgmain
说明:编译并发布路径 gpkgmain 下的包,main 包,则在将编译后的以 pkgmain 命名的二进制程序拷贝到 bin 目录
使用 go install 编译发布库文件
命令:go install gpkgname/pkg01
说明:编译并发布路径 gpkgname/pkg01 下的包,非 main 包,则在将编译的以包名命名的库文件拷贝到 pkg/GOOS_GOARCH 目录下
使用 go install 编译发布所有二进制和库文件
命令:go install ./…
说明:编译并发布当前路径下的所有二进制程序和库文件
注意:Go 语言不允许交叉导入包
1. go get
go get 下载目录到gopath的第一个路径中
go env
echo $GOPATH
go get github.com/WPFS/gopkg
*/
2. 包的导入方式
/*
(1) 绝对导入
import (
"fmt"
"github.com/WPFS/gopkg"
)
(2) 相对导入,不建议使用
import (
"fmt"
"./github.com/WPFS/gopkg"
)
(3) 别名导入解决多个包或者包内函数名冲突
import (
lgopkg "gopkg"
"github.com/WPFS/gopkg"
)
(4) 点导入 调用函数,可省略包名. 不建议使用
import (
"fmt"
. "github.com/WPFS/gopkg"
)
(5) 下划线导入 (使用下划线作为别名)调用包的初始化函数init。
init函数是初始化包使用,无返回值,无参数。建议每个包只定义一个
init函数在import包时自动被调用(const-->var-->init)
import (
"fmt"
_"gopkg"
"github.com/WPFS/gopkg"
)
*/
3. 包-成员可见性
/*
Go语言使用名称首字母大小写来判断对象(常量、变量、函数、类型、结构体、方法等)的访问权限,
首字母大写标识包外可见(公开的),否则仅包内可访问(内部的)
*/
4. main包和main函数
/*
main包用于声明告知编译器将包编译为二进制可执行文件
在main包中的main函数是程序的入口,无返回值,无参数
*/
5. 包管理
/*
(1)gopath
(2)gopath+vendor
将项目依赖包拷贝到项目下的vendor目录,在编译时使用项目下vendor目录中的包进行编译
解决的问题依赖包过多,在使用第三方包时需要使用go get进行下载
第三方包在go get下载后不能保证开发和编译时版本的兼容性
查找顺序
当前包下的vender目录查找
向上级目录查找,直到gopath/src/vender目录
在gopath目录查找
在goroot目录查找
go get常用参数
-d 仅下载依赖包
-u 更新包并安装
-x 打印执行的命令
-v 打印构建的包
-insecure 允许使用http协议下载包
第三方包查找地址
https://godoc.org
https://gowalker.org
(3)go modules机制
a)优势
不用设置GOPATH,代码可任意放置
自动下载依赖管理
版本控制
不允许使用相对导入
replace机制
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命令会自动将第三方依赖包写入到go.mod文件中同时下载第三方依赖包到GOPATH/pkg/mod/cache目录,
并在当前模块目录生成一个构建状态跟踪文件go.sum,文件中记录当前module所有的顶层和间接依赖,以及这些依赖的检验和
常用命令
go mod tidy 整理依赖模块
go mod vendor 将依赖模块拷贝到模块中vendor目录
go build 编译当前模块
go build ./... 编译当前目录下的所有模块
go build -mod=vendor 使用当前模块下的vendor目录中的包进行编译
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 单元测试和基准测试(性能)
a) 创建testcalc/calc目录
b) 运行go 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 .
}