func foo(arr []int) int 和 func foo(arr [num]int) int 有什么区别

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

我还发现如果我使用foo1(arr2)foo2(arr1),编译器会报错"cannot use arr2 (type []int) as type [2]int in argument to foo1""cannot use arr1 (type [2]int) as type []int in argument to foo2".

所以谁能帮忙解释一下它们有什么区别或者给我一些link研究一下?提前谢谢你。

[2]int 是一个有 2 个条目的定长数组。
[]int 是一个不固定的切片。

func foo1(arr [2]int) 需要一个 固定长度 具有 2 个条目的 int 数组。 func foo2(arr []int) 接受一个 非固定 整数切片,其中包含任意数量的条目。

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

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

类型 []T 是一个包含类型 T 元素的切片。

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

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

所以原值arr1保持不变

[2]int 是一个 array, []int is a slice.

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

的内容

Go 中的一切都是按值传递的。片也。但是切片值是 header,描述了后备数组的连续部分,切片值仅包含指向实际存储元素的数组的指针。切片值不包括其元素(与数组不同)。当你传递一个切片时,只有切片 header 被复制(指向同一个后备数组),因此修改它的元素会修改同一个后备数组中的元素,所以调用者会观察到变化。在这里阅读更多相关信息:Are golang slices pass by value? To see what's in a slice header: reflect.SliceHeader.

与切片不同,数组不是 header。一个数组值意味着它的所有元素,所以当你传递一个数组值时,它的所有元素都被复制,并且在传递给它的函数内部你只能修改这个复制数组;调用者不会观察到对数组所做的更改(例如更改其元素)。

请注意,从数组中获取切片值非常容易,您可以简单地使用 slicing:

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

推荐博客post:Go Slices: usage and internals

更深入地了解数组与切片:Why have arrays in Go?