关于go的map结构中,如果值类型是结构体的话,如以下代码,直接修改值会报一个错误

type User struct{
  Name string
}

func main(){
  list := make(map[int]User)
  list[0] = User{Name:"heihei"}  //到此时执行正确
  list[0].Name = "wangheihei"    //报错
}
cannot assign to struct field xxxx in map 

原因

要给变量赋值,必须知道其地址,而当map扩容的时候,可能要做key,value的迁移,如果此时value的类型是struct时,那么struct的属性则无法寻址,也就无法赋值了。

本身map是一种hash映射,而在底层实现则是利用了数组与链表两种数据结构来实现,这里稍微提一下hash的实现方式:

语言本身会提供一个hash函数来实现key到数组index的映射,如果映射之后的index不重复,那么本身是一个数组,这样通过index来读取值的时间复杂度是O(1),效率很高,但是当映射index重复的时候,并不是马上扩容,而是会在相同的index下挂载成一个链表,类似如下的数据结构:

只有当数据的值到达一定长度的时候,为了避免链表过长,就会进行扩容,此时的key/value的地址是可能发生改变的。

对具体map如何实现感兴趣的可以查看这边文章 golang之map底层实现

如何解决问题呢?

其实很简单,map值使用指针类型就可以解决

type User struct{
  Name string
}

func main(){
  list := make(map[int]*User)
  list[0] = &User{Name:"heihei"}  
  list[0].Name = "wangheihei"    这样就不会报错
}