DEV Community

loading...

What on earth is Go Mod?

#go
Tunde Oladipupo
Open Source Community Advocate. All things Performance and Automation.
・4 min read

Go mod is the recommended way to manage packages and their dependencies in go. Go can look at your imported packages and add them to its go.mod for management. For example, in this project;

module knative.dev/client

require (
    contrib.go.opencensus.io/exporter/ocagent v0.6.0 // indirect
    contrib.go.opencensus.io/exporter/prometheus v0.1.0 // indirect
    contrib.go.opencensus.io/exporter/stackdriver v0.12.9 // indirect
    github.com/google/go-containerregistry v0.0.0-20200131185320-aec8da010de2 // indirect
...
    github.com/openzipkin/zipkin-go v0.2.2 // indirect
    github.com/pkg/errors v0.8.1
    github.com/robfig/cron v1.2.0 // indirect
...
    golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413
    gotest.tools v2.2.0+incompatible
...
    sigs.k8s.io/yaml v1.1.0
)

// Temporary pinning certain libraries. Please check periodically, whether these are still needed
// ----------------------------------------------------------------------------------------------

// Fix for `[` in help messages and shell completion code
// See https://github.com/spf13/cobra/pull/899
replace github.com/spf13/cobra => github.com/chmouel/cobra v0.0.0-20191021105835-a78788917390

go 1.13

The go.mod has the required modules for this module as well as their specific version. Talking about version, you can see we have different version as well as comment. Lets take a look;

  • Semvars

    github.com/pkg/errors v0.8.1
    

    This package is required but version v0.8.1 of it. If this module is updated in its remote git repo with the new version, go will not used it but v0.8.1 instead

  • Pseudo-versions

        knative.dev/eventing v0.12.1-0.20200206203632-b0a7d8a77cc7
    

    This is the same as semvar but with weird version generated by go in form of last_tag-date-commit_hash. This is done when you import a package without specifying the version to use. Go simply update with the last tagged version(v0.12.1 in the case of knative.dev/eventing), then calculate the time of last commit as well as hash of last commit in the git repo to generate its version tag to give us v0.12.1-0.20200206203632-b0a7d8a77cc7

replace

So you have an external dependency in your project that you want to make some local changes to or replace temporarily with another source for testing or specific purpose. How do you do that? You can use replace. This means instead of using the external dependency source, it will use the replacement instead.

replace github.com/spf13/cobra => github.com/chmouel/cobra v0.0.0-20191021105835-a78788917390

This will make go mod use github.com/chmouel/cobra anywhere github.com/spf13/cobra is used. You can do the same locally by pointing the replacement to local path.

incompatible

Let's talk incompatible. If a repo does not have go.mod and it has semver that is >= 2,it will tagged with the semver as well as incompatible to indicate this is not a go mod repo. For our case,

gotest.tools v2.2.0+incompatible

If you look at the tagged repo, you can see the repo is missing go.mod and its on >=2 tag.

go version directive

This simply answers the question of which golang version and features should I use? I will quote one of the authority on this for better explanation.

The basic guideline is fairly simple: a "go" directive 1.N means that the code in that module is permitted to use language features that existed in 1.N even if those features were removed in later releases of the language.

In other words, if the code compiles successfully at version 1.N, then it will continue to compile for all later versions of the language, even if it happens to use language features that were later removed.

To a first approximation, nobody should ever have to worry about the "go" directive. The only likely time you might need to set it manually is if you are copying some existing code to a new module, that code uses some obsolete language feature, and you don't have time to rewrite it. In that case you might want to set the "go" directive (using go mod edit -go) to the version used by the original module, thus permitting your new module to use the obsolete features. When writing new code you will presumably simply avoid the obsolete language features.

go sum

This go.sum is way for go to keep cryptographic hash of the modules version in go.mod. It keeps a cache copy of this hashes and verifies them during run. Make sure to check in the go.sum file.

golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

Discussion (0)