前言
无论什么Python还是Golang当你的代码量达到一定程度时,就需要使用package来组织我们的代码文件。
package概念
在项目开发过程中组织代码的一中方式。包是多个Go文件的集合,是一种高级的代码复用方案,Go语言为我们提供了很多内置包,如fmt
、os
、io
等。
在目前我使用的go1.11.5中每1个.go文件都需要存放在Gopath路径下的1个文件中(包)。
package main
.go文件最开始声明这是1个main包,也就是程序的入口。
package使用
定义package
一般来说除了1个程序入口(main包)之外,在Go项目中其他都是我们程序开发人员自由定义的(工具包),以便调用。
我们使用package关键字定义1个包,
如果当前package想要被其他包调用,那么该工具包中的标识符(变量名、函数名、struct名、interface名)首字母大写表示可见性(对外可见)。
在Go中1个文件夹就是1个package, 所以package中的.go文件一般会和package同名。
programmer.go
package devlepment import "fmt" //Programer 大写才能被外部其他包调用 func Programer(name string) { fmt.Printf(` I'm %s a programmer work in devlepment department I interest in programing.in my free time I like seing some Science fiction films ranther than porn. `, name) }
init函数
包中的init函数在调用该包时自动执行
package resources import "fmt" //init:导入包时自动执行 func init(){ fmt.Println("导入resources包时自动执行") receptionist("May") } func receptionist(nam string){ fmt.Println(`Good morning.may I help you? `) }
init()函数执行顺序
Go语言包会从main
包开始检查其导入的所有包,每个包中又可能导入了其他的包。Go编译器由此构建出一个树状的包引用关系,再根据引用顺序决定编译顺序,依次编译这些包的代码。
Golang中1个包可以包含1个init函数,不一样的是这个init函数需要自己定义。
调用包时会最先初始化并调用包中mian函数的init()
函数, 如下图示:
导入package
调用Go里面的包需要从Go project的src目录后面的文件夹开始import。
hello/package_practice/devlepment
package main import ( //匿名调用包:只调用执行包中init函数中的代码,不使用(pymysql) _ "hello/package_practice/resources" //别名:包所在的路径 devlepment "hello/package_practice/devlepment" sales "hello/package_practice/sales" finnace "hello/package_practice/finance" ) func main(){ devlepment.Programer("Sam") finnace.Contant("Sally") sales.Salesman("Todd") }
go mod第三方依赖包管理
为什么需要go mod?
go所有的项目以及项目依赖的第三方库默认情况下全部放在go path/src目录下。如果在项目开发过程中需要不同版本的第三方依赖库,应该怎么解决?
godep依赖包管理
Go语言从v1.5开始开始引入vendor
模式,如果项目目录下有vendor目录,那么go工具链会优先使用vendor
内的包进行编译、测试等。
安装
go get github.com/tools/godep
基本命令
godep save 将依赖项输出并复制到Godeps.json文件中 godep go 使用保存的依赖项运行go工具 godep get 下载并安装具有指定依赖项的包 godep path 打印依赖的GOPATH路径 godep restore 在GOPATH中拉取依赖的版本 godep update 更新选定的包或go版本 godep diff 显示当前和以前保存的依赖项集之间的差异 godep version 查看版本信息
使用godep
在项目目录下执行godep save
命令,会在当前项目中创建Godeps
和vender
两个文件夹。
Godeps
文件夹:有一个Godeps.json
的文件,里面记录了项目所依赖的包信息。
vender
文件夹:是项目依赖的包的源代码文件。
vender机制
Go1.5版本之后开始支持,能够控制Go语言程序编译时依赖包搜索路径的优先级。
例如查找项目的某个依赖包,首先会在项目根目录下的vender
文件夹中查找,如果没有找到就会去$GOAPTH/src
目录下查找。
godep开发流程
- 保证程序能够正常编译
- 执行
godep save
保存当前项目的所有第三方依赖的版本信息和代码 - 提交Godeps目录和vender目录到代码库。
- 如果要更新依赖的版本,可以直接修改
Godeps.json
文件中的对应项
go module依赖包管理
go module
是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,go module
将是Go语言默认的依赖管理工具。
GO111MODULE
要启用go module
支持首先要设置环境变量GO111MODULE
,通过它可以开启或关闭模块支持,它有三个可选值:off
、on
、auto
,默认值是auto
。
GO111MODULE=off
禁用模块支持,编译时会从GOPATH
和vendor
文件夹中查找包。GO111MODULE=on
启用模块支持,编译时会忽略GOPATH
和vendor
文件夹,只根据go.mod
下载依赖。GO111MODULE=auto
,当项目在$GOPATH/src
外且项目根目录有go.mod
文件时,开启模块支持。
简单来说,设置GO111MODULE=on
之后就可以使用go module
了,以后就没有必要在GOPATH中创建项目了,并且还能够很好的管理项目依赖的第三方包信息。
使用 go module 管理依赖后会在项目根目录下生成两个文件go.mod
和go.sum
。
我使用的就是go1.13所以不需要每次都开启go mod模式。
D:goprojectsrc>go env set GO111MODULE=on set GOPROXY=https://goproxy.cn
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中设置的版本和D:goprojectpkgmod中的版本是否一致!
go mod vendor 将依赖复制到vendor下
go mod verify 校验依赖
go mod why 解释为什么需要依赖
使用流程
D:goprojectsrcgo相关模块kafka>SET GO111MODULE=on D:goprojectsrcgo相关模块kafka>SET GOPROXY=https://goproxy.cn D:goprojectsrcgo相关模块kafka>go mod init go: creating new go.mod: module go相关模块/kafka D:goprojectsrcgo相关模块kafka>go mod download go: finding github.com/Shopify/sarama v1.19.0
go mod文件语法
go.mod文件记录了项目所有的依赖信息,其结构大致如下:
module jd.com/logagent //当前包名 go 1.13 //go版本 require ( //在这里指定第三方依赖库的版本信息 github.com/Shopify/sarama v1.19.0 github.com/davecgh/go-spew v1.1.1 // indirect github.com/eapache/go-resiliency v1.2.0 // indirect github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect github.com/eapache/queue v1.1.0 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/hpcloud/tail v1.0.0 github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect gopkg.in/fsnotify.v1 v1.4.7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect )
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 )
go get
在项目中执行go get
命令可以下载依赖包,并且还可以指定下载的版本。
- 运行
go get -u
将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号) - 运行
go get -u=patch
将会升级到最新的修订版本 - 运行
go get package@version
将会升级到指定的版本号version
如果下载所有依赖可以使用go mod download
命令。