Golang将数组传递给函数并修改它

Golang passing arrays to the function and modifying it

本文关键字:函数 修改 数组 Golang      更新时间:2023-10-16

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

这让我有点困惑-这是不是意味着传递一个没有引用的数组不应该修改数组本身?让我举例说明:

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完全陌生,并试图很好地理解基础知识。

解释相当简单:上面的代码中没有显式声明或使用单个数组。您的tab局部变量和tab参数是

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

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

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

请阅读下面的博客文章,这些文章详细解释了这一点:

Go Slices:用法和内部构造

数组、切片(和字符串):'append'

的机制

为什么在Go中有数组?

golang切片是按值传递的吗?

您定义的不是array,而是一个数组的slice,该数组通过引用传递,如golang文档中指定的。查看此链接