What's the difference between func foo(arr []int) int and func foo(arr [num]int) int

huangapple go评论78阅读模式
英文:

What's the difference between func foo(arr []int) int and func foo(arr [num]int) int

问题

func foo(arr []int) intfunc foo(arr [num]int) int 之间的区别是什么?

这里有两个例子:

func foo1(arr [2]int) int {
    arr[0] = 1
    return 0
}

func foo2(arr []int) int {
    arr[0] = 1
    return 0
}

func main() {
    var arr1 = [2]int{3, 4}
    var arr2 = []int{3, 4}
    foo1(arr1)
    println(arr1[0])      // 结果是3,所以foo1(arr)中的arr是一个副本
    foo2(arr2)
    println(arr2[0])      // 结果是1,所以foo2(arr)中的arr不是一个副本,它是一个引用
}

我还发现如果我使用 foo1(arr2)foo2(arr1),编译器会报错,类似于“cannot use arr2 (type []int) as type 2int in argument to foo1”和“cannot use arr1 (type 2int) as type []int in argument to foo2”。

所以谁能帮忙解释一下它们之间的区别,或者给我一些学习的链接?提前谢谢你。

英文:

What's the difference between func foo(arr []int) int and func foo(arr [*num*]int) int?

Here are two examples:

func foo1(arr [2]int) int {
    arr[0] = 1
    return 0
}

func foo2(arr []int) int {
    arr[0] = 1
    return 0
}

func main() {
    var arr1 = [2]int{3, 4}
    var arr2 = []int{3, 4}
    foo1(arr1)
    println(arr1[0])      // result is 3, so arr in foo1(arr) is a copy
    foo2(arr2)
    println(arr2[0])      // result is 1, so arr in foo2(arr) is not a copy, it is a reference
}

I also found if I use foo1(arr2) or foo2(arr1), the compiler will report an error like "cannot use arr2 (type []int) as type 2int in argument to foo1" and "cannot use arr1 (type 2int) as type []int in argument to foo2".

So who can help to explain what's the difference between them or give me some link to study? Thank you in advance.

答案1

得分: 5

[2]int 是一个数组,[]int 是一个切片。

数组和切片是完全不同的类型:你不能将一个数组传递给需要切片的地方,也不能将一个切片传递给期望数组的地方。由于长度是数组类型的一部分,所以你甚至不能使用长度不同的数组值,例如你不能将类型为 [3]int 的数组值用于期望 [2]int 的地方。

在Go中,所有的东西都是按值传递的,包括切片。但是,切片值是一个“头部”,描述了一个连续的部分,它指向一个后备数组,并且切片值只包含一个指向实际存储元素的数组的指针。切片值不包括其元素(与数组不同)。当你传递一个切片时,只有切片头部被复制(指向相同的后备数组),所以修改其元素会修改相同后备数组中的元素,因此调用者会观察到这些变化。在这里可以了解更多信息:https://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value/39993797#39993797 要查看切片头部的内容,请参阅 reflect.SliceHeader

与切片不同,数组不是头部。数组值表示其所有元素,因此当你传递一个数组值时,所有的元素都会被复制,在函数内部,你只能修改这个复制的数组;调用者不会观察到对数组(例如更改其元素)所做的更改。

请注意,虽然很容易从数组中获取一个切片值,你可以简单地使用切片操作:

var a [2]int = [2]int{1, 2}
var s []int = a[:]
fmt.Println(s) // 输出 [1 2]

推荐的博客文章:Go切片:用法和内部原理

关于数组和切片的更多见解:https://stackoverflow.com/questions/38645175/why-have-arrays-in-go/38645895#38645895

英文:

[2]int is an array, []int is a slice.

Arrays and slices are completely different types: you can't pass an array where a slice is required, and you can't pass a slice where an array is expected. Since the length is part of the array type, you can't even use array values where the length differs, e.g. you can't use an array value of type [3]int for something that expects [2]int.

Everything in Go is passed by value. Slices too. But a slice value is a header, describing a contiguous section of a backing array, and a slice value only contains a pointer to the array where the elements are actually stored. The slice value does not include its elements (unlike arrays). When you pass a slice, only the slice header is copied (pointing to the same backing array), and so modifying its elements modifies elements in the same backing array, so the caller will observe the changes. Read more about this here: https://stackoverflow.com/questions/39993688/are-golang-slices-pass-by-value/39993797#39993797 To see what's in a slice header: reflect.SliceHeader.

Unlike slices, arrays are not headers. An array value means all its elements, so when you pass an array value, all its elements are copied, and inside the function it is passed to you can only modify this copy array; the caller won't observe the changes made to the array (e.g. changing its elements).

Note that however it is very easy to obtain a slice value from an array, you may simply use slicing:

var a [2]int = [2]int{1, 2}
var s []int = a[:]
fmt.Println(s) // Prints [1 2]

Recommended blog post: Go Slices: usage and internals

More insight into arrays vs slices: https://stackoverflow.com/questions/38645175/why-have-arrays-in-go/38645895#38645895

答案2

得分: 0

[2]int 是一个长度为2的固定长度数组。
[]int 是一个非固定长度的切片。

func foo1(arr [2]int) 期望一个长度为2的固定长度int数组。
func foo2(arr []int) 接受一个任意长度的非固定长度int切片。

它们看起来相似,但如果你将2int和[]int视为完全不同的结构,可能会有所帮助。

英文:

[2]int is a fixed-length array with 2 entries.
[]int is a not fixed slice.

func foo1(arr [2]int) expects a fixed-length array of int with 2 entries.
func foo2(arr []int) takes a non-fixed slice of int with any number of entries.

They look similar, but it may help if you think of 2int and []int as totally different structures.

答案3

得分: 0

类型[n]T是由类型Tn个值组成的数组。

类型[]T是具有类型T的元素的切片。

数组具有固定的大小,而切片是动态的。

使用foo1时,在调用函数时会创建数组的副本。

因此,原始值arr1保持不变。

英文:

The type [n]T is an array of n values of type T.

The type []T is a slice with elements of type T.

An array has a fixed size. whereas a slice is dynamic.

With foo1 a copy of the array is made when the function is called.

So the original value arr1 remains unchanged

huangapple
  • 本文由 发表于 2017年6月23日 16:01:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/44716125.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定