英文:
Converting from slice to array?
问题
我想知道是否有一种方法可以将适当大小的切片传递给期望数组的函数?
例如,我是否可以这样做的原因是什么?
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]) // 错误
}
我知道我可以创建一个副本:
arr := [4]int{}
copy(arr[:], data)
p(arr)
但这不是创建一个不必要的副本吗?(因为我猜测栈上可能还需要另一个arr
的副本)
英文:
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
例如,我不被允许执行以下操作的原因是什么?
是的,有原因。[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)
}
然而,切片是指向某个大小为 capacity 的数组的指针,以及一个 length - 两个指针大小的数字。当你将切片传递给函数时,实际上是传递了对底层数组的 引用,所以你可以在函数内部对其进行修改。下面的程序先打印出 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 语言设计者有意决定尽可能避免隐式转换。如果你真的需要这个操作,你可以自己做,这并不难。
英文:
> 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论