go
command configuration fileRuss Cox
Last Updated: March 1, 2019.
Discussion at golang.org/issue/30411
Setting environment variables for go
command configuration is too difficult and system-specific. We propose to add go env -w
, to set defaults more easily.
The go
command is configured by environment variables: see the output of go env
for a partial list, and go help environment
for a longer one. Although nearly all variables are optional, it is not uncommon to need to set one or another. The details of setting an environment variable's initial value differs by operating system and even by distribution or terminal program—for example, do you have to log out entirely, or just restart the shell window?—which can make this environment-based configuration quite difficult. (When setting $GOPATH
was required to get started with Go, doing so was a major stumbling block for new users.)
It would help all users to have a consistent, simple way to set the default value for these configuration variables.
We propose to store in the file os.UserConfigDir()
+”/go/env”
a list of key-value pairs giving the default settings for configuration variables used by the go
command. Environment variables, when set, override the settings in this file.
The go env <NAME> ...
command will continue to report the effective values of the named configuration variables, using the current environment, or else the go.env
file, or else a computed default.
A new option go env -w <NAME>=<VALUE> ...
will set one or more configuration variables in the go.env
file. The command will also print a warning if the current environment has $<NAME>
defined and it is not set to <VALUE>
. For example, a user who needs to set a default $GOPATH
could now use:
go env -w GOPATH=$HOME/mygopath
Another popular setting might be:
go env -w GOBIN=$HOME/bin
The command go env -u <NAME>...
will unset (delete, remove) entries in the environment file.
Most users will interact with the os.UserConfigDir()/go/env
file through the go env
and go env -w
command line syntax, so the exact stored file format should not matter too much. But for concreteness, the format is a sequence of lines of the form <NAME>=<VALUE>
, in which everything after the =
is a literal, uninterpreted value—no quoting, no dollar expansion, no multiline values. Blank lines, lines beginning with #
, and lines not containing =
, are ignored. If the file contains multiple lines beginning with <NAME>=
, only the first has any effect. Lines with empty values set the default value to the empty string, possibly overriding a non-empty default.
Only the go
command will consult the os.UserConfigDir()/go/env
file. The environment variables that control go
libraries at runtime—for example, GODEBUG
, GOMAXPROCS
, and GOTRACEBACK
—will not be read from go.env
and will be rejected by go env
command lines.
The go
command is already configured by environment variables, simple <KEY>=<VALUE>
pairs. An alternative would be to introduce a richer configuration file format, such as JSON, TOML, XML, or YAML, but then we would also need to define how these richer values can be overridden in certain contexts. Continuing to use plain <KEY>=<VALUE>
pairs aligns better with the existing environment-based approach and avoids increasing the potential complexity of any particular configuration.
The use of os.UserConfigDir()
(see golang.org/issue/29960) seems to be the established correct default for most systems. Traditionally we've stored things in $GOPATH
, but we want to allow this file to contain the default value for $GOPATH
. It may be necessary—albeit ironic—to add a GOENV
environment variable overriding the default location. Obviously, it would not be possible to set the default for GOENV
itself in the file.
There are no compatibility issues. It may be surprising in some use cases that an empty environment still uses the go.env
settings, but those contexts could avoid creating a go.env
in the first place, or (if we add it) set GOENV=off
.
Russ Cox plans to do the implementation in the go
command in Go 1.13.