2014-12-04 85 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在另一个问题的答案,如果有帮助。)