文章目录
  1. 1. Go mod 嵌套引用不同版本的module,最终使用哪个版本?
  2. 2. Go mod如何同时引用多个版本的module

首先,注意区分使用Go mod后,module和package的概念

  • module是go mod的引入单位,go.mod文件里引入的是module:

image

  • package是go代码import的单位,一个module可以覆盖多个package

image

Go mod 嵌套引用不同版本的module,最终使用哪个版本?

答案是:全局使用二者之中最新的版本来运行程序。

比如下面的目录关系:

1
2
3
4
5
6
7
8
9
$ tree
.
├── go.mod
├── go.sum
├── mtest
│   ├── go.mod
│   ├── go.sum
│   └── main.go
└── test.go

test.go一级的go.mod里引用一个版本的qmgo

1
2
3
require (
github.com/qiniu/qmgo v0.7.6
)

mtest一级的go.mod里使用另一个版本:

1
2
3
require (
github.com/qiniu/qmgo v0.7.7

然后在test.go里调用mtest包里的方法RunTest(),此时,go mod会选择二者中最新的版本来进行编译和运行,也是就说test.gomtest.go里使用的qmgo都是v0.7.7版本(test.go一级的go.mod里的v0.7.6会被改写成v0.7.7)。

上例中两个go.mod的引用版本调换,结果依然是使用最新的版本来编译和运行。

Go mod的这个设计无可厚非,只是实际工程中,包的引用是间接的、复杂的,如果某个包的新版本不向前对旧版本兼容,比如新版本删除了一个旧版本的API,那么使用新版本来编译旧版本实现,会导致编译失败。解决方案需要根据实际情况来具体分析,比如替换旧版本module引用(线上更新或者拉私有库修改),回退新版本,某些情况下也可以通过下面的方法同时支持2个版本的存在。

代码如下:

test.go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"context"
"fmt"
"mtest" // test.go一层的go.mod里,mtest需要replace,上面的go.mod里没有写

"github.com/qiniu/qmgo"
)

func main() {
client, err := qmgo.NewClient(context.Background(), &qmgo.Config{Uri: "mongodb://localhost:27017"})
fmt.Println(err)
defer client.Close(context.Background())

mtest.RunTest()
}

mtest.go:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package mtest

import (
"context"
"fmt"

"github.com/qiniu/qmgo"
)

func RunTest() {
client, err := qmgo.NewClient(context.Background(), &qmgo.Config{Uri: "mongodb://localhost:27017"})
fmt.Println(err)
defer client.Close(context.Background())
}

Go mod如何同时引用多个版本的module

使用replace即可达成目的

1
2
3
4
5
6
7
8
9
10
module test

go 1.14

replace github.com/qiniu/qmgo077 => github.com/qiniu/qmgo v0.7.7

require (
github.com/qiniu/qmgo v0.7.6
github.com/qiniu/qmgo077 v0.0.0-00010101000000-000000000000 // 自动生成
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import (
"context"
"fmt"

"github.com/qiniu/qmgo"
qmgo077 "github.com/qiniu/qmgo077"
)

func main() {
client, err := qmgo.NewClient(context.Background(), &qmgo.Config{Uri: "mongodb://localhost:27017"})
fmt.Println(err)
defer client.Close(context.Background())

client077, err := qmgo077.NewClient(context.Background(), &qmgo077.Config{Uri: "mongodb://localhost:27017"})
fmt.Println(err)
defer client077.Close(context.Background())
}

本文引自这里

文章目录
  1. 1. Go mod 嵌套引用不同版本的module,最终使用哪个版本?
  2. 2. Go mod如何同时引用多个版本的module