Go语言入门到实战——00主目录 在上一讲中我们学习了Go语言的错误处理的知识。
一.Go语言package的特点
1.基本复用模块单元:
以首字母大写来表明可被包以外的代码访问。如函数,结构体(或其成员名)
等定义时首字母大写代表可以被外包的代码访问
2.代码的package可以和所在的目录名不一致,但是在同一个目录下的
不同文件所在包的包名需要一致(这个读者可以自己实验)
首先我先讲一个自己构建可复用包的案例:
//现在我的项目目录结构如下:(位于E:\go_workspace\go_helloproject)
go_helloproject:
src:
hello:
add.go
test:
addUse_test.go
先在命令行使用go env
来查看go语言的导包路径GOPATH:
//我的是:
GOPATH=C:\Users\Administrator\go
//我们需要添加我们的包路径使其成为可复用包,设置的原则就是一直到src的前一步
//(src时默认的可以导包的位置),因此在搭建的时候注意先建src包在继续构建其它
//最后的结果是下面这样,具体设置方法根据Windows系统和Linux系统可自行百度
//注意Linux应该把下面的分号改为冒号':'
GOPATH=C:\Users\Administrator\go;E:\go_workspace\go_helloproject
//修改完记得重启IDE
add.go的代码如下
//add.go
package hello_add
func add(a int, b int) int {
return a + b
}
addUse_test.go
//addUse_test.go
package testAdd
import (
hello_add "hello"//这里由于hello目录下的add.go的包名
//为hello_add,所以导入时需要起别名为其包名(其实也可以不是包名
//,但是必须起别名,随便什么都可,不过建议和包名一致)
//当然如果add.go的包名就是hello,那么就不需要使用别名了
"testing"
)
func TestAdd(t *testing.T) {
t.Log(hello_add.Add(1, 2))
}
接下来我们测试下大写字母的问题:
//在add.go中添加这个函数
func square(a int) int {
return a * a
}
二.init方法
1.在main/test被执行之前,所以依赖的package的init方法都会被执行
2.不同包的init方法按照包的导入依赖关系决定执行的顺序
3.每个包可以有多个init方法
4.包的每个源文件也可以有多个init方法,这点比较特殊
在add.go里面添加下面内容:
func init() {
fmt.Println("init1")
}
func init() {
fmt.Println("init2")
}
执行测试如下(在输出Add方法的结果前,init先被执行了,并且是按照在源文件add.go里面的顺序执行的):
三.远程package的使用
//我们使用go get 命令下载包:
//-u表示会更新依赖和对应的下载的包,不使用-u那么对于已经存在的包或者依赖不会去更新
//https://github.com/easierway/concurrent_map.git的https://和.git都要去掉
go get -u github.com/easierway/concurrent_map
在下载包时我出现了git clone出现错误 fatal: unable to access ‘https://github.com/…‘的解决办法
package testAdd
import (
"testing"
cm "github.com/easierway/concurrent_map"
)
func TestConcurrentMap(t *testing.T) {
m := cm.CreateConcurrentMap(99)
m.Set(cm.StrKey("key"), 10)
t.Log(m.Get(cm.StrKey("key")))
}
最后需要强调的一点就是在提交自己的源码到github时不要把src也提交了,不然git get就会找不到,即直接以代码路径开始,不要有src。
四.依赖管理
Go语言依赖管理其实并不完善,还有下面两个未解决的问题
1.同一环境下,不同项目使用同一包的不同版本没有实现
get下来的包会放在Gopath里面,项目在查找包时会现在Gopath里面寻找,然后在从Goroot里面去找,
这样会造成所有的项目使用的是同一个版本的包,而自己特定的包版本就无法使用了
2.无法管理对包的特点版本的依赖
我们在使用get是发现从来没有指定过包的版本,因此缺乏对特定版本的报的依赖管理
那么为了解决上面的问题官方给出了vendor路径来解决这一问题。
vecdor目录是被添加到GOPATH和GOROOT之外的依赖目录的查找解决方案。这个在Go1.6之前需要自己手动
设置环境变量
有了vendor目录后查找包的解决方案就是:
1.当前包的vendor目录
2.向上级目录查找,直到找到src下的vendor目录
3.在GOPATH下查找依赖包
4.在GOROOT下查找依赖包
常见的依赖管理工具充分利用了vendor来帮我们做到;
1.godep:https://github.com/tools/godep (比较早期了)
2.glide:https://github.com/Masterminds/glide
3.dep:https://github.com/golang/dep (相比于前两个是最新的)
下面演示glide:
1.安装glide(Linux)
brew install glide
不过在Windows下使用会有一些bug,参加这篇文章修正
cs
最后生成glide.exe是在glide目录下使用go build即可,最后替换掉go/bin下的glide.exe
接下来我们以上面的concurrent_map为例来进行演示
1.进入到测试concurrent_map的go文件所在包,然后执行glide init,后面的可以根据需要自行选择
此时会在当前目录生成一个ymal文件,里面记载了当前目录下所有文件你所依赖的包,我们这里就是
concurrent_map包
2.glide install
表示根据yaml文件的内容进行依赖包下载,并且会生成vendor目录
这样我们就可以在vendor目录下使用我们自己想要的版本包了(指定版本可以在ymal里面修改
如果报update失败可能就是版本号的问题,这就需要自己修改对了)
go语言中go.mod文件有什么用