Gomt append()受fmt.Println()影响的奇怪行为

I noticed some strange behavior with Golang's append(). I understand the basic concept of how slice capacity affects whether a new underlying array gets allocated, but why is whether or not I use a fmt.Println() AFTER the append has happened affecting the result of the append?

package main

import "fmt"

func main() {
    a := []byte("AAA")

    b := append(a, []byte("BBB")...)
    fmt.Println(" a: ", string(a), " b: ", string(b))

    c := append(a, []byte("CCC")...)
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c))

    fmt.Println(&b) //try commenting this out and in and running the program
}

Link to run code here: https://play.golang.org/p/jJ-5ZxTBIn

You're right: That is because The Go Playground version is old (go1.6.2), use new version.


The correct output (using go version go1.7rc6) is:

 a:  AAA  b:  AAABBB
 a:  AAA  b:  AAACCC  c:  AAACCC

1- The Go Playground (go1.6.2):

package main

import "fmt"

func main() {
    a := make([]byte, 100, 1000)
    a = []byte("AAA")

    b := append(a, []byte("BBB")...)
    fmt.Println(" a: ", string(a), " b: ", string(b))

    c := append(a, []byte("CCC")...)
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c))

    //fmt.Println(&b) //try commenting this out and in and running the program
}

output:

 a:  AAA  b:  AAABBB
 a:  AAA  b:  AAABBB  c:  AAACCC

2- The Go Playground (go1.6.2):

package main

import "fmt"

func main() {
    a := make([]byte, 100, 1000)
    a = []byte("AAA")

    b := append(a, []byte("BBB")...)
    fmt.Println(" a: ", string(a), " b: ", string(b))

    c := append(a, []byte("CCC")...)
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c))

    fmt.Println(&b) //try commenting this out and in and running the program
}

output:

 a:  AAA  b:  AAABBB
 a:  AAA  b:  AAACCC  c:  AAACCC
&[65 65 65 67 67 67]

using go version go1.7rc6:

package main

import "fmt"

func main() {
    a := make([]byte, 100, 1000)
    a = []byte("AAA")

    b := append(a, []byte("BBB")...)
    fmt.Println(" a: ", string(a), " b: ", string(b))

    c := append(a, []byte("CCC")...)
    fmt.Println(" a: ", string(a), " b: ", string(b), " c: ", string(c))

    //fmt.Println(&b) //try commenting this out and in and running the program
}

output :

 a:  AAA  b:  AAABBB
 a:  AAA  b:  AAACCC  c:  AAACCC

I will summarize:

a := make([]byte, 100, 1000)
a = []byte("AAA")

creates a slice, in first line, but in second it creates a new array and slice again.

Capacity of this new array depends on version of compiler, therefore good written code should not make any other assumption, than it will be 3 or more.

Be cautious when using append. Returned slice could be shallow or deep copy of previous slice. Which one depends on array capacity. If you need a deep copy, you have to do it manually.

b:=make([]byte, len(a))
copy(b,a)