【问题标题】:What's the difference between func foo(arr []int) int and func foo(arr [num]int) intfunc foo(arr []int) int 和 func foo(arr [num]int) int 有什么区别
【发布时间】:2017-07-04 19:19:05
【问题描述】:

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”的错误 em> 和 “不能在 foo2 的参数中使用 arr1(类型 [2]int)作为类型 []int”

那么谁可以帮助解释它们之间的区别或给我一些学习链接?提前谢谢你。

【问题讨论】:

标签: arrays go slice func


【解决方案1】:

[2]intarray[]intslice

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

Go 中的所有内容都是按值传递的。切片也。但是切片值是一个header,描述了一个支持数组的连续部分,切片值只包含一个指向实际存储元素的数组的指针。切片值不包括其元素(与数组不同)。当你传递一个切片时,只有切片头被复制(指向同一个后备数组),所以修改它的元素会修改同一个后备数组中的元素,所以调用者会观察到变化。在此处阅读有关此内容的更多信息:Are golang slices pass by value? 要查看切片标头中的内容:reflect.SliceHeader

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

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

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

推荐博文:Go Slices: usage and internals

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

【讨论】:

    【解决方案2】:

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

    []T 类型是一个带有T 类型元素的切片。

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

    foo1 在调用函数时会生成数组的副本。

    所以原来的值arr1保持不变

    【讨论】:

      【解决方案3】:

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

      func foo1(arr [2]int) 需要一个包含 2 个条目的 固定长度 int 数组。 func foo2(arr []int) 采用 non-fixed 的 int 切片,其中包含任意数量的条目。

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

      【讨论】:

      • [2]int 类型的数组有 2 个元素,而不是 3 个。
      猜你喜欢
      • 2011-07-26
      • 2021-09-16
      • 1970-01-01
      • 2010-09-16
      • 2015-01-06
      • 2010-11-18
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      相关资源
      最近更新 更多