从切片转换为数组?

时间:2013-11-17 05:34:40

标签: go

我想知道是否有办法将适当大小的切片传递给期望数组的函数?

例如,我不应该被允许做以下事情吗?

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
}

我知道我可以创建副本:

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

但这不就是创造一个不必要的副本吗? (因为我猜测必须在堆栈上制作arr的另一个副本)

1 个答案:

答案 0 :(得分:3)

  

例如,是否有理由不允许我这样做   以下

是的,有。 [4]int只是一个由四个整数组成的平坦序列。将它传递给函数时,它们会被复制,因此函数内部的修改不会影响原始值。以下代码同时打印1 2 3 4

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)
}

但是,切片是指向某个大小的数组(称为切片的容量)和长度的指针 - 两个指针大小的数字。将切片传递给函数时,实质上是将引用传递给基础数组,因此可以在函数内部进行更改。以下程序打印1 2 3 4,然后打印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)
}

因此,实际上,切片和数组的内部表示是不同的,不能使用一个而不是另一个,反之亦然。您必须将切片内容复制到另一个数组。

当然,没有技术上的困难阻止Go自动进行这样的转换(隐式创建数组并将切片内容复制到它并将其传递给函数)。然而,Go语言设计者故意决定尽可能地避免隐式转换。如果你真的需要这个操作,你可以自己做,不是那么难。