
Sometimes you need to write an application that should use different versions of the same package, for example, the ability to work with versions v1.0.1 and v1.22.0 simultaneously. The reasons why can be different, e.g., you have a library that works only with one version of protocol, but your application should be able to work with legacy and modern systems that use different protocol versions or file formats, API versions, encoding, encryption, etc.
You can use the Go module directive called “replace” in this case, as “replace” allows us to rename the package and use the new name to import it into the program.
Usage is pretty simple:
“replace new/name/for/package => github.com/realpackagename v1.0.0”
As an example, let’s make a program that will simultaneously use the package “github.com/pkg/errors” versions v0.8.1 and v0.9.1.
In the go.mod file, we can give the package any new name, but for convenience, it’s better to add a version number to the normal path. As a result, we obtain the following content:
module multiversion go 1.13 replace github.com/pkg/errors/081 => github.com/pkg/errors v0.8.1 replace github.com/pkg/errors/091 => github.com/pkg/errors v0.9.1
Now, using the new names, we import these two packages into the go file and use them.
package main import ( "fmt" errors081 "github.com/pkg/errors/081" errors091 "github.com/pkg/errors/091" ) func main() { err := errors081.New("New error for v0.8.1") fmt.Println(err) err = errors091.New("New error for v0.9.1") fmt.Println(err) }
So, now you just have to build and run the program:
$ ./multiversion New error for v0.8.1 New error for v0.9.1
Thus, your application can use several versions of one package at the same time without using, for example, gopkg.in or git submodules. Moreover, everything can be easily written in one root go.mod file.