-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
variable overwrite behavior in "select" defers from otherwise #739
Labels
Comments
Notice, the problematic situation described here generalizes cleanly as follows. The code: f() (n int) { n := 4 ... } is not allowed. Because "the new" n shadows the return parameter n. On the other hand, the following is allowed: f() (n int) { { n := 4 ... return // MARK } panic("x") } So, it seems that as soon as we are in a sub-block of the function body, the compiler ceases to check whether locally defined new variables shadow the return parameters. This creates a very easy spot for programmer confusion at the MARK, because the programmer is thinking that the local copy of "n" is what is returned, when in fact it is not. |
Isn't this merely a duplicate of issue #377? The behavior is documented in The Go Programming Language Specification: Short variable declarations http://golang.org/doc/go_spec.html#Short_variable_declarations |
Yes, this issue is an exact duplicate. I also looked at the documentation which suggests that the current implementation violates the specification: " ... Redeclaration does not introduce a new variable; it just assigns a new value to the original.... " Because this is not what happens when you have shadowing of a variable. |
"Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared in the same block with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original." In your Comment 1 example, the short variable declaration `n := 4` can't redeclare the function result variable `n int`; `n int`, the original declaration, is not in the same block. Also, `n := 4` isn't a multi-variable short declaration. Therefore, `n := 4` declares a new inner variable, shadowing and hiding the outer variable `n int`. |
Fair enough. The compiler behaves by the spec, but my point is that the spec seems too convoluted: (1) According to the spec the following two functions are different, but according to common-sense programmer's assumption, they shouldn't be: func f() (n int) { n,err := Read(...) return } and func f() (n int) { { n,err := Read(...) return } } (2) I have made the following error over and over again in my code over the past few months, *despite* having known of this issue at various times (and forgotten it): func f() (err os.Error) { if _,err := Read(); err != nil { return } } And consequently, in complex programs, this takes forever to debug, especially because while you are debugging it you still have the wrong idea in your mind about what this code does, so you eyeball it and you think, the error is not there. --P |
It's true that := and named returns don't play nicely with each other. I tend to avoid named returns in all but the most trivial of functions. Status changed to Duplicate. Merged into issue #377. |
Comment 7 by [email protected]: Notice how when citing a real-world example, the problem is between "if ... {". Maybe the problem is really with the implicit blocks instead of the scoping issue. I miss some knowledge here, but what if the implicit scope where executed in the parent's scope instead of in it's own ? It seems like it would solve most of the problems and still allow shallow variables. |
This issue was closed.
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
The text was updated successfully, but these errors were encountered: