Muhammad Faizan
Muhammad Faizan

Reputation: 944

Converting from slice to array?

I'm wondering whether there is a way to pass a slice of the appropriate size to a function that is expecting an array?

For example, is there a reason I shouldn't be allowed to do the following?

func p(arr [4]int) {
    for _, v := range arr {
        fmt.Print(v)
    }
}

func main() {
    data := make([]int, 10)
    for i, _ := range data {
        data[i] = i
    }

    p(data[0:4]) // error
}

I know that I can just create a copy:

arr := [4]int{}
copy(arr[:], data)
p(arr)

But isn't that just creating an unnecessary copy? (since I'm guessing that another copy of arr will have to be made on the stack)

Upvotes: 0

Views: 986

Answers (1)

Vladimir Matveev
Vladimir Matveev

Reputation: 127751

For example, is there a reason I shouldn't be allowed to do the following?

Yes, there is. [4]int is just a flat sequence of four integers. When you pass it to the function, they are copied, so modifications inside a function won't affect original value. The following code prints 1 2 3 4 both times.

func change(arr [4]int) {
    arr[1] = 100
}

func prn(arr [4]int) {
    for _, v := range arr {
        print(v, " ")
    }
    println()
}

func main() {
    x := [4]int{1, 2, 3, 4}
    prn(x)
    change(x)
    prn(x)
}

However, a slice is a pointer to an array of some size (called capacity of the slice) and a length - two pointer-sized numbers. When you pass a slice to a function, you essentially pass a reference to the underlying array, so you can change it inside the function. The following program prints 1 2 3 4 and then 1 100 3 4:

func change(arr []int) {
    arr[1] = 100
}

func prn(arr []int) {
    for _, v := range arr {
        print(v, " ")
    }
    println()
}

func main() {
    x := []int{1, 2, 3, 4}
    prn(x)
    change(x)
    prn(x)
}

So, in fact, internal representation of slices and arrays are different, and one cannot be used instead of another and vice versa. You have to copy slice contents to another array.

Of course, there are no technical difficulties which prevent Go from doing such conversion automatically (create an array implicitly and copy slice contents to it and pass it to the function). However, Go language designers made deliberate decision to abstain from implicit conversions as much as possible. If you really need this operation, you can do it yourself, it is not that hard.

Upvotes: 3

Related Questions