2016-11-09 104 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鏈接。