关于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" 这样就不会报错
}