我想知道是否有办法将适当大小的切片传递给期望数组的函数?
例如,我不应该被允许做以下事情吗?
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
的另一个副本)
答案 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语言设计者故意决定尽可能地避免隐式转换。如果你真的需要这个操作,你可以自己做,不是那么难。