| # Proposal: `go` command configuration file |
| |
| Russ Cox |
| |
| Last Updated: March 1, 2019. |
| |
| [golang.org/design/30411-env](https://golang.org/design/30411-env) |
| |
| Discussion at [golang.org/issue/30411](https://golang.org/issue/30411) |
| |
| ## Abstract |
| |
| 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. |
| |
| ## Background |
| |
| 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. |
| |
| ## Proposal |
| |
| We propose to store in the file [`os.UserConfigDir()`](https://golang.org/issue/29960)`+”/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. |
| |
| ## Rationale |
| |
| 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](https://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. |
| |
| ## Compatibility |
| |
| 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`. |
| |
| ## Implementation |
| |
| Russ Cox plans to do the implementation in the `go` command in Go 1.13. |
| |