When combining two slices, e.g. fruit and vegetables, to create a third, e.g. food. it would seem to make sense to append fruit and vegetable and assign the result directly to food.
golangci-lint's check: "appendAssign" suggests that is not an accepted way of doing so, with an alternative (see below) being preferrable.
What is the most idiomatic way of achieving this?
Code to illustrate question: https://go.dev/play/p/IFV6o92-HTb
package main
import "fmt"
func main() {
// fails linting with: gocritic: appendAssign: append result not assigned to the same slice
fruits := []string{"banana", "strawberry"}
vegetables := []string{"potato", "carrot"}
food := append(fruits, vegetables...)
fmt.Println(food)
// reset
food = nil
// passes linting
food = fruits
food = append(food, vegetables...)
fmt.Println(food)
}
One reason might be that you can get surprising results, like (Go Playground):
func main() {
fruits := []string{"banana", "strawberry", "apple", "cherry"}
vegetables := []string{"potato", "carrot"}
food := append(fruits[:2], vegetables...)
fmt.Println(food) // [banana strawberry potato carrot]
fmt.Println(fruits) // [banana strawberry potato carrot]
}
or even
func main() {
allFruits := []string{"banana", "strawberry", "apple", "cherry"}
fruits := allFruits[:2]
vegetables := []string{"potato", "carrot"}
food := append(fruits, vegetables...)
fmt.Println(food) // [banana strawberry potato carrot]
fmt.Println(allFruits) // [banana strawberry potato carrot]
}
because you potentially modify the underlying array of the first slice, which could be easily missed by the casual reader. It is immediately clear when you assign to the same variable in the same step.
The best way would be to use slices.Concat
:
food := slices.Concat(fruits, vegetables)
an alternative would be:
food := make([]string, 0, len(fruits)+len(vegetables))
food = append(food, fruits...)
food = append(food, vegetables...)
having the advantage of an preallocated array. Also possible is:
var food []string
food = append(food, fruits...)
food = append(food, vegetables...)
While what you are doing is fine from a language perspective, it could be surprising for people quickly reading over your code.
You are free to disagree and ignore the linter warning or turn it off. As a matter of opinion I think the alternative approaches are much more readable, especially slices.Concat
.