备注1:本文旨在介绍Go语言中map这个内置数据结构的引用行为,并用实例来说明如何避免这种引用行为带来的“副作用”。
备注2:文末列出的参考资料均来自GoLang.org官方文档,需翻墙访问。
目前已经清楚,map在内部维护了一个hashmap,那么语法层面的map数据结构是如何与底层的hashmap关联起来的呢?
在Effective Go关于Maps的说明文档中,有这样一句话:
Like slices, maps hold references to an underlying data structure. If you pass a map to a function that changes the contents of the map, the changes will be visible in the caller.
备注2:文末列出的参考资料均来自GoLang.org官方文档,需翻墙访问。
1. map internals
map是go中内置的数据结构,关于其语法规则,可以查看language specification中这里的说明,或者查看Effective Go中关于Maps的说明,此处略过。
map的底层是用hashmap实现的(底层hashmap源码路径为src/pkg/runtime/hashmap.c),部分注释摘出如下:
// This file contains the implementation of Go's map type.
//
// The map is just a hash table. The data is arranged
// into an array of buckets. Each bucket contains up to
// 8 key/value pairs. The low-order bits of the hash are
// used to select a bucket. Each bucket contains a few
// high-order bits of each hash to distinguish the entries
// within a single bucket.
//
// If more than 8 keys hash to a bucket, we chain on
// extra buckets.
//
// When the hashtable grows, we allocate a new array
// of buckets twice as big. Buckets are incrementally
// copied from the old bucket array to the new bucket array.
这段注释除表明map底层确实是hashmap实现的外,还解释了hashmap部分实现细节。此外,源码中还包含遍历map的处理细节以及一个map性
能的小实验,可以查看源码文件了解。目前已经清楚,map在内部维护了一个hashmap,那么语法层面的map数据结构是如何与底层的hashmap关联起来的呢?
在Effective Go关于Maps的说明文档中,有这样一句话:
Like slices, maps hold references to an underlying data structure. If you pass a map to a function that changes the contents of the map, the changes will be visible in the caller.