range over slice while appending to it

2,535 views
Skip to first unread message

Albert Strasheim

unread,
Feb 1, 2011, 9:43:59 AM2/1/11
to golang-nuts
Hello all

As far as I can see, the Go Language Spec and Effective Go don't say
anything about the behavior of range over a slice where one appends to
the slice during the range.

I decided to see what happens:

package main
import (
"fmt"
)
func main() {
var c []int
c = append(c, 1)
c = append(c, 2)
for _, ci := range c {
if ci == 1 {
c = append(c, 3)
}
fmt.Printf("%d\n", ci)
}
fmt.Printf("%+v\n", c)
}

The output is:

1
2
[1 2 3]

so it seems the range bounds are established when the loop is started.

Regards

Albert

Jan Mercl

unread,
Feb 1, 2011, 10:28:37 AM2/1/11
to golang-nuts
On 1 ún, 15:43, Albert Strasheim <full...@gmail.com> wrote:
> Hello all
>
> As far as I can see, the Go Language Spec and Effective Go don't say
> anything about the behavior of range over a slice where one appends to
> the slice during the range.
The specs do say it (@emphasized@):
http://golang.org/doc/go_spec.html#RangeClause

[quoted]
RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "range"
Expression .

The expression on the right in the "range" clause is called the range
expression, which ...

The range expression is evaluated @once before beginning the loop@.
[/quoted]

ziutek

unread,
Feb 1, 2011, 10:30:42 AM2/1/11
to golang-nuts
The Go Programming Language Specification seys:

"The range expression is evaluated once before beginning the loop."

So range works on copy of its parameter.

Another test:

package main

import "fmt"

func main() {
array := [...]string{"a", "b", "c", "d"}
slice := array[:]

for i, s := range array {
array[3] += s
fmt.Printf("copy_of_array[%d] = %s\n", i, s)
}
fmt.Println("array =", array)
for i, s := range slice {
array[3] += s
fmt.Printf("copy_of_slice[%d] = %s\n", i, s)
}
fmt.Println("slice =", array)
fmt.Println("array =", array)
}

prints:

copy_of_array[0] = a
copy_of_array[1] = b
copy_of_array[2] = c
copy_of_array[3] = d
array = [a b c dabcd]
copy_of_slice[0] = a
copy_of_slice[1] = b
copy_of_slice[2] = c
copy_of_slice[3] = dabcdabc
slice = [a b c dabcdabcdabcdabc]
array = [a b c dabcdabcdabcdabc]

You can see what is difference between copy of array and copy of slice.

ziutek

unread,
Feb 1, 2011, 10:56:39 AM2/1/11
to golang-nuts
There is two mistakes in my example. There is correct one:

package main

import "fmt"

func main() {
array := [...]string{"a", "b", "c", "d"}
slice := array[:]

for i, s := range array {
fmt.Printf("copy_of_array[%d] = %s\n", i, s)
array[3] += s
}
fmt.Println("array =", array)

for i, s := range slice {
fmt.Printf("copy_of_slice[%d] = %s\n", i, s)
slice[3] += s
}
fmt.Println("slice =", slice)
fmt.Println("array =", array)
}

Output is identical as from previous incorrect code.
Reply all
Reply to author
Forward
0 new messages