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) int
和func 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
是类型 T
的 n
个值的数组。
类型 []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?
func foo(arr []int) int
和func 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
是类型 T
的 n
个值的数组。
类型 []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?