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
Post a Comment