I started to learn the language Golang in 2018. At that time, vendor was widely used in package management. During project development, we only need to perform vendor initialization (govendor Init) in the root directory of the project, and the file directory vendor/ for package management will be produced in the root directory of the project. There is a vendor.json file in this directory, which is similar to the godep tool for describing the version of the file.
Here is an example of this file
{ "comment": "", "ignore": "", "package": [ { "checksumSHA1": "qL4naKgOOJE2hXxKKYu+5W2ULHU=", "path": "github.com/certifi/gocertifi", "revision": "0944d244cd40db6fa14fa14fc8c53b29f0ad66e4", "revisionTime": "2019-10-21T19:10:39Z" }, ...... ] , "rootPath": "/path/to/project" }Copy the code
Of course, when the project is created, the contents of the package list are not available before the package is imported. When a package is introduced during project development, simply execute the govendor add +external command to add the referenced package to the package list.
In addition, the current version of the package is placed in the vendor directory, as shown in the example below
In the project code management system, we need to manage vendor files uniformly.
Recently in the new project, we introduced the package management tool mod from Golang 1.11 1.12.
This is different from the vendor. Let’s look at how mods manage packages.
A module is a collection of Go packages stored in a file tree, with the go.mod file in its root directory. The go.mod file defines the module path for the module (which is also the import path for the root directory) and its dependency requirements, which are the other modules needed for a successful build. Each dependency requirement is written as a module path and a specific semantic version.
Take a look at a simple example
Let’s take the greeter example from Micro and write a simple hello World in client-server mode.
First take a look at the greeter.proto file
syntax = "proto3";
service Greeter {
rpc Hello(HelloRequest) returns (HelloResponse) {}
}
message HelloRequest {
string name = 1;
}
message HelloResponse {
string greeting = 2;
}
Copy the code
The function of the whole project is very simple, so let’s see how to manage packages through mod
First, we initialize with go mod init /path/to/project. This will produce a go.mod file in the root directory of the project
The module modtest go 1.13Copy the code
We produce the corresponding GO code via Protoc.
protoc --micro_out=. --go_out=. ./greeter/greeter.proto
Copy the code
Then implement a simple server
➜ server more server.go package main import ("context" "FMT" proto "modtest/greeter" micro" github.com/micro/go-micro" ) type Greeter struct{} func (g *Greeter) Hello(ctx context.Context, req *proto.HelloRequest, rsp *proto.HelloResponse) error { rsp.Greeting = "Hello " + req.Name return nil } func main() { // Create a new service. Optionally include some options here. service := micro.NewService( micro.Name("greeter"), ) // Init will parse the command line flags. service.Init() // Register handler proto.RegisterGreeterHandler(service.Server(), new(Greeter)) // Run the server if err := service.Run(); err ! = nil { fmt.Println(err) } }Copy the code
After running the server, implement a client to communicate with the server
➜ client more client.go
package main
import (
"context"
"fmt"
proto "modtest/greeter"
micro "github.com/micro/go-micro"
)
func main() {
// Create a new service. Optionally include some options here.
service := micro.NewService(micro.Name("greeter.client"))
service.Init()
// Create new greeter client
greeter := proto.NewGreeterService("greeter", service.Client())
// Call the greeter
rsp, err := greeter.Hello(context.TODO(), &proto.HelloRequest{Name: "John"})
if err != nil {
fmt.Println(err)
}
// Print response
fmt.Println(rsp.Greeting)
}
Copy the code
Now let’s look at the management of its dependency packages
➜ modtest more go.mod
module modtest
go 1.13
require github.com/micro/go-micro v1.18.0
Copy the code
Automatic introduction of the Go-Micro package. And the version is specified. At the same time, you’ll notice that in the project directory, there’s a file called go.sum. Take some of it and look at it
➜ modtest more go.sum cloud.google.com/go v0.26.0/go.mod H1 :aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod H1 :aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod H1:990 n + gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU = contrib. Go. Opencensus. IO/exporter/ocagent v0.4.12 / go mod H1:450 aplntsr6frvc3ctrqyosudstrb9un7sox2k/cka = 9 github.com/Azure/azure-sdk-for-go v32.4.0 + incompatible. / go to the mod H1:9 xxnku + eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc = github.com/Azure/go-ansiterm v0.0.0-20170929234023 - d6e3b3328b78 / go. Mod H1: LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8 = github.com/Azure/go-autorest/autorest v0.1.0 / go mod H1: AKyIcETwSUFxIcs / + kwCtlEYGUVd7FPNb2slmg Wnq/C = github.com/Azure/go-autorest/autorest v0.5.0 / go mod h1:9HLKlQjVBH6U3oDfsXOeVc56THsLPw1L03yban4xThw=Copy the code
These are cryptographic hashes for software versions. Ensure that later downloads of these modules are the same bits retrieved during the first download to ensure that the modules on which your project depends do not change accidentally due to malicious, accidental, or other reasons.
Both go.mod and go.sum should be committed to code version control.
So what if we upgrade dependencies?
$go list -m all github.com/coreos/bbolt v1.3.3 github.com/coreos/etcd v3.3.17+incompatible github.com/coreos/go-semver V0.3.0 github.com/coreos/go-systemd v0.0.0-20190719114852 - fd7a80b32e1f github.com/coreos/pkg Ea9e2e55f v0.0.0-20180928190104-399Copy the code
Did you notice that some versions are specified directly, while others are given directly as V0.0.0
A given release is divided into three parts: body, minor release, and patch, such as V1.3.3, major release 1, minor release 3, and patch 3. This v0.0.0 is the unmarked version. In other words, we can upgrade this version to the latest version without any impact, and the project can still run normally.
➜ modtest go get github.com/coreos/pkg
go: finding github.com/coreos/pkg latest
Copy the code
Let’s run our project
Go run server.go error
➜ server go run for server go # github.com/coreos/etcd/clientv3/balancer/resolver/endpoint.. /.. /.. /.. / pkg/mod/github.com/coreos/[email protected]+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:114:78: undefined: resolver.BuildOption .. /.. /.. /.. / pkg/mod/github.com/coreos/[email protected]+incompatible/clientv3/balancer/resolver/endpoint/endpoint.go:182:31: undefined: resolver.ResolveNowOption # github.com/coreos/etcd/clientv3/balancer/picker .. /.. /.. /.. / pkg/mod/github.com/coreos/[email protected]+incompatible/clientv3/balancer/picker/err.go:37:44: undefined: balancer.PickOptions .. /.. /.. /.. / pkg/mod/github.com/coreos/[email protected]+incompatible/clientv3/balancer/picker/roundrobin_balanced.go:55:54: undefined: balancer.PickOptionsCopy the code
Check out our go.mod
➜ modtest more go. Mod module modtest go 1.13 the require (github.com/golang/protobuf v1.4.1 github.com/micro/go-micro V1.18.0 google.golang.org/protobuf v1.25.0)Copy the code
Software versions are incompatible. So how do we solve this problem? We want to see what’s valuable in the error message, and indeed everyone can see incompatibilities, who’s incompatibilities with whom, and how do we solve incompatibilities. Now let’s look at etcd of the codebase 3.3.17 library version, this version of its associated code can go with us. The mod packages have management namely google.golang.org/protobuf, we go. Version is v1.25.0 mod.
whileEtcd 3.3.17
The required version isv1.23.0
Version of thegrpc
. Looking at thev1.23.0
Version of thegrpc
So versions that resolve such conflicts will either upgrade etCD or degrade Protobuf. The solution for ease of use and thinking is to update the protobuf version directly.
After the protobuf version in go.mod is updated to v1.23.0, the server is started successfully
1.13 the require module modtest go (github.com/golang/protobuf v1.4.1 github.com/micro/go-micro v1.18.0 Google.golang.org/protobuf v1.23.0)Copy the code
Finally, many unnecessary versions may have been introduced during debugging. Go.mod is confusing and can be passed at this time
$go mod tidy
Copy the code
Manage update packages.
What do you think about modding software package dependency management and vendor? Which one do you prefer? Welcome to join the discussion