map存入结构体的指针和结构体本身有什么区别吗?

一种是

mm := make(map[int]*struct)
ss := &struct{}

还有一种是

mm := make(map[int]struct)
ss := struct{}

最后

mm[1] = ss

请问一下这几种写法区别是什么呢?性能方面哪个更好啊?

另外我很好奇的是第一种写法里面&struct{}难道是在堆上分配空间吗?

我记得在c语言里面如果在函数里面直接初始化一个结构体是在栈上操作的,如果仅仅把这个结构体的指针存入一个数组里面,等函数返回之后这个结构体就销毁了。

golang为什么我见有人这样写也没事呢?是底层操作方式不一样吗?

阅读 14.4k
2 个回答
  • map[int]struct {}不能修改struct内的属性
type SS struct {
    Name string
}

func main() {
    ss := SS{
        Name: "struct",
    }

    ms := make(map[int]SS)
    ms[1] = ss

    sp := &SS{
        Name: "pointer",
    }
    mp := make(map[int]*SS)
    mp[1] = sp

    //修改 struct 类型的,会报错
    //ms[1].Name = "new struct name"

    mp[1].Name = "new struct name"

    fmt.Printf("ss:%+v\n", ss)

    fmt.Printf("sp:%+v\n", sp)
}

至于性能,没有在实际中测试过,不能下结论。性能和场景有很大关系

  • &struct{}这种,在栈还是堆分配,和struct的大小有关
type smallStruct struct {
    id int
}
type bigStruct struct {
    id [2E7]int64
}

func createStructSmall() {
    _ = &smallStruct{}
}

func createStructBig() {
    _ = &bigStruct{}
}

goos: linux
goarch: amd64
BenchmarkCreateSmallStruct-8       2000000000             0.27 ns/op           0 B/op           0 allocs/op
BenchmarkCreateBigStruct-8              200       9950261 ns/op    160006144 B/op           1 allocs/op
PASS
ok      _/home/singlethread/test/src/map    2.932

还要考虑逃逸分析,可以搜一下

一是存指针修改方便,直接使用map[0]的语法修改即可,不然就只能用中间变量整个struct重新赋值。
二是如果你的struct内容太多,建议map存指针,避免取用的时候反复拷贝。即使map[0]这种取法取出来也只是原struct的拷贝。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题