将值附加到切片时,值与原始值不同

consider this piece of code:

package main

import (
    "fmt"
)

func main() {
    fmt.Println(Part(11))
}

func Part(n int) string {
    enumResult := [][]int{}
    enum(n, n, []int{}, &enumResult)
    fmt.Println(enumResult)
    fmt.Println(40, enumResult[40])
    return ""
}

var abc int = 0

func enum(n int, top int, pre []int, result *[][]int) {
    var i int
    if n > top {
        i = top
    } else {
        i = n
    }
    for ; i > 0; i-- {
        tempResult := append(pre, i)
        if n-i == 0 {
            /*  if tempResult[0] == 3 && tempResult[1] == 3 && tempResult[2] == 3 && tempResult[3] == 2 {
                tempResult = append(tempResult, 12345)
            }*/
            fmt.Println(abc, tempResult)
            abc++
            *result = append(*result, tempResult)
        } else {
            enum(n-i, i, tempResult, result)
        }
    }
}

When I run this code

I append value '[3,3,3,2]' to 'enumResult'

but If I check the value of 'enumResult' then '[3,3,3,1]' is appear

it`s index is 40 =>enumResult[40] (other value is correct)

I don`t know why this is happening Can you explain to me why?

The problem is indeed due to append.

There are two thing about append. First is, that append doe not necessarily copy memory. As the spec specifies:

If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large underlying array that fits both the existing slice elements and the additional values. Otherwise, append re-uses the underlying array.

This may cause unexpected behavior if you are not clear. A playground example: https://play.golang.org/p/7A3JR-5IX8o

The second part is, that when append does copy memory, it grows the capacity of the slice. However, it does not grow it just by 1. A playground example: https://play.golang.org/p/STr9jMqORUz

How much append grows a slice is undocumented and considered an implentation details. But till Go 1.10, it follows this rule:

Go slices grow by doubling until size 1024, after which they grow by 25% each time.

Note that when enabling race-detector, this may change. The code for growing slice is located in $GOROOT/src/runtime/slice.go in growslice function.

Now back to the question. It should be clear now that your code did append from a same slice with sufficient capacity due to growth of the slice from append before. To solve it, make a new slice and copy the memory.

tempResult := make([]int,len(pre)+1)
copy(tempResult,pre)
tempResult[len(pre)] = i