Skip to content
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

cmd/go: go run should mimic the running script #17813

Closed
natefinch opened this issue Nov 6, 2016 · 10 comments

Comments

Projects
None yet
9 participants
@natefinch
Copy link
Contributor

commented Nov 6, 2016

IMO, go run should always mimic the output of the program it is running, unless there is some problem generating that program. Currently, go run only ever returns exit code 0 on success, or 1 on failure, regardless of what error code the program exited with. I think it should return the same exit code as the program always. In addition, if the program exits with a non-zero exit code, go run prints "exit status 1" (or whatever the exit code was). Unless go run has a problem generating the program (can't find a file, can't compile, etc), then I don't think it should print anything out. Notably, if go run returned the right return code, that extra text would be extraneous anyway.

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

1.7

What operating system and processor architecture are you using (go env)?

linux/amd64

What did you do?

go run script.go
echo $?

where script.go is

package main
import "os"
func main() {
	os.Stderr.Write([]byte("Hi!"))
	os.Exit(2)
}

What did you expect to see?

Hi!
2

What did you see instead?

Hi!
exit status 2
1

@0xmohit

This comment has been minimized.

Copy link
Contributor

commented Nov 6, 2016

This came up earlier too.

@josharian josharian changed the title Go Run should mimic the running script cmd/go: go run should mimic the running script Nov 6, 2016

@natefinch

This comment has been minimized.

Copy link
Contributor Author

commented Nov 6, 2016

The arguments against this in the other thread seem at cross purposes. At once we have Dave saying "Go run is a toy". And Russ saying "But what if this edge case happens?"

Right now, go run is working in a way that I would think is unexpected to most people. I think it's reasonable for people to expect go run to exit with the same code the program it is running exits with.

Russ asked if go run is an interpreter for go programs, and I think it's clear that most people assume it is. Is it going to have perfect output, since we're running two executables in series? No, of course not. But we can do better than we do now. The 99% case is that go run successfully builds what you point it at, and thus should return what the executing binary returns. When go run fails to build, this is generally going to be while a human is editing the code and thus will see the errors.

Dimitry mentioned "go run is a convenience feature for when your needs are not as demanding and you're okay with less information" ... well if we're ok with less information, why not get the 99% case right?

@cznic

This comment has been minimized.

Copy link
Contributor

commented Nov 6, 2016

I object to improving go run in any way. If it does not work for someone as needed, he's abusing it.

What's wrong with executing a properly built binary instead?

@justinfx

This comment has been minimized.

Copy link

commented Nov 6, 2016

@cznic, I disagree with you that a tool shouldn't be improved because you feel it was written for a limited purpose and that making it better would encourage people to use it.

If an available tool is perceived to have flaws then I would think it should be a candidate for improvement, or otherwise a candidate for removal. If someone is finding it useful, then it should be valid that go run should see improvements as necessary.

I agree that a wrapper which executes an application should be well behaved and preserve the exit code, as well as not introduce its own print statements regarding the execution of the app. Printing after failure to initialize the app should be fine though.

@cznic

This comment has been minimized.

Copy link
Contributor

commented Nov 6, 2016

@justinfx

If an available tool is perceived to have flaws then I would think it should be a candidate for improvement, or otherwise a candidate for removal. If someone is finding it useful, then it should be valid that go run should see improvements as necessary.

With full due respect, IMO the perceived flaw is what I call abuse. Then, of course, the conclusion I'd adopt differs. Anyway, bringing different views on the table can help in seeking the decision on the issue, so thanks for the input.

@dmitshur

This comment has been minimized.

Copy link
Member

commented Nov 6, 2016

IMO, go run should always mimic the output of the program it is running, unless there is some problem generating that program.

Then, when you get exit code 1, it is impossible to know if it came from go run or the built binary.

Currently, go run is precise, and it's returning as much information as it can with 100% accuracy. I would argue this is what most people using Go expect. Making it work for the 99% case means it wouldn't work in the 1% case, and I disagree with that being an improvement.

As @0xmohit said, this is a duplicate of #13440. I will link to my #13440 (comment) there. @natefinch, can you tell me if you disagree with that rationale, and if so, which part(s)?

@natefinch

This comment has been minimized.

Copy link
Contributor Author

commented Nov 7, 2016

@shurcooL I read the other thread. I responded to a few of the points from there.

You say that go run's return value is precise, but that's not exactly true. The only return code that you can really understand is 0. When it returns 1, it might be because go run itself failed (.e.g if the file you specified was not a go file), or it might be because the executable returned non-zero. You can't tell. This would not change with my proposal. 0 would still be "everything worked" and 1 would still be "something went wrong"... but at least go run wouldn't be intentionally dropping data on the floor for absolutely no reason.

In fact, if the script is written to avoid colliding with error codes that go run uses (since go run only uses 1 and 2 for failures AFAICT), then it can be 100% precise - just return 3 or higher.

There seems to be no logical reason to avoid returning the correct error code. Carefully written scripts can still be precise, and if you're not sure if a script was written in that way, you can still just treat any non-zero error code as a unknowable failure, just as it works today. The only possible thing you're losing is the fact that if the script doesn't print out anything when it fails, then go run won't either... but again, if it returned the right error code in the first place, you wouldn't need to print it out.

I think it's interesting that Russ mentioned go run as an equivalent to make, because a lot of people use go run as a replacement makefile, for example, @bradfitz's camlistore, which it also happens, may return an exit code that gets swallowed into the abyss.

@cznic - the reason to use go run instead of a binary is exactly how it's being used in Camlistore - you can check in a script to source control that is runnable. Sure, you could compile that script in CI and then run it and throw away the binary later.... except that's exactly what go run does, but it munges the error code and the output.

Go run fills a niche, and is quite useful, except for this one little niggle.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Nov 7, 2016

As far as I can tell, this is a straight dup of #13440. So, closing as dup.

Personally I think that go run should either pass the exit status through precisely, or it should do something simple. Passing the exit status through precisely is rather difficult and is most likely undesirable when the exit status indicates that the program dumped core. So, it should do something simple, which is what it already does.

@posener

This comment has been minimized.

Copy link

commented Aug 26, 2017

Another solution could have been something similar to the one chosen in the GNU env command. Quoting:

Exit status:

0 if no command is specified and the environment is output
125 if env itself fails
126 if command is found but cannot be invoked
127 if command cannot be found
the exit status of command otherwise

@karma0

This comment has been minimized.

Copy link

commented Sep 14, 2017

For anyone looking for a potential use-case or workaround, consult this shell scripting hackery around using go files in Bash/Zsh.

This functionality would definitely be handy for some.

@golang golang locked and limited conversation to collaborators Sep 14, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.