Golang将数组传递给函数并进行修改

时间:2016-11-09 19:27:52

标签: c++ arrays go reference

在大多数语言(如c ++)中,传递数组会导致通过引用隐式传递它,因此对函数中传递的数组的任何更改都将导致更改原始数组。我正在学习Golang,并在Alan A.A.的“The Go Programming Language”一书中学习。 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完全不熟悉,并试图更好地理解基础知识。

2 个答案:

答案 0 :(得分:4)

解释相当简单:上面的代码中没有明确声明或使用的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?

答案 1 :(得分:1)

您定义的内容不是array,而是数组的slice,该数组按照golang文档中的指定通过引用传递。查看this链接。