Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
golang结构的另一个功能更改映射_Go - Fatal编程技术网

golang结构的另一个功能更改映射

golang结构的另一个功能更改映射,go,Go,我是新来的。现在我有一个关于functoid pass变量的问题。下面是代码: type User struct { Name string Map map[string]string } func main() { u := User{Name: "Leto"} u.Map = make(map[string]string) fmt.Println("before --------") fmt.Println(unsafe.Pointer(&a

我是新来的。现在我有一个关于functoid pass变量的问题。下面是代码:

type User struct {
    Name string
    Map  map[string]string
}
func main() {
    u := User{Name: "Leto"}
    u.Map = make(map[string]string)
    fmt.Println("before --------")
    fmt.Println(unsafe.Pointer(&u))
    fmt.Println(unsafe.Pointer(&(u.Map)))
    fmt.Println(u)
    Modify(u)
    fmt.Println("after --------")
    fmt.Println(u)
}
func Modify(u User) {
    fmt.Println("in func --------")
    fmt.Println(unsafe.Pointer(&u))
    fmt.Println(unsafe.Pointer(&(u.Map)))
    u.Name = "Paul"
    u.Map["t"] = "t"
}
以上代码输出:

before --------
0xc04203a4c0
0xc04203a4d0
{Leto map[]}
in func --------
0xc04203a500
0xc04203a510
after --------
{Leto map[t:t]}

在Modify func中,我知道用户是副本,所以更改名称不起作用是可以的,但为什么更改映射会影响用户结构?

切片、映射和通道是引用类型。因此,它们总是通过引用传递。

您应该在赋值和修改操作中分别使用&User和*User

检查这个


使用指向结构的指针总是更好的。

我们需要了解在每次调用中内存分配是如何工作的:

  u := User{Name: "Leto"}
// u is an object of type User
// after this line memory has been allocated to both the
// properties u.Name(string) and u.Map(reference)
// lets say allocated memory address for u.Name starts with x
// for u.Map it starts with y, and note that u.Map is a reference i.e. 
// the value contained in it will be a different memory address which
// will be the starting memory address of the actual map
// right now the value written at y is nil since it 
// does not point to any memory address
u.Map = make(map[string]string)
// now value of y has been updated to z (which is the 
// memory address of the beginning of the map initialized 
// with make call) 
fmt.Println("before --------")
fmt.Println(unsafe.Pointer(&u))
fmt.Println(unsafe.Pointer(&(u.Map)))
fmt.Println(u)
// here you are about to pass object by value 
// so basically a new object will be created of type User
// lets talk about how copy of this object will be created
// copy of u.Name will have a new address 
// lets call it x1 and the value "Leto" too will be 
// copied to memory address starting with x1
// copy of u.Map will have a new address too lets call it 
// y1 and its value z will be copied too to the memory address y1
// I think you must have got your answer by now. 
// Basically the newly copied object's property u.Map and 
// the old one's u.Map both points to the same memory address "z" 
// and hence whosoever updates the map the other one will see it
Modify(u)
fmt.Println("after --------")
fmt.Println(u)

有没有理由使用不安全的而不是fmt.Printf%p\n和&u?有趣的是,@nothingmoth实际上用这个用户名回答了他自己的问题!因为只有映射本身是按值传递和复制的:映射的内容由映射的所有副本共享。因此,一个映射在被正式复制并通过值传递时,其行为就好像它是一个引用类型。thks,很好的答案