I was using go get -u to get a package which depends on golang.org/x/text#v0.3.7. I noticed that it first downloads golang.org/x/text#v0.3.7 then downloads golang.org/x/text#v0.4.0.
Then I ran go clean -modcache and go get golang.org/x/text which downloaded v0.4.0 of golang.org/x/text and then again go get -u entgo.io/ent. This time go didn't download golang.org/x/text#v0.3.7
So, Why go get -u downloads both the old version and latest version when the latest version is not present locally, and Why it doesn't download the old version when the latest version is available locally?
Because it is a two-step process of
Getting dependencies
Updating dependencies
From a programming standpoint there is no good reason to merge these into a single concern of "Get latest dependencies".
From the go command documentation:
The -u flag instructs get to update modules providing dependencies of packages named on the command line to use newer minor or patch releases when available.
This means that -u specifically deals with modules which the package you are getting depends on, rather than with the module of the package you are getting.
Furthermore, it appears that -u is agnostic to the Go idiom of treating any change in a v0 version as a major version change, so one cannot lightheartedly recommend using -u out of principle. The README of golang.org/x/test even says:
Until version 1.0.0 of x/text is reached, the minor version is considered a major version. So going from 0.1.0 to 0.2.0 is considered to be a major version bump.
TL;DR: Is there any way I can forcefully prevent go get from altering the go.mod file?
When I do a go get of certain packages, e.g.:
$ go get github.com/AsynkronIT/protoactor-go/protobuf/protoc-gen-gograin
It will printout that it has updated dependencies (which are defined in my go.mod file):
go get: upgraded github.com/AsynkronIT/protoactor-go v0.0.0-20200815184336-b225d28383f2 => v0.0.0-20210405044454-10bc19881ad6
# (...) Note, this happens for other packages, not just `AsynkronIT/protoactor-go`.
This causes the go.mod file to change during a CI build, and affects subsequent build stages where, while building something, it’ll try to use an updated version of the dependency, which might introduce breaking changes, instead of the version defined on the go.mod file initially.
I’ve tried using -mod=readonly or making sure the -u flag is not used but it will still update the go.mod file, e.g.:
$ GOFLAGS=-mod=readonly go get github.com/AsynkronIT/protoactor-go/protobuf/protoc-gen-gograin
go get: upgraded github.com/AsynkronIT/protoactor-go v0.0.0-20200815184336-b225d28383f2 => v0.0.0-20210405044454-10bc19881ad6
# (...)
I've also tried finding similar issues, like this one, or this other one, but haven't yet find an alternative to prevent go get commands from altering the go.mod.
The current workaround I'm using to stop this behavior is to do a git checkout -- go.mod right after certain go get … steps to reset any changes done by go get, and hence, avoiding breaking changes with certain dependencies newer versions.
I'm using go version 1.16.3.
For Go 1.16 and after, you can use go install to install binaries without affecting go.mod
go install github.com/AsynkronIT/protoactor-go/protobuf/protoc-gen-gograin
I need a pre build project and I need a version of protoc-gen-go v1.25.0-devel but I am unable to find command etc to install It , till now I tried to do something like this :
go get -u google.golang.org/protobuf/cmd/protoc-gen-go#v1.25.0-devel
and I am getting this ERROR invalid version: unknown revision cmd/protoc-gen-go/v1.25.0-devel
Is there any way to get this version ?
If you're following this post to create a sample service, you don't need the specific version 1.25.0-devel that appears in the generated files. You should use the latest stable version (currently v1.26.0). Since it is an minor version upgrade, there should be no breaking changes between versions. One thing that you may need to make the examples in the post to work is that you should set the package for the generated code. You can set it in the .proto file as an option, for example option go_package = grpc-example/generated/protos/calc or as a command line argument for the protoc command, for example protoc ...OTHER_OPTS --go_opt=Mprotos/calc.proto=grpc-example/generated/protos/calc.
If you are sure that you absolutely need the specific version v1.25.0-devel you can install the plugin pointing to a specific commit (as that version is not currently available as a tag/branch name). If you're using go 1.16.x you can use go install google.golang.org/grpc/cmd/protoc-gen-go-grpc#a9513eb pointing at this commit. For older go versions, use go get
I'm starting the process of switching my applications to using go modules from currently not using any dependency manager. I want to use all of the same versions of the dependencies I currently use to avoid the risk of a different version of something causing unforeseen issues. Since I have a microservice architecture with a lot of applications I'm trying to figure out if there's a better way to do this than checking each application and its individual dependencies against what is currently in the build server's GOPATH.
Is there any way, even if just once when first initializing go mods, to have go modules default to the versions in the GOPATH.
If that's not possible (which I have a strong feeling it's not), is it possible to use go list or something similar to print the imported dependencies and the current git sha that exists in the GOPATH?
From the root of your project directory:
go mod init
To pull in build (and optionally test dependencies):
go build ./... # ... notation will scan any subdirectories for any nested packages/tools
go test ./... # optional
The above will pull the latest (semver) version of each dependency. This may NOT be the version you are using with a GOPATH build.
So to ensure you get the latest commit (which is what GOPATH builds use) - I'd go through each dependency in go.mod and issue a manual update to master. So for example lets say you had logrus as a dependency, to update to the latest commit:
go get github.com/sirupsen/logrus#master
If the latest semver matches the latest commit - no change will occur - but if not you will get a tag version plus commit style pseudo-version.
The Go wiki has other go-modules daily workflows e.g. fast-forward, a month/year from now, to pull the latest version of your dependencies into your go.mod (and go.sum):
go get -u ./...
but again be aware if a dependency does not use semver or has switched to a v2 breaking change - the above will not work.
The best practice is to eyeball the repo:
does it support go-modules (i.e. does it have a go.mod at the top level or at the import path level)
is the git repo tagged
and if the latest commit is tagged
only then can you be sure you are getting the version you expect.
coming from a Node environment I used to install a specific version of a vendor lib into the project folder (node_modules) by telling npm to install that version of that lib from the package.json or even directly from the console, like so:
$ npm install express#4.0.0
Then I used to import that version of that package in my project just with:
var express = require('express');
Now, I want to do the same thing with go. How can I do that?
Is it possible to install a specific version of a package? If so, using a centralized $GOPATH, how can I import one version instead of another?
I would do something like this:
$ go get github.com/wilk/uuid#0.0.1
$ go get github.com/wilk/uuid#0.0.2
But then, how can I make a difference during the import?
Go 1.11 will have a feature called go modules and you can simply add a dependency with a version. Follow these steps:
go mod init .
go mod edit -require github.com/wilk/uuid#0.0.1
go get -v -t ./...
go build
go install
Here's more info on that topic - https://github.com/golang/go/wiki/Modules
Really surprised nobody has mentioned gopkg.in.
gopkg.in is a service that provides a wrapper (redirect) that lets you express versions as repo urls, without actually creating repos. E.g. gopkg.in/yaml.v1 vs gopkg.in/yaml.v2, even though they both live at https://github.com/go-yaml/yaml
gopkg.in/yaml.v1 redirects to https://github.com/go-yaml/yaml/tree/v1
gopkg.in/yaml.v2 redirects to https://github.com/go-yaml/yaml/tree/v2
This isn't perfect if the author is not following proper versioning practices (by incrementing the version number when breaking backwards compatibility), but it does work with branches and tags.
A little cheat sheet on module queries.
To check all existing versions: e.g. go list -m -versions github.com/gorilla/mux
Specific version #v1.2.8
Specific commit #c783230
Specific branch #master
Version prefix #v2
Comparison #>=2.1.5
Latest #latest
E.g. go get github.com/gorilla/mux#v1.7.4
You can use git checkout to get an specific version and build your program using this version.
Example:
export GOPATH=~/
go get github.com/whateveruser/whateverrepo
cd ~/src/github.com/whateveruser/whateverrepo
git tag -l
# supose tag v0.0.2 is correct version
git checkout tags/v0.0.2
go run whateverpackage/main.go
Glide is a really elegant package management for Go especially if you come from Node's npm or Rust's cargo.
It behaves closely to Godep's new vendor feature in 1.6 but is way more easier. Your dependencies and versions are "locked" inside your projectdir/vendor directory without relying on GOPATH.
Install with brew (OS X)
$ brew install glide
Init the glide.yaml file (akin to package.json). This also grabs the existing imported packages in your project from GOPATH and copy then to the project's vendor/ directory.
$ glide init
Get new packages
$ glide get vcs/namespace/package
Update and lock the packages' versions. This creates glide.lock file in your project directory to lock the versions.
$ glide up
I tried glide and been happily using it for my current project.
Nowadays you can just use go get for it. You can fetch your dependency by the version tag, branch or even the commit.
go get github.com/someone/some_module#master
go get github.com/someone/some_module#v1.1.0
go get github.com/someone/some_module#commit_hash
more details here - How to point Go module dependency in go.mod to a latest commit in a repo?
Go get will also install the binary, like it says in the documentation -
Get downloads the packages named by the import paths, along with their dependencies. It then installs the named packages, like 'go install'.
(from https://golang.org/cmd/go/)
Update 18-11-23: From Go 1.11 mod is official experiment. Please see #krish answer.
Update 19-01-01: From Go 1.12 mod is still official experiment.
Starting in Go 1.13, module mode will be the default for all development.
Update 19-10-17: From Go 1.13 mod is official package manager.
https://blog.golang.org/using-go-modules
Old answer:
You can set version by offical dep
dep ensure --add github.com/gorilla/websocket#1.2.0
From Go 1.5 there's the "vendor experiment" that helps you manage dependencies. As of Go 1.6 this is no longer an experiment. Theres also some other options on the Go wiki..
Edit: as mentioned in this answer gopkg.in is a good option for pinning github-depdencies pre-1.5.
dep is the official experiment for dependency management for Go language. It requires Go 1.8 or newer to compile.
To start managing dependencies using dep, run the following command from your project's root directory:
dep init
After execution two files will be generated: Gopkg.toml ("manifest"), Gopkg.lock and necessary packages will be downloaded into vendor directory.
Let's assume that you have the project which uses github.com/gorilla/websocket package. dep will generate following files:
Gopkg.toml
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/gorilla/websocket"
version = "1.2.0"
Gopkg.lock
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/gorilla/websocket"
packages = ["."]
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "941e8dbe52e16e8a7dff4068b7ba53ae69a5748b29fbf2bcb5df3a063ac52261"
solver-name = "gps-cdcl"
solver-version = 1
There are commands which help you to update/delete/etc packages, please find more info on official github repo of dep (dependency management tool for Go).
go get is the Go package manager. It works in a completely decentralized way and how package discovery still possible without a central package hosting repository.
Besides locating and downloading packages, the other big role of a package manager is handling multiple versions of the same package. Go takes the most minimal and pragmatic approach of any package manager. There is no such thing as multiple versions of a Go package.
go get always pulls from the HEAD of the default branch in the repository. Always. This has two important implications:
As a package author, you must adhere to the stable HEAD philosophy. Your default branch must always be the stable, released version of your package. You must do work in feature branches and only merge when ready to release.
New major versions of your package must have their own repository. Put simply, each major version of your package (following semantic versioning) would have its own repository and thus its own import path.
e.g. github.com/jpoehls/gophermail-v1 and github.com/jpoehls/gophermail-v2.
As someone building an application in Go, the above philosophy really doesn't have a downside. Every import path is a stable API. There are no version numbers to worry about. Awesome!
For more details : http://zduck.com/2014/go-and-package-versioning/
The approach I've found workable is git's submodule system. Using that you can submodule in a given version of the code and upgrading/downgrading is explicit and recorded - never haphazard.
The folder structure I've taken with this is:
+ myproject
++ src
+++ myproject
+++ github.com
++++ submoduled_project of some kind.
That worked for me
GO111MODULE=on go get -u github.com/segmentio/aws-okta#v0.22.1
There's a go edit -replace command to append a specific commit (even from another forked repository) on top of the current version of a package.
What's cool about this option, is that you don't need to know the exact pseudo version beforehand, just the commit hash id.
For example, I'm using the stable version of package "github.com/onsi/ginkgo v1.8.0".
Now I want - without modifying this line of required package in go.mod - to append a patch from my fork, on top of the ginkgo version:
$ GO111MODULE="on" go mod edit -replace=github.com/onsi/ginkgo=github.com/manosnoam/ginkgo#d6423c2
After the first time you build or test your module, GO will try to pull the new version, and then generate the "replace" line with the correct pseudo version. For example in my case, it will add on the bottom of go.mod:
replace github.com/onsi/ginkgo => github.com/manosnoam/ginkgo v0.0.0-20190902135631-1995eead7451
It might be useful.
Just type this into your command prompt while cd your/package/src/
go get github.com/go-gl/mathgl#v1.0.0
You get specific revision of package in question right into your source code, ready to use in import statement.
The current way to do this is to use go install
https://golang.org/doc/go-get-install-deprecation
Starting in Go 1.17, installing executables with go get is deprecated. go install may be used instead.
go install github.com/someone/some_module
Specific version
go install github.com/someone/some_module#v1.1.0
Specific commit
go install github.com/someone/some_module#commit_hash