[go-nuts] Two complaints about :=

24 views
Skip to first unread message

Daniel Smith

unread,
Apr 18, 2010, 9:44:49 AM4/18/10
to golang-nuts
Suppose I have ret defined.

var ret int

I can do this, creating the new variable err:

ret, err := SomethingThatCouldFail()

However, this gives an error:

var ret MyType
ret.Field, err := SomethingThatCouldFail()

As does this:

var ret [5]int
ret[0], err := SomethingThatCouldFail()

Judging from the documentation [1], this is might be (it's unclear to me) the intended behavior, but it seems inconsistent to me. I'd expect all three or none to work.


That's not so bad (just annoying), since it at least gives a compiler error. More insidious is this behavior:

var ret int
if SomeCondition {
    ret, err := SomethingThatCouldFail()
    if err != nil {
        return err
    }
}

ret gets redeclared in the inner block, and the ret in the outer block never gets set. Again, it's hard to call this behavior wrong based on the spec, but it is easy to accidentally do this and it can make for hard-to-find bugs (especially the first time it happens to you). My preferred behavior would be for it to search enclosing scopes for "ret" as well as the current scope. I think that would be more user-friendly.


[1] http://golang.org/doc/go_spec.html#Variable_declarations

--
Daniel Smith
http://www.schaumburggoclub.org/

peterGo

unread,
Apr 18, 2010, 10:36:55 AM4/18/10
to golang-nuts
Daniel,

On Apr 18, 9:44 am, Daniel Smith <dan...@lukenine45.net> wrote:
> More insidious is this behavior:
>
> var ret int
> if SomeCondition {
> ret, err := SomethingThatCouldFail()
> if err != nil {
> return err
> }
>
> }
>
> ret gets redeclared in the inner block, and the ret in the outer block never
> gets set. Again, it's hard to call this behavior wrong based on the spec,
> but it is easy to accidentally do this and it can make for hard-to-find bugs
> (especially the first time it happens to you). My preferred behavior would
> be for it to search enclosing scopes for "ret" as well as the current scope.
> I think that would be more user-friendly.
>
> [1]http://golang.org/doc/go_spec.html#Variable_declarations

How does your complaint differ from: Issue 377: various changes to :=
http://code.google.com/p/go/issues/detail?id=377

Peter
> --
> Subscription settings:http://groups.google.com/group/golang-nuts/subscribe?hl=en

befelemepeseveze

unread,
Apr 18, 2010, 10:32:14 AM4/18/10
to golang-nuts
On 18 dub, 15:44, Daniel Smith <dan...@lukenine45.net> wrote:
> Suppose I have ret defined.
>
> var ret int
>
> I can do this, creating the new variable err:
>
> ret, err := SomethingThatCouldFail()
>
> However, this gives an error:
>
> var ret MyType
> ret.Field, err := SomethingThatCouldFail()

Here you are trying to (re)declare a variable named 'ret.Field'.
That's not a legal variable name:

http://golang.org/doc/go_spec.html#Short_variable_declarations
http://golang.org/doc/go_spec.html#Identifiers

>
> As does this:
>
> var ret [5]int
> ret[0], err := SomethingThatCouldFail()

Same story.

> Judging from the documentation [1], this is might be (it's unclear to me)
> the intended behavior, but it seems inconsistent to me. I'd expect all three
> or none to work.
>
> That's not so bad (just annoying), since it at least gives a compiler error.
> More insidious is this behavior:
>
> var ret int
> if SomeCondition {
>     ret, err := SomethingThatCouldFail()
>     if err != nil {
>         return err
>     }
>
> }

http://golang.org/doc/go_spec.html#Declarations_and_scope

"An identifier declared in a block may be redeclared in an inner
block. While the identifier of the inner declaration is in scope, it
denotes the entity declared by the inner declaration. "


> ret gets redeclared in the inner block, and the ret in the outer block never
> gets set. Again, it's hard to call this behavior wrong based on the spec,
> but it is easy to accidentally do this and it can make for hard-to-find bugs
> (especially the first time it happens to you). My preferred behavior would
> be for it to search enclosing scopes for "ret" as well as the current scope.
> I think that would be more user-friendly.

One doesn't have to (re)declare [local] variable names in a block.
Without that the problem can't demonstrate. Example:

var ret int
var err YourErrType
if SomeCondition {
ret, err = SomethingThatCouldFail() // note '=' instead of ':='
if err != nil {
return err
}
}

-bflm

peterGo

unread,
Apr 18, 2010, 11:17:46 AM4/18/10
to golang-nuts
Daniel,

On Apr 18, 9:44 am, Daniel Smith <dan...@lukenine45.net> wrote:
> Suppose I have ret defined.
>
> var ret int
>
> I can do this, creating the new variable err:
>
> ret, err := SomethingThatCouldFail()
>
> However, this gives an error:
>
> var ret MyType
> ret.Field, err := SomethingThatCouldFail()
>
> As does this:
>
> var ret [5]int
> ret[0], err := SomethingThatCouldFail()
>
> Judging from the documentation [1], this is might be (it's unclear to me)
> the intended behavior, but it seems inconsistent to me. I'd expect all three
> or none to work.
>
> That's not so bad (just annoying), since it at least gives a compiler error.
>
> [1]http://golang.org/doc/go_spec.html#Variable_declarations

For your first set of complaints, you only gave fragments of code, so
we don't know exactly what you tried to compile. For example, what is
MyType?

You said you looked at
[1] Variable declarations http://golang.org/doc/go_spec.html#Variable_declarations.

You should also have looked at
[2] Short variable declarations http://golang.org/doc/go_spec.html#Short_variable_declarations.

I wouldn't expect your second and third examples to qualify as a valid
short variable declarations.

Peter

On Apr 18, 9:44 am, Daniel Smith <dan...@lukenine45.net> wrote:

Daniel Smith

unread,
Apr 18, 2010, 11:49:23 AM4/18/10
to peterGo, golang-nuts
On Sun, Apr 18, 2010 at 9:36 AM, peterGo <go.pe...@gmail.com> wrote:
For your first set of complaints, you only gave fragments of code, so
we don't know exactly what you tried to compile. For example, what is
MyType?

It doesn't matter-- the point was that you can't set a field of a struct at the same time you declare a variable.
 
You said you looked at
[1] Variable declarations  http://golang.org/doc/go_spec.html#Variable_declarations.

You should also have looked at
[2] Short variable declarations  http://golang.org/doc/go_spec.html#Short_variable_declarations.

I did, its immediately after the section I linked and they both fit on my screen at the same time, so I didn't link them both.

I wouldn't expect your second and third examples to qualify as a valid
short variable declarations.

Your expectations are correct, because they don't. But since := allows you to set a pre-existing variable while declaring others, it seems reasonable to me to expect that it would be able to set fields in structs or elements of arrays/slices. This is mostly just a minor annoyance.



How does your complaint differ from: Issue 377: various changes to :=
http://code.google.com/p/go/issues/detail?id=377

My complaint is more general. 377 appears to only be complaining about shadowing return variables. My complaint is that if you use := to set multiple variables (intending to declare only one of them) in an "if" or "for" clause, you will end up shadowing a variable from the main body of your function. It makes it very easy to introduce a subtle bug. Yes, it happens most often with a variable named "err", but it is just as bad when it happens with other variables.


I think it is probably behaving according to spec, so I guess I'm complaining about the spec. Again, the first one is just annoying, the second one I really think ought to be changed.

Daniel Smith

unread,
Apr 18, 2010, 11:52:30 AM4/18/10
to befelemepeseveze, golang-nuts
On Sun, Apr 18, 2010 at 9:32 AM, befelemepeseveze <befeleme...@gmail.com> wrote:
On 18 dub, 15:44, Daniel Smith <dan...@lukenine45.net> wrote:
Here you are trying to (re)declare a variable named 'ret.Field'.
That's not a legal variable name:

I'm aware of why the compiler is complaining. I just think it's inconsistent with the rest of the things you can do with :=.

"An identifier declared in a block may be redeclared in an inner
block. While the identifier of the inner declaration is in scope, it
denotes the entity declared by the inner declaration. " 
One doesn't have to (re)declare [local] variable names in a block.
 
Without that the problem can't demonstrate. Example:

Again, I know why it happens and how to fix it. My complaint is that it's easy to do something you don't intend.
 

Daniel Smith

unread,
Apr 18, 2010, 11:55:58 AM4/18/10
to peterGo, golang-nuts
On Sun, Apr 18, 2010 at 9:36 AM, peterGo <go.pe...@gmail.com> wrote:
How does your complaint differ from: Issue 377: various changes to :=
http://code.google.com/p/go/issues/detail?id=377

After re-reading that issue, I think I'm making the same complaint. Sorry for the noise.
Reply all
Reply to author
Forward
0 new messages