Bug or misunderstanding?

15 views
Skip to first unread message

Mark Summerfield

unread,
Nov 19, 2010, 10:26:39 PM11/19/10
to golang-nuts
Hi,

The following tiny program does not work correctly:
////////////////////////////////////////////////////////////
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
var input *os.File
if len(os.Args) == 1 {
input = os.Stdin
} else {
input, err := os.Open(os.Args[1], os.O_RDONLY, 0)
if err != nil {
panic(err)
}
defer input.Close()
}
reader := bufio.NewReader(input)
for {
line, err := reader.ReadString('\n')
if err != nil {
break
}
fmt.Print(line)
}
}
////////////////////////////////////////////////////////////
If built as "test" then:
$ ./test
blah
blah

works fine, but

$ ./test datafile

outputs nothing.

If I change the program to:
////////////////////////////////////////////////////////////
package main
// as before
func main() {
var input *os.File
var err os.Error // NEW
if len(os.Args) == 1 {
input = os.Stdin
} else {
input, err = os.Open(os.Args[1], os.O_RDONLY, 0) // CHANGED
// as before
////////////////////////////////////////////////////////////
it works fine in both cases.

In the Specification it says:

"Unlike regular variable declarations, a short variable declaration
may redeclare variables provided they were originally declared in
the same block ... and at least one of the non-blank variables is
new. ... Redeclaration does not introduce a new variable; it just
assigns a new value to the original."

In the first version err is a new variable so I'm expecting input to get
assigned the *os.File returned by os.Open.

So is this a bug, or have I misunderstood?

Thanks!

PS

$ hg identify
a7800e20064a+ release/release.2010-11-10


--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
C++, Python, Qt, PyQt - training and consultancy
"Programming in Python 3" - ISBN 0321680561
http://www.qtrac.eu/py3book.html

Eoghan Sherry

unread,
Nov 19, 2010, 10:54:52 PM11/19/10
to Mark Summerfield, golang-nuts
In your first example the var declaration and short declaration of
input are in different blocks. One is in the func block the other in
the if block. The short decl goes out of scope after the if statement.
All you're left with is nil.

Eoghan

peterGo

unread,
Nov 19, 2010, 11:06:43 PM11/19/10
to golang-nuts
Mark,

{
input, err := os.Open(os.Args[1], os.O_RDONLY, 0)
}

Variables input and err are not originally declared in the same block.
Variables input and err will not redeclare any variables outside the
block. Variables input and err are new variables.

"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."

Short variable declarations, The Go Programming Language Specification
http://golang.org/doc/go_spec.html#Short_variable_declarations

Peter

Mark Summerfield

unread,
Nov 19, 2010, 11:10:46 PM11/19/10
to Eoghan Sherry, golang-nuts
Hi Eoghan,

So it was my misunderstanding.

Thanks!

--
Mark Summerfield, Qtrac Ltd, www.qtrac.eu
C++, Python, Qt, PyQt - training and consultancy

"Advanced Qt Programming" - ISBN 0321635906
http://www.qtrac.eu/aqpbook.html

peterGo

unread,
Nov 19, 2010, 11:11:05 PM11/19/10
to golang-nuts
Mark,

Issue 377 and others.

http://code.google.com/p/go/issues/detail?id=377

Peter

On Nov 19, 11:06 pm, peterGo <go.peter...@gmail.com> wrote:
> Mark,
>
> {
>         input, err := os.Open(os.Args[1], os.O_RDONLY, 0)
>
> }
>
> Variables input and err are not originally declared in the same block.
> Variables input and err will not redeclare any variables outside the
> block. Variables input and err are new variables.
>
> "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."
>
> Short variable declarations, The Go Programming Language Specificationhttp://golang.org/doc/go_spec.html#Short_variable_declarations

fango

unread,
Nov 19, 2010, 11:55:42 PM11/19/10
to golang-nuts

quote := `http://code.google.com/p/go/issues/detail?id=739

Comment 6 by project member r...@golang.org, Apr 25, 2010
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.
`
Maybe it's time to write a 'Go trap and pit falls'?

Cheers,
Fango

Eoghan Sherry

unread,
Nov 20, 2010, 1:51:11 AM11/20/10
to Mark Summerfield, golang-nuts
Whenever I see := I read "defined to be". So x:=y reads "x is defined
to be a variable initialized to y". This way it's clear that any x in an outer
block will be hidden.

I wasn't aware of the variable redeclaration clause before this
thread. It seems to only be of use when you have a sequence of
declarations which rely on an accumulated value. So instead of

var field1, field2 Field
var offset int
field1, offset = nextField(str, 0)
field2, offset = nextField(str, offset)

you can write

field1, offset := nextField(str, 0)
field2, offset := nextField(str, offset)

I would use the second form sparingly, if at all, since it breaks
how := is read.

Eoghan

fango

unread,
Nov 20, 2010, 4:07:26 AM11/20/10
to golang-nuts
Why not just read "x is y"?

Same we can simply read:

x = 1 as 'x is 1'
*p = f() as 'at p is (what) f returns' where 'at' is remembered as
asterisk
a[i] = 23 as "a'i is 23"
k = <-ch as ' k is from ch'

a[i] <<= 2 as " a'i left shift by 2"
i &^= 1<<n as " i XOR by 1 left shift n"

x, y = f() as " x y is f returns"
x, _ = f(1,2) as " x blank is f with 1 2 returns"
a, b = b, a as " a b is b a"

fango

unread,
Nov 20, 2010, 4:15:19 AM11/20/10
to golang-nuts
of cause example like "y[f()], ok = g(h(), i() + x[j()], <-c), k()" is
simply not readable no matter how we define the 'reading' language. An
experience of me is if one cannot be read aloud, it cannot be fully
understood. That's me only, I guess.

Cheers,
Fango

Eoghan Sherry

unread,
Nov 20, 2010, 11:03:57 AM11/20/10
to fango, golang-nuts
On 20 November 2010 04:07, fango <fan.h...@gmail.com> wrote:
> Why not just read "x is y"?
>
> Same we can simply read:
>
> x = 1 as 'x is 1'

The semantics of x:=y and x=y are different. Reading them both as
"x is y" seems like a bad idea. Of course, "x is defined
to be a variable initialized to y" is purposefully verbose. It's
internalized to a more efficient form.

Eoghan

ajstarks

unread,
Nov 20, 2010, 12:49:25 PM11/20/10
to golang-nuts
When I see x := y, I always think "x gets to be y"

On Nov 20, 11:03 am, Eoghan Sherry <ejshe...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages