2016-11-09 120 views
1

在大多数语言(如C++)中,传递数组会导致通过引用隐式传递数组,所以对函数中传递数组的任何更改都会导致更改原始数组。我正在学习Golang,并且在Alan A.A.的书“The Go Programming Language”中。 Donovan和Brian W. Kernighan据说,它的行为与其他语言不同 - 它并不隐式地按引用传递数组。Golang将数组传递给函数并对其进行修改

它让我感到困惑 - 这并不意味着传递没有引用的数组不应该修改数组本身吗?让我来说明:

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

你有没有通过任何的文件不见了,像(https://golang.org/doc/effective_go.html#slices)的[在“有效进入”片段],在[“之旅(https://tour.golang.org/moretypes/7),[Slice规范](https://golang.org/ref/spec#Slice_types),甚至是[Go博客关于切片的帖子](https://blog.golang.org/go-slices-usage-and-internals)? – JimB

回答

4

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

在Go中,数组的长度是该类型的一部分,例如, (例如,[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

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