go - unexpected slice append behaviour -


i encountered weird behaviour in go code today: when append elements slice in loop , try create new slices based on result of loop, last append overrides slices previous appends.

in particular example means slicefromloop j,g , h slice's last element not 100,101 , 102 respectively, but...always 102!

second example - slicefromliteral behaves expected.

package main  import "fmt"  func create(iterations int) []int {     := make([]int, 0)     := 0; < iterations; i++ {         = append(a, i)     }     return }  func main() {     slicefromloop()     slicefromliteral()  }  func slicefromloop() {     fmt.printf("** not working expected: **\n\n")     := create(11)     fmt.println("initial slice: ", i)     j := append(i, 100)     g := append(i, 101)     h := append(i, 102)     fmt.printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) }  func slicefromliteral() {     fmt.printf("\n\n** working expected: **\n")     := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}     fmt.println("initial slice: ", i)     j := append(i, 100)     g := append(i, 101)     h := append(i, 102)     fmt.printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h) } 

link play.golang: https://play.golang.org/p/inadvs3ats

after reading, digging , experimenting found problem originated in slices referencing same underlaying array values , can solved copying slice new 1 before appending anything, looks quite... hesitantly.

what's idomatic way creating many new slices based on old ones , not worrying changing values of old slices?

don't assign append other itself.

as mention in question, confusion due fact append both changes underlying array , returns new slice (since length might changed). you'd imagine copies backing array, doesn't, allocates new slice object points @ it. since i never changes, appends keep changing value of backingarray[12] different number.

contrast appending array, allocates new literal array every time.

so yes, need copy slice before can work on it.

func makefromslice(sl []int) []int {     result := make([]int, len(sl))     copy(result, sl)     return result }  func main() {     := make([]int, 0)     ii:=0; ii<11; ii++ {         = append(i, ii)     }     j := append(makefromslice(i), 100)  // works fine } 

the slice literal behavior explained because new array is allocated if append exceed cap of backing array. has nothing slice literals , internals of how exceeding cap works.

a := []int{1,2,3,4,5,6,7} fmt.printf("len(a) %d, cap(a) %d\n", a, len(a), cap(a)) // len(a) 7, cap(a) 7  b := make([]int, 0) i:=1; i<8, i++ {     b = append(b, i) }  // b := []int{1,2,3,4,5,6,7} // len(b) 7, cap(b) 8  b = append(b, 1)  // number, hits cap  := append(b, 100) j := append(b, 101) k := append(b, 102)  // these work expected 

Comments

Popular posts from this blog

java - pagination of xlsx file to XSSFworkbook using apache POI -

Unlimited choices in BASH case statement -

apache - How do I stop my index.php being run twice for every user -