2014-12-04 91 views
0

爲什麼map在Go上有不同的行爲?關於在Go上使用等號和地圖的說明

在Go所有類型由值複製:stringintxxuintxxfloatxxstruct[...]array[]slice除了map[key]value

package main 

import "fmt" 
type test1 map[string]int 

func (t test1) DoSomething() { // doesn't need to use pointer 
    t["yay"] = 1 
} 

type test2 []int 

func (t* test2) DoSomething() { // must use pointer so changes would effect 
    *t = append(*t,1) 
} 

type test3 struct{ 
    a string 
    b int 
} 

func (t* test3) DoSomething() { // must use pointer so changes would effect 
    t.a = "aaa" 
    t.b = 123 
} 

func main() { 
t1 := test1{} 
u1 := t1 
u1.DoSomething() 
fmt.Println("u1",u1) 
fmt.Println("t1",t1) 

t2 := test2{} 
u2 := t2 
u2.DoSomething() 
fmt.Println("u2",u2) 
fmt.Println("t2",t2) 

t3 := test3{} 
u3 := t3 
u3.DoSomething() 
fmt.Println("u3",u3) 
fmt.Println("t3",t3) 
} 

而傳遞變量作爲函數的參數/參數等於與:=分配

package main 

import "fmt" 
type test1 map[string]int 

func DoSomething1(t test1) { // doesn't need to use pointer 
    t["yay"] = 1 
} 

type test2 []int 

func DoSomething2(t *test2) { // must use pointer so changes would effect 
    *t = append(*t,1) 
} 

type test3 struct{ 
    a string 
    b int 
} 

func DoSomething3(t *test3) { // must use pointer so changes would effect 
    t.a = "aaa" 
    t.b = 123 
} 

func main() { 
t1 := test1{} 
DoSomething1(t1) 
fmt.Println("t1",t1) 

t2 := test2{} 
DoSomething2(&t2) 
fmt.Println("t2",t2) 

t3 := test3{} 
DoSomething3(&t3) 
fmt.Println("t3",t3) 
} 

回答

3

Map values are pointers。其他一些類型(片,字符串,通道,函數)類似地用指針實現。有趣的是,鏈接的常見問題條目說,

早些時候,地圖和通道是語法指針,並且不可能聲明或使用非指針實例。最終我們決定嚴格分離指針和值使得語言更難以使用。

「按值傳遞」表示作爲常規函數參數傳遞的變量不會被被調用函數修改。這並不改變一些內置類型可以包含指針(就像你自己的結構一樣)。

Python是相似的:f(x)不會改變傳遞給它的整數x,但它可以添加到一個列表x因爲Python列表與指針內部實現。相比之下,C++具有實際的傳遞參考:f(x)可以更改調用者的int x,如果f被聲明爲具有參考參數(void f(int& x))。

(我也寫了一些general info on pointers vs. values in Go在另一個問題的答案,如果有幫助。)