0

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)

1
  • 3
    Essential reading on Go slices and arrays: blog.golang.org/go-slices-usage-and-internals and a short quote "Go's arrays are values. An array variable denotes the entire array; it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents." Commented Nov 17, 2013 at 9:51

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Nitpicking: a capacity of a slice is not merely the length of the underling array but the difference between its length and the first index of the slice (unless explicitly set when slicing, of course). More info here.
Keep in mind you can always create an array and pass it as a slice, for example x := [4]int{1, 2, 3, 4}; change(x[:]) will work as expected. play.golang.org/p/78jnOowS-7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.