Home / Alt manpages / go-gopath-get(1)

  • go-gopath-get(1)
  • User command
  • linux

Recovering the Legacy GOPATH Workflow Behind go get

An old script calling go get with GOPATH-style flags will fail outright on a modern Go toolchain. This guide shows you how to recognise that legacy form and test it safely before you touch a real workspace. The local reference is the Debian go-gopath-get(1) manual, dated 15 October 2021, which describes legacy behaviour, not the current module-aware command.

Allow about fifteen minutes. You need a shell and a Go installation. The examples use an isolated temporary GOPATH and a deliberately nonexistent import path, so they do not alter a project or download a real dependency. No command here needs sudo.

Checkpoint

If you are trying to add a dependency to a project containing go.mod, stop at step 2 and use the module-aware command described there. This guide is for maintaining an older GOPATH workspace or diagnosing an old script.

1. Identify the installed tool and reference version

Check both the executable and the Debian package. This matters because the manual page may document a different generation of Go than the binary found through your PATH:

$ go version
go version go1.26.1 linux/amd64
$ dpkg-query -W -f='${Package} ${Version}\n' golang-go
golang-go 2:1.22~2build1

Your output may differ. The reference machine reports Go 1.26.1 from the executable and Debian package version 2:1.22~2build1. Record the executable result when reproducing behaviour; package metadata alone does not prove which binary will run.

2. Decide whether this is really GOPATH mode

Modern Go normally uses modules. In module-aware mode, go get updates dependency requirements in go.mod and downloads source into the module cache. It is not the legacy install command. The current Go documentation recommends go install for installing an executable.

For a project, inspect the directory and its parents for go.mod before running anything that changes dependencies:

$ pwd
/path/to/project
$ find .. -name go.mod -print
../project/go.mod

If a relevant go.mod exists, do not force the old workflow. For a dependency, use a versioned module command such as:

$ go get example.com/[email protected]

That changes go.mod and possibly go.sum, so review the diff afterwards. To install a command without changing the current module, use:

$ go install example.com/example/cmd/[email protected]

3. Enter legacy mode explicitly for an old workspace

The manual describes legacy go get with GO111MODULE=off. In that mode, the import path is placed under the first entry in GOPATH, at GOPATH/src/<import-path>. Set a disposable GOPATH for a test rather than pointing at a valuable workspace:

$ testdir=$(mktemp -d /tmp/gopath-get-check.XXXXXX)
$ GOPATH="$testdir" GO111MODULE=off go env GOPATH GO111MODULE
/tmp/gopath-get-check.abc123
off

The random suffix is variable. A real legacy workspace would use a persistent directory, such as $HOME/go, but check the existing value before changing your shell environment. Multiple GOPATH entries are separated by colons on Linux, and the first one is where a newly checked-out package goes.

4. Understand what the old command would do

In the manual's contract, go get IMPORT_PATH downloads the named package and dependencies, then installs the named package in the manner of go install. Without -u, it may fetch a missing package but does not search the network for updates to an existing checkout.

Use -d for downloading without installation. Use -u when you intentionally want the named package and its dependencies updated. -t also downloads packages needed by the named package's tests. -v shows progress and diagnostic output. The old -fix option runs the fix tool before dependency resolution and building.

Safety boundary

-u changes source checkouts and can move a dependency to a newer revision. -f is only valid with -u and skips the source-control-origin check, useful for a local fork but weaker as a provenance check. Use it only when you have independently verified the checkout.

For a historical script, the least surprising download-only shape is:

$ GOPATH="/path/to/legacy-gopath" GO111MODULE=off go get -d -v example.com/old/project/package

Replace the import path with one the project actually uses. Do not use a URL, a local filesystem path or a package name copied from an unrelated module.

5. Test the installed command before trusting an old script

Go 1.22 and later no longer support go get outside a module in legacy GOPATH mode. On the reference machine, this probe is safe because the import path is not real:

$ GOPATH="$testdir" GO111MODULE=off go get -d -v example.com/definitely-not-a-real-package
go: -d flag is deprecated. -d=true is a no-op
go: modules disabled by GO111MODULE=off; see 'go help modules'
$ printf 'status: %s\n' "$?"
status: 1

The exact wording can change, but a non-zero status means this installed tool cannot perform the manual's legacy workflow. Do not keep adding flags or use sudo; neither repairs a removed mode. Find the old toolchain required by the project, or migrate the project to modules and update its script deliberately.

6. Verify the intended result and recover safely

Inspect a real legacy run before deleting anything:

$ find /path/to/legacy-gopath/src/example.com/old/project -maxdepth 2 -type f -print
$ git -C /path/to/project diff -- go.mod go.sum
$ go env GOPATH GOMOD GO111MODULE

If a real run produced an unwanted checkout, remove only that known package directory after checking its exact path and preserving local changes. A safer recovery is to restore the checkout from its own version-control remote or discard it through the project's normal process. Do not recursively delete the whole GOPATH: it may contain unrelated projects, binaries and caches.

There is no elevated-privilege step in this workflow. If a path is unreadable, fix its ownership or permissions through the host's normal administration process rather than routinely prefixing go get with sudo. A root-owned checkout often creates a second problem for the ordinary developer account.

Done means

  • You checked the executable version as well as package metadata.
  • You distinguished module-aware go get from the historic GOPATH command.
  • You used an isolated GOPATH for the compatibility probe.
  • You understand the legacy meanings of -d, -u, -t, -v, -fix and -f.
  • You tested whether the installed Go version still supports that workflow before changing a real workspace.
  • You can review any changed checkout or module file and recover without deleting the whole GOPATH.