Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Go  Module 1 – Getting started with Go 1.27

Install Go 1.27 and set up your editor

Install Go 1.27 on Windows, macOS or Linux, check it with go version, set up VS Code or GoLand, and see what GOPATH, GOBIN and GOPROXY hold.

  • Beginner
  • 15 minutes
  • Examples run with Go 1.27.1 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 15 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Install Go 1.27 on Windows, macOS or Linux and verify it with go version
  • Explain what GOROOT, GOPATH, GOBIN, GOMODCACHE, GOCACHE and GOPROXY hold
  • Change a go env setting for one command and for good, and undo the change
  • Configure VS Code or GoLand to work with your Go installation
  • Fix an older Go first on PATH and a stale GOROOT

Before you start

What you’ll learn · Before you start

What you will learn

  • Install Go 1.27 on Windows, macOS or Linux and verify it with go version
  • Explain what GOROOT, GOPATH, GOBIN, GOMODCACHE, GOCACHE and GOPROXY hold
  • Change a go env setting for one command and for good, and undo the change
  • Configure VS Code or GoLand to work with your Go installation
  • Fix an older Go first on PATH and a stale GOROOT

Before you start

On this page

Installing Go takes one download of 60 to 70 MB from go.dev, and it is finished when one command, go version, prints the release you installed. Most trouble comes later, from a second Go installation or a setting left behind by an old one, so this lesson does more than install: it shows where Go keeps everything and reproduces the two problems that break builds after an upgrade.

You will install Go 1.27 on Windows, macOS or Linux, read the folders Go uses with go env, change a setting and undo it, connect an editor through gopls, choose what telemetry may do, and fix an older Go that comes first on PATH and a stale GOROOT.

One download puts the whole toolchain in one folder

The downloads page, go.dev/dl, offers one file per system: an installer for macOS (.pkg) and Windows (.msi), and an archive (.tar.gz) for Linux, each for amd64 or arm64 processors. Take the newest minor release of 1.27, such as 1.27.2, because minor releases carry the security fixes. The examples on this track show what Go 1.27.1 printed.

  • macOS. Open the package and follow the prompts. It installs Go into /usr/local/go and puts /usr/local/go/bin on your PATH by creating the file /etc/paths.d/go. Go 1.27 needs macOS 13 Ventura or later.
  • Windows. Open the MSI file and follow the prompts. By default it installs into Program Files. Close every open command prompt and open a new one, so the changes the installer made to the environment take effect.
  • Linux. Extract the archive into /usr/local, after removing any older tree. Step through the official commands:
Interactive · stage by stage Installing Go 1.27 from the Linux archive Step through the official instructions, from the download to the first go version that prints the new release.
Installing Go 1.27 from the Linux archive, step 6 of 6. Showing Download the archive, Remove the old tree, Extract a fresh tree, Put Go on PATH, Open a new shell, Check it (prints the new release). In focus: Check it.Download the archivefrom go.dev/dlRemove the old treerm -rf /usr/local/goExtract a fresh treeinto /usr/localPut Go on PATH/usr/local/go/binOpen a new shellthe profile is read againCheck itprints the new release

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. Download. On go.dev/dl, pick the archive for Linux and your processor, amd64 for most servers and laptops, arm64 for Arm machines, and take the newest 1.27 minor release, because minor releases carry the security fixes.
  2. Remove the old tree. Delete any earlier installation with rm -rf /usr/local/go, as root or with sudo. The instructions warn that extracting over an existing /usr/local/go tree is known to produce a broken installation.
  3. Extract. tar -C /usr/local -xzf with the archive's file name creates a fresh /usr/local/go. That one folder is the whole toolchain, the go command, the compiler and the standard library, and it becomes GOROOT.
  4. PATH. Add the line export PATH=$PATH:/usr/local/go/bin to $HOME/.profile, or to /etc/profile for every user, so a shell can find the go command.
  5. New shell. A change to a profile applies to shells started after it. Log in again, or run source $HOME/.profile in the shell you have.
  6. Check. go version must print the release you installed, for example go1.27.2 linux/amd64. An older version here means another go comes first on PATH, the problem the last section of this lesson reproduces.

Extracting over an old installation

tar -C /usr/local -xzf go1.27.2.linux-amd64.tar.gz on top of an existing /usr/local/go mixes the files of two releases, and the install instructions warn that this is known to give a broken installation. Run rm -rf /usr/local/go first, then extract into an empty place.

On every system the check is the same, and it should be the first thing you run in a new terminal:

The first check after any install Python · check_session.py
from session import run

# The first check after any install: which Go runs, for which system.
run("""
go version
go env GOVERSION GOOS GOARCH
""")

Output

$ go version
go version go1.27.1 darwin/arm64
$ go env GOVERSION GOOS GOARCH
go1.27.1
darwin
arm64

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 check_session.py

go version names the release and the system it was built for, here go1.27.1 on darwin/arm64, a Mac with Apple silicon. go env prints any of the go command’s settings by name: GOVERSION is the release again, and GOOS and GOARCH are the operating system and processor that go build targets unless you say otherwise.

Checkpoint

Check: Installing Go and checking it

  1. Question 1 of 2 On Linux, Go 1.26 is installed in /usr/local/go. You extract the 1.27.2 archive into /usr/local without removing anything first. What do the install instructions say about this?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: It mixes the files of two releases, which is known to give a broken installation

    The Linux instructions say to remove any previous /usr/local/go before extracting, and warn that extracting into an existing tree is known to produce broken Go installations.

  2. Question 2 of 2 Which command shows, on every system, that an installation worked?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: go version, run in a new terminal

    Every set of instructions ends with go version. If it prints an older release or nothing at all, the problem is PATH: the new installation is not the first go the shell finds.

go env shows where Go keeps everything

The installation folder is GOROOT: The folder of a Go installation, which holds the go command, the compiler and the standard library. The go command finds it from its own location, so it rarely needs setting by hand.: /usr/local/go after the official macOS and Linux installs. It holds the go command, the compiler and the standard library, and the go command works it out from its own location, so you never need to set it. Everything else Go writes lives in folders that go env reports:

Where Go keeps commands, modules and its cache Python · env_session.py
from session import run

# Where this Go keeps installed commands, downloaded modules and its build cache,
# and the settings it uses to download modules.
run("""
go env GOPATH GOBIN GOMODCACHE GOCACHE
go env GOPROXY GOSUMDB GOTOOLCHAIN
""")

Output

$ go env GOPATH GOBIN GOMODCACHE GOCACHE
~/go
~/go/bin
~/go/pkg/mod
~/Library/Caches/go-build
$ go env GOPROXY GOSUMDB GOTOOLCHAIN
https://proxy.golang.org,direct
sum.golang.org
auto

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 env_session.py

  • GOPATH: A folder, by default go in your home folder, under which the go command keeps downloaded modules (pkg/mod) and the commands go install builds (bin), unless GOMODCACHE or GOBIN name other folders. is ~/go, a folder named go in your home folder, unless you set it. With modules it no longer says where your code lives; it is the parent of two folders the go command fills.
  • GOBIN, ~/go/bin, is where go install writes the commands it builds. Add it to PATH, as the install instructions say, with export PATH="$PATH:$(go env GOPATH)/bin" in your shell profile on macOS or Linux. Go 1.27.1 prints the folder it will use even when GOBIN is not set.
  • GOMODCACHE, ~/go/pkg/mod, is the module cache: The folder named by GOMODCACHE where the go command keeps every module version it has downloaded, so each version is downloaded once and shared by all your projects.: every module version the go command has downloaded, shared by all your projects.
  • GOCACHE is the build cache: The folder named by GOCACHE where the go command keeps compiled packages and the programs go run built, so a later build reuses that work instead of compiling again. of compiled packages, in your user cache folder: ~/Library/Caches/go-build on macOS, ~/.cache/go-build on Linux and %LocalAppData%\go-build on Windows.
  • GOPROXY and GOSUMDB say where modules come from and how they are checked: the module proxy: A server that hands out module versions to the go command. GOPROXY lists the proxies to ask, in order; the default asks proxy.golang.org first and then the module's own source (direct). proxy.golang.org, then the module’s own repository (direct), with every download checked against the checksum database sum.golang.org. GOTOOLCHAIN auto lets a module’s go line fetch a newer Go when it needs one.

Step through one go install and watch which of these settings decides each part of it:

Interactive · message by message What one go install touches Step through go install golang.org/x/tools/gopls@latest and watch which setting decides each step.
What one go install touches, step 6 of 6. Messages so far: The go command to Proxy and sum database: newest gopls?; Proxy and sum database to The go command: module files; The go command to Your Go folders: save the modules; The go command to Your Go folders: compiled packages; The go command to Your Go folders: the gopls program.The go commandgo install gopls@latestProxy and sum databaseGOPROXY and GOSUMDBYour Go foldersGOBIN: ~/go/bin/goplsnewest gopls?module filessave the modulescompiled packagesthe gopls program

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. The command. The @latest suffix asks for the newest version of the gopls program. With a version suffix, go install builds outside any module of yours and ignores the go.mod of the folder you are in.
  2. Ask the proxy. GOPROXY says where to ask. By default that is proxy.golang.org, and then the module's own repository (direct) when the proxy answers that it has no copy.
  3. Download and check. The proxy sends the module and the modules it needs. Every download is checked against the checksum database that GOSUMDB names, sum.golang.org, so a changed copy is noticed.
  4. The module cache. The modules go into the module cache, GOMODCACHE, by default ~/go/pkg/mod. Every project on the computer shares it, so each version is downloaded once.
  5. Compile. The go command compiles gopls with the compiler and standard library of GOROOT and keeps each compiled package in the build cache, GOCACHE, so the next build of the same code is fast.
  6. The program. The finished program is written to GOBIN, by default ~/go/bin. Add that folder to PATH, as the install instructions say, and gopls runs from any terminal.

Checkpoint

Check: The folders go env reports

  1. Question 1 of 2 Where does the go command keep the module versions it downloads, unless you change it?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: In ~/go/pkg/mod, the module cache that GOMODCACHE names

    Downloaded modules go to GOMODCACHE, by default GOPATH/pkg/mod, which is ~/go/pkg/mod when GOPATH is not set. Every project on the computer shares it.

  2. Question 2 of 2 go install golang.org/x/tools/gopls@latest succeeded, yet typing gopls gives "command not found". What is the likeliest fix?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Add GOBIN, ~/go/bin by default, to PATH

    The install instructions add $(go env GOPATH)/bin to PATH for exactly this reason. After that, every command go install builds runs from any terminal.

A setting comes from the environment, your go env file or the installation

You will sometimes need to change one of these settings, for one command or for good. The session changes GOPROXY in both ways and then undoes the change:

A setting changed, overridden and undone Python · settings_session.py
from session import run

# Change a setting with go env -w, override it for one command, then undo it.
run("""
go env GOPROXY
go env -w GOPROXY=direct
go env GOPROXY
go env -changed
GOPROXY=off go env GOPROXY
go env -u GOPROXY
go env GOPROXY
""")

Output

$ go env GOPROXY
https://proxy.golang.org,direct
$ go env -w GOPROXY=direct
$ go env GOPROXY
direct
$ go env -changed
GOPROXY='direct'
$ GOPROXY=off go env GOPROXY
off
$ go env -u GOPROXY
$ go env GOPROXY
https://proxy.golang.org,direct

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 settings_session.py

go env -w GOPROXY=direct changed the setting for every later command, and go env -changed listed it. Writing GOPROXY=off in front of one command changed it for that command alone, and go env -u GOPROXY removed the saved value, so the default came back. Those three places, and a fourth, are read in a fixed order:

Interactive · stage by stage Where go env finds a value Step through the four places, in the order the go command reads them. The first one with a value wins.
Where go env finds a value, step 5 of 5. Showing An environment variable, Your go env file, The install's go.env, The built-in default. In focus: An environment variable, Your go env file.An environment variablesuch as GOPROXY=off go …Your go env filewritten by go env -wThe install's go.envin the GOROOT folderThe built-in defaultwhen none has a value

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. The environment. The go command looks at its environment first. GOPROXY=off in front of a command, as in the session, wins over everything else, for that one command only.
  2. Your go env file. Without an environment variable, it reads your go env file. go env -w writes a value there, go env -u removes it, and go env GOENV prints where the file is, in your user configuration folder.
  3. The installation. Without a value there either, the go.env file of the installation decides. In a standard Go it sets GOPROXY to proxy.golang.org then direct, GOSUMDB to sum.golang.org and GOTOOLCHAIN to auto.
  4. The default. Last come the defaults built into the go command, such as GOPATH, a folder named go in your home folder.
  5. What changed. go env -changed lists the settings whose value differs from the default, from your go env file or the environment. That is how the session showed GOPROXY='direct' after go env -w.

The order explains a common surprise: a value saved with go env -w seems to be ignored, because an environment variable of the same name, set in a shell profile long ago, wins over it. go env -changed lists the settings that differ from the defaults, whether they come from the environment or from your go env file, which makes it the first command to run when Go behaves differently on two machines.

Key idea

The environment beats your go env file, which beats the installation’s go.env, which beats the built-in default; the first place with a value wins.

Checkpoint

Check: Where a setting comes from

  1. Question 1 of 2 You want GOPROXY=direct for one go command only, and every other command as before. What do you do?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Write GOPROXY=direct in front of that one command

    The session did exactly this: GOPROXY=off go env GOPROXY printed off, and the next command was back to the saved or default value.

  2. Question 2 of 2 Your go env file says GOPROXY=direct, but go env GOPROXY prints off. What explains it?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: An environment variable GOPROXY=off is set, and the environment wins over your go env file

    The order is the environment, your go env file, the installation's go.env, then the built-in default. Look for the variable with echo $GOPROXY and in your shell profiles.

Your editor talks to gopls, the Go language server

Most of what makes an editor good at Go comes from gopls: Go's official language server, pronounced "Go please". Editors send it your code and get back completions, errors as you type, formatting, renames and the other features of a Go editor., the official language server of the Go team. Editors talk to it through the Language Server Protocol, a standard that many editors support, so the same completions, errors and refactorings appear in VS Code, Vim and Neovim, Emacs, Helix, Zed or Sublime Text. Step through one file being opened, edited and saved:

Interactive · message by message Your editor and gopls, one file at a time Step through opening, typing in and saving a Go file, and see which part does what.
Your editor and gopls, one file at a time, step 7 of 7. Messages so far: You to Your editor: open main.go; Your editor to gopls: the file's text; gopls to Your editor: errors and warnings; Your editor to gopls: what can follow fmt.?; gopls to Your editor: Println, Printf, …; Your editor to gopls: format and imports; gopls to Your editor: edits to apply.YouYour editorVS Code or anothergoplsthe Go language serveropen main.gothe file's texterrors and warningswhat can follow fmt.?Println, Printf, …format and importsedits to apply

The drawing shows the whole scene; its 7 steps are listed below.

Every step as text
  1. Open a file. You open main.go. The editor starts gopls if it is not running yet, and sends it the file over the Language Server Protocol, the standard way editors talk to language servers.
  2. The text goes over. Every change you make is sent on to gopls, so it always holds the text you see, saved or not.
  3. Diagnostics. gopls type-checks the package and answers with diagnostics, the compile errors and the findings of its static analyzers. The editor underlines them while you type, before you build anything.
  4. Completion. You type fmt and a dot. The editor asks gopls what can follow, and gopls answers from the types it has checked, the exported names of package fmt.
  5. Suggestions. The list arrives, Println, Printf, Sprintf and the rest, each with its signature and documentation.
  6. Save. You save. An editor set to format on save asks gopls for formatting and for organized imports, which adds the imports the code needs and removes the ones it does not use.
  7. Edits back. gopls answers with edits, not a new file. The editor applies them, so the file is laid out in Go's standard format and its import list is right.

In the 2025 Go Developer Survey, most respondents preferred VS Code (37 %) or GoLand (28 %); Zed and Cursor were each the preferred editor of 4 %. How you set up the two leading ones:

  • VS Code. Install the Go extension (its identifier is golang.go), then open any .go or go.mod file to activate it. The extension depends on go and gopls, and if gopls is missing it tries to install it; the command Go: Install/Update Tools installs and updates the other tools it uses. A ⚡ sign next to the Go version in the status bar says the language server is running. The extension needs Go 1.21 or newer and officially supports the two most recent major releases.
  • GoLand. JetBrains’ IDE for Go usually sets GOROOT by itself, and it can also download a Go SDK for you: open Settings, then Go | GOROOT.

Another editor needs an LSP plugin and gopls itself, installed with go install golang.org/x/tools/gopls@latest; the program lands in GOBIN, as the scene in the go env section showed. gopls follows the Go release policy: it supports the go command of the two most recent major releases, so keep Go up to date along with it.

Checkpoint

Check: Editors and gopls

  1. One question In VS Code, Go files open but show no completions and no errors as you type, and there is no ⚡ next to the Go version in the status bar. What is the likeliest cause?

    Choose one answer.

    Show the answer: One question

    Answer: gopls, the language server, is not running

    The Go extension depends on gopls and tries to install it when it is missing. Go: Install/Update Tools installs it by hand.

Telemetry stays on your computer unless you switch uploading on

Since Go 1.23 the toolchain keeps telemetry counters, small counts of named events in its own programs, and the go telemetry command decides what happens to them:

The telemetry mode, and how to change it Python · telemetry_session.py
from session import run

# The telemetry mode: local is the default; off stops even local counting.
run("""
go telemetry
go telemetry off
go telemetry
go telemetry local
go env GOTELEMETRY
""")

Output

$ go telemetry
local
$ go telemetry off
$ go telemetry
off
$ go telemetry local
$ go env GOTELEMETRY
local

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 telemetry_session.py

Mode Counters kept on your computer Uploaded to the Go team
local, the default Yes Never
on Yes Possibly, depending on sampling, and only the counters the upload configuration lists
off No No

The counters are kept in your user configuration folder, under go/telemetry, and go env GOTELEMETRYDIR prints where. The Go telemetry documentation says that even the counters that record a call stack hold only the names and line numbers of functions in the toolchain’s own programs, never the names or contents of your source code. Turning uploading on is your choice: go telemetry on does it, and so does answering yes to the prompt gopls may show in VS Code. go telemetry off stops even the local counting, and go telemetry local returns to the default, as the session did.

Checkpoint

Check: The telemetry modes

  1. One question What does Go's default telemetry mode do?

    Choose one answer.

    Show the answer: One question

    Answer: It keeps counters on your computer and never uploads them

    local collects counters and stores them on your computer, on may upload some of them, and off neither collects nor uploads.

Two Go installations in each other’s way

Many problems after an upgrade come from two installations meeting. The session reproduces four of them on one computer, which has Go 1.27.1 and also an older Go 1.26.8:

hello.go: a program to test the installation Go · hello.go
// hello.go: a one-line program to test that a Go installation can build.
package main

import "fmt"

func main() {
	fmt.Println("built with a working GOROOT")
}
Two Go installations in each other's way Python · two_installs_session.py
from session import run

# Four ways two Go installations get in each other's way, then the build that works.
run(
    """
# 1. An older Go comes first on PATH ($OLD_GO_BIN holds Go 1.26.8):
PATH="$OLD_GO_BIN:$PATH" go version
# 2. GOROOT, set by hand, still names the older release's folder:
GOROOT="$OLD_GOROOT" go build -o hello hello.go 2>&1 | grep -m 1 "does not match"
GOROOT="$OLD_GOROOT" go env -changed
# 3. GOROOT names a folder that no longer exists:
GOROOT="$HOME/sdk/go1.20" go version
# 4. Go 1.27.1 refuses to save GOROOT, Go 1.26.8 still saves it, and Go 1.27.1 reads it:
go env -w GOROOT="$OLD_GOROOT"
"$OLD_GO_BIN/go" env -w GOROOT="$OLD_GOROOT"
go build -o hello hello.go 2>&1 | grep -m 1 "does not match"
go env -changed
go env -u GOROOT
go env GOENV
"$OLD_GO_BIN/go" env -u GOROOT
# With neither setting, the same build works:
go build -o hello hello.go && ./hello
""",
    expect_failure=[
        'GOROOT="$HOME/sdk/go1.20" go version',
        'go env -w GOROOT="$OLD_GOROOT"',
        "go env -u GOROOT",
    ],
)

Output

# 1. An older Go comes first on PATH ($OLD_GO_BIN holds Go 1.26.8):
$ PATH="$OLD_GO_BIN:$PATH" go version
go version go1.26.8 darwin/arm64
# 2. GOROOT, set by hand, still names the older release's folder:
$ GOROOT="$OLD_GOROOT" go build -o hello hello.go 2>&1 | grep -m 1 "does not match"
compile: version "go1.26.8" does not match go tool version "go1.27.1"
$ GOROOT="$OLD_GOROOT" go env -changed
# 3. GOROOT names a folder that no longer exists:
$ GOROOT="$HOME/sdk/go1.20" go version
go: cannot find GOROOT directory: ~/sdk/go1.20
[exit status 2]
# 4. Go 1.27.1 refuses to save GOROOT, Go 1.26.8 still saves it, and Go 1.27.1 reads it:
$ go env -w GOROOT="$OLD_GOROOT"
go: GOROOT cannot be modified
[exit status 1]
$ "$OLD_GO_BIN/go" env -w GOROOT="$OLD_GOROOT"
$ go build -o hello hello.go 2>&1 | grep -m 1 "does not match"
compile: version "go1.26.8" does not match go tool version "go1.27.1"
$ go env -changed
$ go env -u GOROOT
go: GOROOT cannot be modified
[exit status 1]
$ go env GOENV
~/Library/Application Support/go/env
$ "$OLD_GO_BIN/go" env -u GOROOT
# With neither setting, the same build works:
$ go build -o hello hello.go && ./hello
built with a working GOROOT

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 two_installs_session.py

The first go version printed go1.26.8, although 1.27.1 is installed, because the older Go’s folder came first on PATH. The second command failed with compile: version "go1.26.8" does not match go tool version "go1.27.1": GOROOT, set by hand, made the new go command run the old compiler, and go env -changed did not list it. The third failed before building anything, because GOROOT named a folder that no longer exists.

The fourth case is the one an upgrade leaves behind. Go 1.27.1 refused go env -w GOROOT=…, but Go 1.26.8 saved the same value in the go env file without a word, and from then on Go 1.27.1 read it there and failed with the same mismatch, while go env -changed printed nothing. It could not remove the line either: go env -u GOROOT gave GOROOT cannot be modified too, and only the older go command took it out again.

GOROOT and go env, since Go 1.27

Go 1.27 refuses go env -w and go env -u for GOROOT, while Go 1.26 accepted both. A GOROOT line that an older release saved still counts. When the older release is gone, open the file that go env GOENV names and delete that line yourself.

Step through how a typed go command reaches its compiler, and where each failure enters:

Interactive · stage by stage From typing go build to the compiler that runs Step through how the shell finds go, and how go finds its tools, then see where each failure of the session enters.
From typing go build to the compiler that runs, step 6 of 6. Showing You type go build, The shell searches PATH, The first go found runs (ran go1.27.1: the new one), It picks its GOROOT (its own folder), GOROOT's tools run (the build works). In focus: GOROOT's tools run.You type go buildin a terminalThe shell searches PATHfolder by folder, in orderThe first go found runsran go1.27.1: the new oneIt picks its GOROOTits own folderGOROOT's tools runthe build works

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. You type go. The shell has to turn the word go into a program file. It does not know about Go installations at all.
  2. PATH, in order. The shell tries each folder of PATH in order and stops at the first that holds a program named go. Two installations on PATH means the earlier folder always wins.
  3. An older go first. In the session, the folder of Go 1.26.8 came first, so go version printed go1.26.8 although Go 1.27.1 was installed too. The fix is to remove the old folder from PATH, or the old installation itself.
  4. GOROOT. Now take the newer go, Go 1.27.1, first on PATH. It takes GOROOT from the environment if the variable is set, then from your go env file, and otherwise from its own location, so left alone it finds the installation it belongs to.
  5. A GOROOT set by hand. In the session, GOROOT still named the Go 1.26.8 folder, first in the environment and then in the go env file. Go 1.27.1 then started the compiler of 1.26.8, which refused to work for it, and the build failed with a version mismatch.
  6. Leave it unset. With GOROOT unset and one Go on PATH, the go command finds its own tools, and the same build worked. A GOROOT naming a deleted folder fails even earlier, with cannot find GOROOT directory.

To find the cause on your own computer, list every go the shell can find with which -a go on macOS and Linux, or where go on Windows, and print the GOROOT variable with echo $GOROOT (echo %GOROOT% in the Windows command prompt). A stale value comes from the environment, through a shell profile, the Windows environment variables or an editor’s own setting, or from a GOROOT line in the go env file. go env -changed lists neither, so look in both places.

Setting GOROOT by hand

Exporting GOROOT in a shell profile looks harmless right after an install. A GOROOT written by hand is right only until the next upgrade, and then it makes the new go command run old tools. Remove the line, open a new terminal, and check go version and go env GOROOT again.

Once both are clean, the two answers agree: go version names the release of the go command that runs, and go env GOROOT names the folder it came from.

Key idea

Keep one Go on PATH and leave GOROOT unset: the go command then finds its own installation, and go version tells you which one runs.

Checkpoint

Check: Two installations in each other's way

  1. Question 1 of 2 You installed Go 1.27.2, but go version prints go1.26.8. Which command shows why?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: which -a go (where go on Windows), which lists every go on PATH, first one first

    With two installations on PATH, the earlier folder wins. Remove the old folder from PATH, or the old installation, and open a new terminal.

  2. Question 2 of 2 A build fails with: compile: version "go1.26.8" does not match go tool version "go1.27.1". What do you change?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Remove the stale GOROOT, from the environment or from your go env file, then open a new terminal

    Left unset, GOROOT is worked out from the go command's own location, so it always matches. The session showed the same build working once the stale GOROOT was gone.

Practise: check your own installation

Run these in a new terminal and compare each line with what this lesson showed:

  1. go version prints go1.27 followed by a minor release, and your system.
  2. which -a go (or where go on Windows) prints one line, the folder of that installation.
  3. go env GOROOT prints that installation’s folder, echo $GOROOT prints an empty line (on macOS and Linux), and the file that go env GOENV names, if there is one, has no GOROOT line.
  4. go env GOPATH GOBIN GOMODCACHE print folders under your home folder, and GOBIN is on your PATH.
  5. go env -changed prints only settings you changed on purpose.

Then answer the self-check on the six ideas of this lesson; it begins with the idea you are least sure of:

Practice that adapts to you

Practise this lesson

13 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 13 Where does the official macOS package install Go?

    Choose one answer.

    Show the answer: Question 1 of 13

    Answer: /usr/local/go, with /usr/local/go/bin put on PATH through /etc/paths.d/go

    The package installs the distribution into /usr/local/go and adds /usr/local/go/bin to PATH by creating /etc/paths.d/go. That folder is GOROOT.

  2. Question 2 of 13 Right after the Windows installer finishes, a command prompt that was already open says go is not recognized. What do you do first?

    Choose one answer.

    Show the answer: Question 2 of 13

    Answer: Close it and open a new command prompt

    The Windows instructions say to close and reopen any open command prompts, so the installer's changes to the environment are seen.

  3. Question 3 of 13 GOPATH is not set. What does go env GOPATH print?

    Choose one answer.

    Show the answer: Question 3 of 13

    Answer: A folder named go in your home folder, ~/go

    Most people never set GOPATH. Its default is the go folder in the home folder, and it is the parent of the module cache and of GOBIN.

  4. Question 4 of 13 Disk space is low, and you delete the build cache, GOCACHE, on a Mac. What is the effect on your next builds?

    Choose one answer.

    Show the answer: Question 4 of 13

    Answer: The next builds are slower while packages are compiled again, and nothing breaks

    The build cache keeps compiled packages for reuse. go help cache describes it, and go clean -cache deletes all of it; the next build fills it again.

  5. Question 5 of 13 Which command removes a value you saved with go env -w GOPROXY=direct?

    Choose one answer.

    Show the answer: Question 5 of 13

    Answer: go env -u GOPROXY

    go env -w writes to your go env file, and go env -u takes the value out of it again. go env GOENV prints the file's location.

  6. Question 6 of 13 Put the places the go command takes a setting from in order, from the one that wins to the one used last.

    Give each item its position, from 1 (first).

    Show the answer: Question 6 of 13

    Answer:

    1. An environment variable
    2. Your go env file, written by go env -w
    3. The installation's go.env file
    4. The default built into the go command

    The environment wins, then your go env file, then the installation's go.env, then the built-in default. The first place with a value decides.

  7. Question 7 of 13 What is gopls?

    Choose one answer.

    Show the answer: Question 7 of 13

    Answer: The Go team's language server, which gives editors completion, diagnostics, formatting and more

    gopls is the official language server for Go. Because it speaks a standard protocol, many editors share the same Go features.

  8. Question 8 of 13 A project's machine still runs Go 1.24, and gopls, up to date, behaves oddly there. What does gopls's support policy suggest?

    Choose one answer.

    Show the answer: Question 8 of 13

    Answer: Upgrade Go, because gopls supports only the go command of the two most recent major releases

    gopls follows the Go release policy: it supports the two most recent major releases of the go command on PATH. An older Go is outside that window.

  9. Question 9 of 13 Which command stops even the local telemetry counting?

    Choose one answer.

    Show the answer: Question 9 of 13

    Answer: go telemetry off

    go telemetry off, go telemetry local and go telemetry on choose the three modes; go env GOTELEMETRY prints the one in use, as the session did.

  10. Question 10 of 13 A colleague worries that Go telemetry sends their source code to the Go team. What is accurate?

    Choose one answer.

    Show the answer: Question 10 of 13

    Answer: The default mode uploads nothing, and the counters hold only facts about the toolchain's own programs

    In local mode the counters stay on your computer. The documentation says stack counters contain no user input, such as the names or contents of source files.

  11. Question 11 of 13 When should you set GOROOT by hand?

    Choose one answer.

    Show the answer: Question 11 of 13

    Answer: Almost never, because the go command finds its own installation

    The go command works GOROOT out from its own location. A GOROOT set by hand is the cause of the mismatch error the session reproduced.

  12. Question 12 of 13 After an upgrade to Go 1.27, builds fail with the version mismatch, but echo $GOROOT prints an empty line and no shell profile sets it. Where is the stale GOROOT, and how do you remove it?

    Choose one answer.

    Show the answer: Question 12 of 13

    Answer: In the go env file, saved by go env -w with an older Go; delete the GOROOT line from the file that go env GOENV names

    A GOROOT reaches the go command from the environment or from your go env file. When the environment is clean, look in the file: an older release may have written the line with go env -w, and only an older go command or an edit by hand takes it out again.

  13. Question 13 of 13 go version fails with "go: cannot find GOROOT directory:" followed by a folder name. What happened?

    Choose one answer.

    Show the answer: Question 13 of 13

    Answer: GOROOT is set to a folder that no longer exists

    A GOROOT left over from an old installation points at a folder that was removed. Unset it and open a new terminal.

Interview questions

Warm-up (fresher): What is GOPATH used for in a project that uses modules?

With modules, your code can live in any folder, so GOPATH no longer says where projects go. It is the default home of two things: the module cache in GOPATH/pkg/mod, where downloaded module versions are kept, and GOPATH/bin, where go install puts the commands it builds. GOMODCACHE and GOBIN can move each of them elsewhere. When GOPATH is not set, it is a folder named go in your home folder ($HOME/go on Unix, %USERPROFILE%\go on Windows), so most people never set it, and go env GOPATH prints the value in use. GOPATH also has an older role, GOPATH mode, the way projects from before modules are built, which the go command uses only when modules are turned off. A new project needs none of it.

Two longer interview questions of this module start from this lesson:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Fresher to mid

    After a Go upgrade, every build on a teammate's laptop fails with "compile: version "go1.26.8" does not match go tool version "go1.27.1"". What causes it, how do you confirm the cause, and how would you keep build machines from ever meeting it?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    Your company network blocks proxy.golang.org, and a new hire's go build cannot download any module. Which settings decide where modules come from and how they are checked, what would you change, and what does each choice risk?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • An installer (macOS, Windows) or a fresh archive in /usr/local (Linux) puts the whole toolchain in one folder, and go version in a new terminal must print the release you installed.
  • go env reports where Go keeps things: GOPATH (~/go), GOBIN (~/go/bin, which belongs on PATH), the module cache (~/go/pkg/mod) and the build cache, and where modules come from (GOPROXY, GOSUMDB).
  • A setting comes from the environment first, then your go env file (go env -w, go env -u), then the installation’s go.env, then the built-in default; go env -changed shows what differs.
  • Editors get completion, errors as you type, formatting and import fixes from gopls; VS Code’s Go extension installs it, and GoLand finds or downloads a Go SDK itself.
  • Telemetry is local by default: counters stay on your computer, go telemetry on lets a sample of them be uploaded, and go telemetry off stops counting.
  • An older Go first on PATH and a GOROOT set by hand, in the environment or in a go env file an older Go wrote, are the classic install problems; keep one Go on PATH and leave GOROOT unset.

Terms in this lesson

build cache
The folder named by GOCACHE where the go command keeps compiled packages and the programs go run built, so a later build reuses that work instead of compiling again.
GOPATH
A folder, by default go in your home folder, under which the go command keeps downloaded modules (pkg/mod) and the commands go install builds (bin), unless GOMODCACHE or GOBIN name other folders.
gopls
Go's official language server, pronounced "Go please". Editors send it your code and get back completions, errors as you type, formatting, renames and the other features of a Go editor.
GOROOT
The folder of a Go installation, which holds the go command, the compiler and the standard library. The go command finds it from its own location, so it rarely needs setting by hand.
module cache
The folder named by GOMODCACHE where the go command keeps every module version it has downloaded, so each version is downloaded once and shared by all your projects.
module proxy
A server that hands out module versions to the go command. GOPROXY lists the proxies to ask, in order; the default asks proxy.golang.org first and then the module's own source (direct).

References

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.