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)