【问题标题】:Golang passing arrays to the function and modifying itGolang 将数组传递给函数并对其进行修改
【发布时间】:2023-04-05 23:44:01
【问题描述】:

在大多数语言(如 c++)中,传递数组会导致通过引用隐式传递它,因此对函数中传递的数组的任何更改都将导致更改原始数组。我正在学习 Golang,并且在 Alan A.A. 的“Go 编程语言”一书中。 Donovan 和 Brian W. Kernighan 据说,它的行为不同于其他语言——它不会通过引用隐式传递数组。

这让我有点困惑——这是否意味着传递没有引用的数组不应该修改数组本身?让我来说明一下:

func main() {
    tab := []int{1, 2, 3}
    fmt.Println(tab)
    // Results in [1 2 3]
    reverse(tab)
    fmt.Println(tab)
    // Results in [3 2 1]
}

func reverse(tab []int) {
    for i, j := 0, len(tab)-1; i < j; i, j = i+1, j-1 {
        tab[i], tab[j] = tab[j], tab[i]
    }
}

在上面的代码中,数组不是通过引用传递的,但是反向函数修改了原始的,所以它的工作方式有点像 C++ 程序会做的事。谁能解释我的区别?

PS:对不起,如果这是一个愚蠢的问题,我对 Golang 完全陌生,并试图很好地理解基础知识。

【问题讨论】:

标签: c++ arrays go reference


【解决方案1】:

解释很简单:上面的代码中没有明确声明或使用一个array。您的tab 局部变量和tab 参数是slices。

在 Go 中,数组的长度是类型的一部分,例如[3]int(这在一定程度上是正确的,例如 [2]int 和 [3]int 是 2 个不同/不同的数组类型)。如果长度不存在(像[2]int 那样显式或像composite literal [...]int{1, 2, 3} 那样隐式),那么这不是数组类型而是切片类型。

是的,正如您所读到的,数组值意味着它的所有元素,并且当传递(或分配)时,它的所有元素都会被复制。然而,切片只是小的描述符、标题,描述了数组的连续部分;当切片被传递(或分配)时,只有这个头被复制(包括指针),它将指向同一个底层数组。因此,如果您修改切片副本的元素,更改将反映在原始切片中,因为只有一个支持数组保存元素。

如果你想知道切片头的确切内容,可以查看reflect.SliceHeader 类型:它是一个struct,包含指向切片第一个元素的指针、长度和容量切片。

请阅读以下详细解释这一点的博文:

Go Slices: usage and internals

Arrays, slices (and strings): The mechanics of 'append'

有关详细信息,另请参阅这些相关问题:

Why have arrays in Go?

Are golang slices pass by value?

【讨论】:

    【解决方案2】:

    您定义的不是array,而是一个数组的slice,它按照golang文档中的规定通过引用传递。检查this链接。

    【讨论】:

      猜你喜欢
      • 2015-06-13
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      相关资源
      最近更新 更多