-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: cmd/go: add go env -w to set default env vars #30411
Comments
Change https://golang.org/cl/164817 mentions this issue: |
See https://golang.org/design/30411-env and golang/go#30411. Change-Id: I8f75958b1c75dea7420d7c90ad8b9d592ce03460 Reviewed-on: https://go-review.googlesource.com/c/164817 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
(The "laugh" emojis were for the original "mine all mine" content) Is there a reason why this has become relevant all of a sudden? I have seen a few junior developers have issues with environment variables, but I don't think the issue is severe enough to warrant adding the first per-user Go config file. |
Two comments about fine details:
May I suggest that later values override earlier? That’s how env vars work (see os/exec’s handling of duplicate env vars), and the implementation is clearer.
I’d suggest omitting the second half of this sentence. When I first read it, in part due to context, I thought it was an exception to the “first entries” sentence immediately preceding it. |
FWIW, yesterday I was struggling with a Windows gomote. I am unfamiliar with windows and had to search for how to set env vars. And then was frustrated every time my ssh connection dropped, because I had to re-set my env vars. This proposal would have made my life considerably more pleasant. |
@josharian, really duplicates should not happen, so this shouldn't matter at all, but it needs to be well-defined. The implementation of 'first wins' is quite clear: read the file until you get to the line you want, and stop. Yes, there's a clear implementation for 'last wins' too, but first seems like what most people would do when reading the file. |
@mvdan, like the proverbial boiling frog, this has been bothering me for quite a while. It's not just junior developers. I personally have a hard time setting default environment variables. We've made go work very well out of the box but at the same time it's not uncommon to need to change a default here or there, and it's honestly just too hard. In Go 1.13 we expect to set a default GOPROXY, and we want to make sure it's easy to modify that setting. But really GOPROXY is just the latest of many straws, and the camel's back is already broken. |
It’s not what I would do. :P I’ll take one more stab at this, and then let it drop. (I agree that either way it is not particularly critical.)
|
I agree with Josh that if the file should generally not have duplicates, it should follow the same logic as the The reason I was asking about the urgency of this change for 1.13 was because I presumed that Go could be used by new developers without setting any env vars. Windows is a good point, I have to admit I don't know how to set an env var, though I hope I won't need to. The timing makes a lot more sense given your point about GOPROXY. A way to summarize my concern with this proposal is that, right now, Go's behavior only changes via env vars and via PWD (modules). Adding a per-user config file adds another dimension to the problem, and I could imagine that resulting in confusion. Perhaps less confusion than setting env vars in a portable way, but still unfortunate. |
@josharian, go env -w will never write a file with duplicate values. If a variable appears multiple times on the command line, that can just be an error. |
I have a concern with
As discussed over on #29960, This likely has overlap with @josharian's point about duplicate values. The configuration files should probably be visited in "reverse" order so that values in configuration directories for the user override configuration directories from the system. |
@zombiezen, what problem are you trying to solve? It is true that every problem can be solved by more indirections, but every indirection also creates new complexity (and often new problems). The problem I am trying to solve—not having a simple, portable way to set defaults for environment-based configuration—is addressed by one indirection; adding more adds complexity without making the solution any better. In fact it arguably makes it worse, because it is hard to understand, and we'd probably then need The host operating system can define whatever complexity it wants. Go is not, nor is it beholden to, the host operating system. Go is Go. It can define a single location. It's not like some general system utility is going to be working on this file on our behalf. We have one GOCACHE, one GOBIN, one GOROOT, one GOTMPDIR, one GCCGOTOOLDIR. We do have multiple GOPATH, but that was arguably a mistake, and source code is quite different in kind from a few environment variables. Why do we need two or more places to store a list of environment variable settings? Again, what problem do you mean to solve by doing that? |
Agreed: I don't want us to add complexity unnecessarily. I see this proposal as really valuable for a reason you have not cited yet: the Here's the problem I'm trying to identify: My experience in the past has been that for sysadmins or OS packagers, it is frequently useful to configure default variables at the system level (as illustrative example, these would be located at I would not expect a
A personal anecdote: I use the |
For the specific case of |
For what it's worth, admins at a company can already set default environment variables across all developer workstations. It's true that user configs then do not override those variables, but it lets them reuse an existing mechanism instead of us having to provide a separate one. I think this proposal is worth doing with a single file. With the complexity of multiple files, it may not be. |
A Since there are three places a setting may come from it would be useful to have something like If As for first wins vs. last wins, I'm vaguely aware that there are a number of config formats for specifying environment variables. What do they with duplicates? If there's an existing convention, it should be followed. |
Over the last five releases we've gotten to a point that a Go developer need not set any environment variables to develop a Go program on their machine. I don't think there needs to be a new mechanism, independent of the existing mechanisms to set environment variables on various operating systems, for operations which are now optional. |
I echo the feelings of @davecheney here. If this is needed just for how to set |
I'm always a bit scared when we add a new feature doing things very similar to an existing one (I'm thinking of the system environment variables). It is one more layer of configuration that someone new to the language will probably have to apprehend or discover the hard way. Especially when there is subtilities such as (these are the first ones but others could appear):
I'm maybe just worried about the fact that it looks ( |
If a variable is set by both the environment and go/env which one wins? I presume the environment, otherwise any program that calls go changing the environment is now broken. There probably are quite a few bashrc out there with |
As @davecheney I cannot see the actual need for the proposal and would like to see more evidence that this is a real world problem. As @aarzilli I have a problem with the following command sequence.
The proposal must also decide whether it is the |
Rethinking it this looks more like changing the defaults. So following command sequence appears more logical. (I still have to see the need.)
|
If it would take N hours to design, discuss, implement, test, and document this feature, perhaps some subset of those N hours could instead be invested in a documentation-based approach with a mix of slightly dynamic help within the tool, coupled with something like a wiki for more details. For example, if you are on Windows, perhaps
https://golang.org/setting-env-vars could redirect to a Wiki page. Perhaps someone from the core Go team could carve out something like 2-4 hours to put together a skeleton first version of that Wiki page, and there could be a tiny-ish outreach effort to the broader community to get other people to help populate it a bit more. That usefulness of For myself, if I was accessing a Plan 9 machine, rather than needing to remember that |
If a wiki-based approach is pursued, some subset of the following could be briefly described for a given OS (either in the wiki itself, or via external reference):
For some or maybe most OSes, only a subset of those would make sense to mention for a given OS. For me personally, regardless of OS, I tend to favor approach 1 or 2 for a machine that is not "mine". For "my" machine, I still tend to favor 1 or 2 for project-based settings, but of course I also set some things persistently. Taking the @josharian use case again, if he could go to a wiki page that briefly outlined approach 1, 2, and 3 for Windows, he could probably skim then pick whichever approach made sense for him at the time, including so that he doesn't have to start from scratch every time he reconnects. (E.g., I am not a Windows expert, but according to my first google hit, apparently the If it is a wiki, it would probably be OK to reference external sources such as StackOverflow for more details or for anything more nuanced. The greatest variability might be on Linux, but someone using Linux also tends to know how to sent env variables more frequently than, say, a randomly selected Windows user. In any event, perhaps |
Read in this context, i.e. "we need a reliable cross-platform one-liner that allows users to set a user-default value," I'm a big 👍 on this. Imagine for one second a brand new, amazing modules proxy is announced, released etc: the usage instructions would be simple for all users on all systems. Not "please got to this wiki page and follow the hard-to-follow instructions on what to do on your OS, for your shell, etc, make sure you reload Terminal on Mac OS X etc". This is not newcomer-friendly. Indeed I think the proposal could usefully be rewritten with A couple of other thoughts:
|
I think this is a very good idea. Environment variables make sense in certain situations and I'm glad they're not going away, but I've found them to sometimes be a source of trouble as well. I've had experiences where certain programs that run an executable on my behalf do so in an environment other than the one I configured. I think people (including myself) set environment variables in their I agree with @myitcv though that the killer feature here is easy cross-platform configuration.
I'm torn on this. Environment variables do well in situations where you're setting up a specific environment with a clear and small scope. For project-wide configuration, the scope becomes larger and things become less clear. An editor, the user's terminal, and any relevant scripts will all have to know about this project-specific configuration information. Where should users put it? I'm hesitant to recommend tools like |
@myitcv related to your comment at #30411 (comment), we haven't had much trouble with providing good docs on how to set Overall, I generally agree with @davecheney's comment that we don't need a new mechanism to set environment variables, with one small but important modification, that it would be a good idea to override a go-related environment variable in a file that is at the to level of a Go module. This was discussed in the context of a specific use case in #25530 (comment) (under "the light proposal") |
To my mind there is likely a significant difference in terms of experience/comfort with these sorts of things between your typical newcomer to Go and someone who is in the process of setting up Athens. On that basis I think the point still stands: we're comparing a single command that will work for 99.9% of users with a link to a page that documents what steps to follow. It feels like a no-brainer to add
I totally get the use case for this, but I don't think it's worth it. There are existing mechanisms for having environment be driven by directory that are not specific to go: |
Why not add |
The obvious downside is it adds a layer of precedence. But maybe this could be avoided by some type of |
Agreeing with @josharian, I like "last wins", just like in a shell script. Agreeing with @zombiezen, I like the extension to at least two levels for all-users and this-user, but perhaps that can happen later. Note that supporting a system-level file will push the issue of environment-variable expansion on the RHS, then quoting, etc -- which if you are really committed to the idea of It would be nice if "go help env" or "go env -help" also printed the location of the file(s), and I don't mind hints about how to set environment variables on whatever screwy platform I happen to need help on. |
Per https://stackoverflow.com/a/2821183/329700, environment variables cannot contain the equals sign character or a null byte but as far as I can tell, the spec does not define the behavior in either of those cases.
I'm used to using e.g. |
Is the |
@go101 No. This is intended to be only used by the |
Change https://golang.org/cl/171137 mentions this issue: |
It is unclear to me from (skimming) the design doc whether the intent is that these are defaults for variables that are not present in the environment, or whether these override explicit environment settings. There's a note that I also want to state for the record that I would prefer "last entry wins" to "first entry wins", but really I'd probably prefer "it is an error to have duplicate entries in the file", because that way we can be reasonably sure people don't get silently-surprising behavior. |
After a long discussion with @golang/proposal-review, we are going to tentatively accept this proposal and try out the implementation for a few weeks. |
cl/171137 seems to also have changed the default for CGO_ENABLED when cross compiling. Not saying it's a bad change, I just don't know if it was supposed to happen? |
@bufflig Historically cross-compiling always set |
So, is there a less hacky way to export the (sorry if the answer is already posted, it was a long thread...) |
@lindhe yes, you can use |
And |
@lindhe As far as I know, except |
I can confirm this change in behavior from 1.12 -> 1.13/1.14. It seems to occur under specific conditions:
Not sure if this was intended or even supported, so I am not opening a new issue for this. |
Setting environment variables for
go
command configurationis too difficult and system-specific.
We propose to add
go env -w
, to set defaults more easily.See https://golang.org/design/30411-env.
(Note: When this was just a placeholder issue to get a number allocated for the design doc, the text here said only "mine all mine". The laughing emoji reactions are from that original text.)
The text was updated successfully, but these errors were encountered: