go mod有时候会报cannot find module providing package xxxx的错,找资料也没有解决。所以自己探索了下,记录一下。
首先,先尝试整一个正常的。
1 // tooljob.go
2
3 package tools
4
5 import "fmt"
6
7 func Print() {
8 fmt.Println("hello,there")
9 }
1 // utiljob.go
2
3 package util
4
5 import "tools"
6
7 func Get() {
8 tools.Print()
9 }
1 // main.go
2
3 package main
4
5 import "util"
6
7 func main() {
8 util.Get()
9 }
目的是在work/中编译出程序。只有这几个文件肯定不行:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
2 main.go:5:8: cannot find package "util" in any of:
3 /usr/local/go/src/util (from $GOROOT)
4 /home/zxq/go/src/util (from $GOPATH)
因为,main中包含util包,但是util包没有找到。因为go version go1.14.12 linux/amd64。GO111MODULE="auto"。没有go.mod文件,所以到GOROOT和GOPATH去找。结果自然没有找到。
添加go.mod:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ go mod init aimport
2 go: creating new go.mod: module aimport
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ tree
2 .
3 ├── go.mod
4 ├── tools
5 │ └── tooljob.go
6 ├── util
7 │ └── utiljob.go
8 └── work
9 ├── main.go
10 └── work
11
12 3 directories, 5 files
这里没有让mod名和目录名一致,也是故意不按套路出牌,好探索下。
再次到work下编译,发现已经不到GOPATH去找了:
备注:以上是go1.14.12的提示。在1.13.3中,本地mod没有util包,会在ROOT中查找util包,还找不到的话,会到互联网查找,但是此时会判断包名是否符合域名的命名规则,不符合就报下面的错误。:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
2 build aimport/work: cannot load util: malformed module path "util": missing dot in first path element
也就是说,尽管go.mod位于它的上一级,也被识别到了,但是没有找到util包。
把main.go中的import修改,补全路径:"aimport/util":
1 // main.go
2
3 package main
4
5 import "aimport/util"
6
7 func main() {
8 util.Get()
9 }
发现引用util不报错,只报tools的错了(毕竟引用tools包还没修改)。
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
2 build aimport/work: cannot load tools: malformed module path "tools": missing dot in first path element
修改完utiljob.go 中的tools引用,可以编译成功了:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ cat ../util/utiljob.go
2 // utiljob.go
3
4 package utilabc
5
6 import "aimport/tools"
7
8 func Get() {
9 tools.Print()
10 }
11 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
12 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ ls
13 main.go work
至此,一个正常的go mod模式的框架完成。
探索1,包名和路径:
util包名修改为utilabc:
1 // utiljob.go
2
3 package utilabc
4
5 import "aimport/tools"
6
7 func Get() {
8 tools.Print()
9 }
编译结果:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
2 # aimport/work
3 ./main.go:5:8: imported and not used: "aimport/util" as utilabc
4 ./main.go:8:2: undefined: util
没报引用不对,只是引用后没有使用。修改之后:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ cat main.go
2 // main.go
3
4 package main
5
6 import "aimport/util"
7
8 func main() {
9 utilabc.Get()
10 }
11 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
12 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ ls
13 main.go work
可以编译。反过来试下,引用包名,而不是路径:
zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ cat main.go
// main.go
package main
import "aimport/utilabc"
func main() {
utilabc.Get()
}
zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
build aimport/work: cannot load aimport/utilabc: malformed module path "aimport/utilabc": missing dot in first path element
说明import后面是路径,而不是包名。
但是 import "aimport/util" 不能写成 import "myimport/util" 否则报错:**
**
同样,上面是1.14.12的报错。在1.13.3:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
2 build aimport/work: cannot load myimport/util: malformed module path "myimport/util": missing dot in first path element
所以,import中的mod名,要和go.mod一致,不是路径名;后面的package名,是路径,不是包名。
探索2, 编译:
1.14.12的情况:
1.13.3的情况:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ go build work/main.go
2 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ tree
3 .
4 ├── go.mod
5 ├── main
6 ├── tools
7 │ └── tooljob.go
8 ├── util
9 │ └── utiljob.go
10 └── work
11 ├── main.go
12 └── work
13
14 3 directories, 6 files
15 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ go build
16 build .: cannot find module for path .
17 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ go build aimport
18 can't load package: package aimport: package aimport is not in the main module (aimport)
修改下名字,看看二进制文件的命名:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ mv work/main.go work/maina.go
2 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ go build work/maina.go
3 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ tree
4 .
5 ├── go.mod
6 ├── maina
7 ├── tools
8 │ └── tooljob.go
9 ├── util
10 │ └── utiljob.go
11 └── work
12 ├── maina.go
13 └── work
14
15 3 directories, 6 files
在外部编译,输出的二进制文件名字用main函数所在文件名命名。原地编译,使用目录名来命名。
探索3,work模块加上go mod
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go mod init work
2 go: creating new go.mod: module work
3 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
4 build work: cannot load aimport/util: malformed module path "aimport/util": missing dot in first path element
找不到aimport/util,在go.mod中添加require和replace:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ cat go.mod
2 module work
3
4 go 1.13
5
6 replace aimport/util => ../util
7 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
8 go: work imports
9 aimport/util: parsing ../util/go.mod: open /mnt/d/test_work/myimport/util/go.mod: no such file or directory
报错,需要util中有go.mod文件。既然如此,那就不引用到具体下层, 只添加:
replace aimport => ../
没问题,且go.mod自动加入了require aimport:
zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ cat go.mod
module work
go 1.13
replace aimport => ../
require aimport v0.0.0-00010101000000-000000000000
zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ ls
go.mod main.go work
探索4:给util加上go.mod
1.14.12:
1.13.3:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/util$ go mod init util
2 go: creating new go.mod: module util
3 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/util$ cd ../work/
4 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
5 build work: cannot load aimport/util: malformed module path "aimport/util": missing dot in first path element
找不到util了。
到这里其实比较清楚了。go.mod会隔离开各个编译的区间。各个区间如果有上下层目录关系,那么就会透明不可见,不可直接引用。如果需要引用,可以使用replace去指定查找路径。
把work/中的go.mod移除后,保留util中的go.mod,那么work即归属于mod aimport,但是与util隔离。
此时,在mod aimport添加replace 信息,才能引用到util:
1 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ go build
2 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport/work$ cd ../
3 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ tree
4 .
5 ├── go.mod
6 ├── maina
7 ├── tools
8 │ └── tooljob.go
9 ├── util
10 │ ├── go.mod
11 │ └── utiljob.go
12 └── work
13 ├── main.go
14 └── work
15
16 3 directories, 7 files
17 zxq@DESKTOP-0BAPSTC:/mnt/d/test_work/myimport$ cat go.mod
18 module aimport
19
20 go 1.13
21
22 replace aimport/util => ./util
23
24 require aimport/util v0.0.0-00010101000000-000000000000
探索5,知道了上面的规则后,看下mod命名,包名,路径名相关:
在main中引用的是utilabc的Get()方法。但是import是引入的aimport/tools,经过其归属的mod文件指向到./util(其实是../util)。
在./util中,mod命名为utilmod,包名为utilabc。
至此,还未发现开头提到的错误:cannot find module providing package xxxx。未完待续。。。
【迁移】www.cnblogs.com/zxq89/p/140… posted @ 2020-12-01 21:53