Search code examples
gogo-modules

Installing All Go Mod Dependency Binaries


I'm using go1.16.3 with this tools file to consolidate dependencies:

// +build tools

package main

import (
    _ "github.com/swaggo/swag/cmd/swag"
    _ "honnef.co/go/tools/cmd/staticcheck"
)

Running go get in the project dir downloads and installs the packages to $GOPATH/pkg/mod but doesn't install their binaries to $GOPATH/bin. Running go get individually for each mod (i.e. go get github.com/swaggo/swag/cmd/swag) does install both packages and binaries.

Is there a way I can install the binaries for all mods with a single command?

If not, what's the right way to automatically install all packages and binaries for all dependencies?


Solution

  • There's not really a good way to do this in a single command. Your best bet might be a script that chains a go list command to list all the imports from tools.go into a go install command:

    tools=$(go list -f '{{range .Imports}}{{.}} {{end}}' tools.go)
    go install $tools
    

    To explain the above, go list queries packages and modules. By default, it just prints package names, but its output can be controlled with -f or -json. go help list shows everything go list can print. The syntax for -f is the same as text/template.

    So here, go list tools.go queries a package which is a list of .go files, in this case, just tools.go. .Imports is a sorted, deduplicated list of imports from that package. We could just use the template {{.Imports}}, but it prints brackets at the beginning and end.

    $ go list -f '{{.Imports}}' tools.go
    [github.com/swaggo/swag/cmd/swag honnef.co/go/tools/cmd/staticcheck]
    

    So instead, we range over .Imports, and inside the range, we print each import ({{.}}) followed by a space.