Why are all dependency in go.mod indirect?

Issue

I initialise a go project by running:

go mod init firstgo_app

I confirmed the module was created:

cat go.mod
module firstgo_app

go 1.18

Then I installed a dependency on github.com/gin-gonic/gin by executing

get github.com/gin-gonic/gin

after which I viewed the content of go.mod and this time it looks like this:

cat go.mod
module firstgo_app

go 1.18

require (
    github.com/gin-contrib/sse v0.1.0 // indirect
    github.com/gin-gonic/gin v1.7.7 // indirect
    github.com/go-playground/locales v0.13.0 // indirect
    github.com/go-playground/universal-translator v0.17.0 // indirect
    github.com/go-playground/validator/v10 v10.4.1 // indirect
    github.com/golang/protobuf v1.3.3 // indirect
    github.com/json-iterator/go v1.1.9 // indirect
    github.com/leodido/go-urn v1.2.0 // indirect
    github.com/mattn/go-isatty v0.0.12 // indirect
    github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
    github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
    github.com/ugorji/go/codec v1.1.7 // indirect
    golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
    golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect
    gopkg.in/yaml.v2 v2.2.8 // indirect
)

What I do not get is the fact that all the dependency has been tagged as indirect. My understanding is that it is only transitive dependency that are tagged indirect but the dependency I directly depend upon should not be tagged as such. That is github.com/gin-gonic/gin v1.7.7 // indirect should not have the indirect tag since this is the dependency I specifically downloaded.

I thought this was the case because I am not directly using the dependency, so I recreated the module again but also created a main.go file where I explicitly depend on gonic/gin:

cat main.go
package main
import "github.com/gin-gonic/gin"
func main() {
        r := gin.Default()
        r.GET("/ping", func(c *gin.Context) {
                c.JSON(200, gin.H{
                        "message": "pong",
                })
        })
        r.Run() // listen and serve on 0.0.0.0:8080
}

When I try to build it fails with:

go build
main.go:2:8: no required module provides package github.com/gin-gonic/gin; to add it:
    go get github.com/gin-gonic/gin

but when I run go get github.com/gin-gonic/gin and then build, all the dependency in go.mod are still tagged indirect.

So what gives? What am I missing here? Or do I understand the indirect wrongly?

Solution

Your understanding is correct. The indirect comment indicates a dependency is not used directly by your module, only indirectly by other module dependencies.

When you first run go get github.com/gin-gonic/gin, the module will be downloaded, but since you don’t use it, it will still be marked indirect.

When you start using it, it will no longer be indirect, but go build does not update go mod automatically.

Run go mod tidy, and then it will not be marked indirect anymore.

$ go mod tidy
$ cat go.mod
module firstgo_app

go 1.18

require github.com/gin-gonic/gin v1.7.7

require (
        github.com/gin-contrib/sse v0.1.0 // indirect
        github.com/go-playground/locales v0.13.0 // indirect
        github.com/go-playground/universal-translator v0.17.0 // indirect
        github.com/go-playground/validator/v10 v10.4.1 // indirect
        github.com/golang/protobuf v1.3.3 // indirect
        github.com/json-iterator/go v1.1.9 // indirect
        github.com/leodido/go-urn v1.2.0 // indirect
        github.com/mattn/go-isatty v0.0.12 // indirect
        github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
        github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
        github.com/ugorji/go/codec v1.1.7 // indirect
        golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
        golang.org/x/sys v0.0.0-20200116001909-b77594299b42 // indirect
        gopkg.in/yaml.v2 v2.2.8 // indirect
)

This has been since Go 1.14:

go commands other than go mod tidy no longer edit the go.mod file if the changes are only cosmetic.

Answered By – icza

Answer Checked By – Clifford M. (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.