目录结构
+D:
+/Projects
+/bin
+/pkg
+/mod
+/src
+/p1
+/package
+/cls1
+/cls2
main.go
-/p2
本文所用案例的环境设定:
GO111MOUDLE
为auto
,GOPATH
为d:/Projects
,GOPATH
下目录有bin
、pkg
、src
,src
中以不同目录区分项目,- 本文所提到的共享包指的是类似
github.com/c1
类型的依赖包;而私有包则是指cls1
类型的依赖包
下面的操作都是以 d:/Projects/src/p1/main.go
为例进行,即名称为p1
的项目,。
一、mod / 非mod 管理方式
go提供了两种项目依赖包的管理方式,一种是mod方式,一种是非mod方式。
1. mod方式
main.go 代码
import(
"github.com/c1"
"github.com/c2"
"bbq.org/o1"
)
终端执行
> go mod init
此刻系统自动生成go.mod
,用于标记所有依赖包。
如果go.mod
内容为空或者go build
时提示依赖包不存在,那可能因为依赖包下载失败了,此刻就需要使用合适的代理,再用go build
或go get
命令获取代码包:
> go get github.com/c1
> go get github.com/c2
> go get bbq.org/o1
go会将这些包下载到%GOPATH%/pkg/mod
(本例即d:/Projects/pkg/mod
)目录中,并将这些包标记在go.mod
内,同时生成go.sum
文件,用于记录包版本。
go.mod
内容如下:
module p1
go 1.17
require (
github.com/c1 v0.0.0-20190825152654-46b345b51c96 // indirect
github.com/c2 v0.3.1 // indirect
bbq.org/o1 v1.24.0 // indirect
)
下载后go会根据版本号自动区分目录
目录结构
+D:
+/Projects
+/bin
+/pkg
+/mod
+/github.com
+/c1@v0.0.0-20190825152654-46b345b51c96
+/c2@v0.3.1
+/bbq.org
+/o1@v1.24.0
+/src
+/p1
+/package
+/cls1
+/cls2
main.go
go.mod
go.sum
-/p2
2.非mod方式
加载方式有多种,此处的例子就是下一节提到的"项目路径"方式。
main.go 代码
import(
"github.com/c1"
"github.com/c2"
"bbq.org/o1"
)
将github.com/c1
、github.com/c2
、bbq.org/o1
三个目录移到d:/Projects/src/
下即可。
注意这种非mod方式目录是不能带版本号的,所以一般不适用于共享依赖包。
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/github.com
+/c1
+/c2
+/bbq.org
+/o1
+/p1
+/package
+/cls1
+/cls2
main.go
-/p2
二、包的加载方式
1.项目路径
以项目名为开头直接引用,我称为项目路径
main.go 代码
import(
"p1/package/cls1"
"p1/package/cls2"
)
- 依托环境变量
GOPATH
,其src
下的项目可直接使用本载入方式; - 项目中有
go.mod
文件,即该项目使用了mod
方式管理包,那么也使用本载入方式。
2. 相对路径
在go没有mod的早期版本,本方式较为常见。
main.go 代码
import(
"./package/cls1"
"./package/cls2"
)
系统提示目录结构不合理
unexpected directory layout:
import path: _/D_/Projects/src/p1/package
root: D:\Projects\src
dir: D:\Projects\src\p1\pkg
expand root: D:\Projects
expand dir: D:\Projects\src\p1\pkg
separator: \
警告你引用的包怎么能和项目都在src下面,不合适,赶紧换~~~
改动很简单,把项目p1
移出%GOPATH%/src
目录就好了,让GOPATH
里只放系统级或共享级的内容。
目录结构
+D:
+Projects
+bin
+pkg
+src
+ppp
+p1
+package
+cls1
+cls2
main.go
-p2
go build 报错 unexpected directory layout 的解决
3. 绝对路径
从没用过,为了写本文试了一下,发现不行,无论项目在src
目录内还是ppp
目录内,都提示不存在
main.go 代码
import(
"d:/Projects/src/p1/package/cls1"
"d:/Projects/src/p1/package/cls2"
)
系统提示路径无效
main.go:3:2: invalid import path: "d:/Projects/src/p1/package/cls1"
main.go:4:2: invalid import path: "d:/Projects/src/p1/package/cls2"
三、综合使用
结合上面的测试,实践中可以用三种方法。
1. 相对路径法
A)共享和私有稍作区隔
main.go 代码
import(
"github.com/c1"
"github.com/c2"
"bbq.org/o1"
"./package/cls1"
"./package/cls2"
)
采用相对路径的项目,其目录不能放在%GOPATH%/src
目录下,请移到别处,src
目录主要用来放依赖包,否则会提示unexpected directory layout
错误
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/github.com
+/c1
+/c2
+/bbq.org
+/o1
+/ppp
+/p1
+/package
+/cls1
+/cls2
main.go
-/p2
B)共享和私有都属一个项目
main.go 代码
import(
"./package/github.com/c1"
"./package/github.com/c2"
"./package/bbq.org/o1"
"./package/cls1"
"./package/cls2"
)
用这个方法,那就和GOPATH
完全没关系了,如果要让兄弟帮忙,把整个项目包给他就完事了,轻松。
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/ppp
+/p1
+/package
+/cls1
+/cls2
+/github.com
+/c1
+/c2
+/bbq.org
+/o1
main.go
-/p2
C)必须注意准确的层级关系
比如p1
下多一个pck
目录
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/ppp
+/p1
+/pck
show.go
+/package
+/cls1
main.go
-/p2
如果pck/show.go
内调用package/cls1
,就需要这么写了
show.go 代码
import(
"../package/cls1"
)
2. 非mod + 项目路径法
参考本文的“非mod方式”
A)共享和私有稍作区隔
main.go 代码
import(
"github.com/c1"
"github.com/c2"
"bbq.org/o1"
"p1/package/cls1"
"p1/package/cls2"
)
将共享包和项目同级,都放在%GOPATH%/src
目录中,共享包相当于一个个项目,go会自动去src
下找项目调用。
总之无论嵌套多少层,一律从项目名开始写包路径
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/github.com
+/c1
+/c2
+/bbq.org
+/o1
+/p1
+/package
+/cls1
+/cls2
main.go
-/p2
B)共享和私有都属一个项目
main.go 代码
import(
"p1/package/github.com/c1"
"p1/package/github.com/c2"
"p1/package/bbq.org/o1"
"p1/package/cls1"
"p1/package/cls2"
)
意思是一样的:一切从项目名开始,但是这里公私都打包在一个package
里了,知道了原理,怎么玩就是你自己的事情了。
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/p1
+/package
+/cls1
+/cls2
+/github.com
+/c1
+/c2
+/bbq.org
+/o1
main.go
-/p2
3. mod + 项目路径法
mod初始化的方法请参考本文的“mod方式”一节。
A)共享和私有稍作区隔
main.go 代码
import(
"github.com/c1"
"github.com/c2"
"bbq.org/o1"
"p1/package/cls1"
"p1/package/cls2"
)
并非只有当项目处于%GOPATH%/src
下才能使用“项目路径”法。
随便搞个文件夹,只要go.mod
所在目录名就是项目名~~
比如这里的D:/ppp/p1
的p1
就是项目名,因为go.mod
在p1
文件夹内。
目录结构
+D:
+/Projects
+/bin
+/pkg
+/mod
+/github.com
+/c1@v0.0.0-20190825152654-46b345b51c96
+/c2@v0.3.1
+/bbq.org
+/o1@v1.24.0
+/src
+/ppp
+/p1
+/package
+/cls1
+/cls2
main.go
go.mod
go.sum
-/p2
B)共享和私有都属一个项目
main.go 代码
import(
"github.com/c1"
"github.com/c2"
"bbq.org/o1"
"p1/package/cls1"
"p1/package/cls2"
)
代码部分并未改变,但是目录结构变了:
通过go mod vendor
命令将依赖包下载到p1/vendor
目录中。
(上一个例子中的依赖包在%GOPATH%/pkg/mod
,即D:/Project/pkg/mod
目录中)
终端执行
> go mod vendor
这时系统会在项目内生成一个vendor
目录,并且将所有包都放入这个目录中。
目录结构
+D:
+/Projects
+/bin
+/pkg
+/src
+/ppp
+/p1
+/package
+/cls1
+/cls2
+/vendor
+/github.com
+/c1@v0.0.0-20190825152654-46b345b51c96
+/c2@v0.3.1
+/bbq.org
+/o1@v1.24.0
main.go
go.mod
go.sum
-/p2
C)系统自动调用和下载
- 在mod方式下,系统会到
D:/Project/pkg/mod
目录和D:/ppp/p1/vendor
目录读取依赖包。 - 如果两个目录都没有,则会将包下载到
D:/Project/pkg/mod
目录中,毕竟GOPATH
放在那里不能当摆设啊~~ - 如果两个目录都有,则会优先加载。。。。(估计是vendor,但还没测试过,有知道的朋友可以留言)
参考:
《go modules:使用 mod 管理项目依赖包,通过vendor实现一键分发编译包》
《Go:go mod vendor 使用》
《go package、import、go.mod 理解 以及 私有包引入》
《go-module的使用》
《go安装依赖包(go get, go module)》
《Golang学习日志 ━━ 下载及安装》
《Golang学习日志 ━━ LiteIDE的主要配置》
《Golang学习日志 ━━ VSCode安装Go插件(代理的使用)及初用mod》
如果有写的不对的地方,欢迎指正,谢谢。