在 Go 中,map 结构始终是按值传递,但这个值包含指向 map 内部结构的指针(底层是哈希表)。因此,如果您将 map 传递给函数并在函数内部更改内容(添加/删除元素),外部将看到这些更改。slice 的行为也是类似——slice 结构被复制,但数据数组本身没有被复制:slice 包含指向数组的指针、长度和容量。如果在函数内部按索引更改值,原始数组也会更改。但是,如果您在函数中赋值一个新的 slice(例如,重新切片),原始变量则不会改变。
func updateMap(m map[string]int) { m["key"] = 42 // 更改外部可见! } func updateSlice(s []int) { s[0] = 99 // 原始数组被修改 }
为什么在传递 map 和 slice 到函数时,它们在函数内部的更改会反映在“原件”上?
答案: 因为只复制了结构指针,而数据仍然是共享的——任何更改都会影响同一块内存。
故事
在 fintech 项目中,将配置设置的 map 传递给不同的服务,假设本地更改不会影响全局 map。结果,一个服务更改了值,导致其他模块出现 bug,因为它们得到了意外更改的配置。
故事
在分析微服务中,传递了 slice,期望获得独立的副本。但函数内部按索引更改了值,这导致报告中的数据失真,因为原始数组意外被更改。
故事
在游戏服务器中,使用 map 来存储用户会话,并同时将此 map 传递给多个 goroutine。假设每个 goroutine 都在处理自己的副本,但实际上出现了数据竞争和部分会话丢失。