Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems about `slice` and `append` in Go

Tags:

go

I have written the following code. But I can't have it compiled. Here is my code:

package main

import "fmt"

func main() {
    tmp := make([]int, 10)
    for i := 0; i < 10; i++ {
        tmp[i] = i
    }
    res := mapx(foo, tmp)
    fmt.Printf("%v\n", res)
}

func foo(a int) int {
    return a + 10
}

func mapx(functionx func(int) int, list []int) (res []int) {
    res = make([]int, 10)
    for _, i := range(list) {
        append(res, functionx(i))
    }
    return
}

Meanwhile the error message is also very confusing: prog.go:21: append(res, functionx(i)) not used

But if I replace append(res, functionx(i))(line 21) with res = append(res, functionx(i)), it works quite well. Can anybody help me?

Thank you!

like image 735
Zhe Chen Avatar asked May 24 '12 15:05

Zhe Chen


People also ask

Why you need to avoid using append in go?

WithAppend has the worst while WithAssignAlloc have the best performance, and this should convince you to avoid append . Let's add one more function which uses append and create a string slice by specifying the size and capacity with make . And run the benchmark again.

Can you append a slice to a slice Golang?

Two slices can be concatenated using append method in the standard golang library. Which is similar to the variadic function operation.

How do I append to slice go?

Append to Slice This allows you to add or remove elements as you see fit. To add an element to a slice in go, we can use the append() method. The append() method takes the name of the slice and the new element to add.

How slice append works in Golang?

The built-in append function appends elements to the end of a slice: if there is enough capacity, the underlying array is reused; if not, a new underlying array is allocated and the data is copied over.


1 Answers

Appending to and copying slices

The variadic function append appends zero or more values x to s of type S, which must be a slice type, and returns the resulting slice, also of type S.

If the capacity of s is not large enough to fit the additional values, append allocates a new, sufficiently large slice that fits both the existing slice elements and the additional values. Thus, the returned slice may refer to a different underlying array.

Calls

In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. The return parameters of the function are passed by value back to the calling function when the function returns.

In Go, arguments are passed by value.

You need to write res = append(res, functionx(i)) so that you don't discard the new value for res, which refers to a different slice and, possibly, a different underlying array.

For example,

package main

import "fmt"

func main() {
    res := []int{0, 1}
    fmt.Println(res)
    _ = append(res, 2) // discard
    fmt.Println(res)
    res = append(res, 2) // keep
    fmt.Println(res)
}

Output:

[0 1]
[0 1]
[0 1 2]
like image 172
peterSO Avatar answered Oct 18 '22 05:10

peterSO