写在前面
嗯,学习go,所以有了这篇文章博文内容为《go语言实战》读书笔记之一主要涉及映射相关知识
你要爱就要像一个痴情的恋人那样去爱,像一个忘死的梦者那样去爱,视他人之疑目如盏盏鬼火,大胆去走你的夜路。——史铁生《病隙碎笔》
映射的内部实现和基础功能
映射是一种数据结构,是用于存储一系列无序的键值对。类比java里的map,python里的字典,可以理解为以哈希值做索引,期望索引可以在一定的连续内存范围内的类似数组的数据结构。
映射里基于键来存储值。映射功能强大的地方是,能够基于键快速检索数据。键就像索引一样,指向与该键关联的值。
内部实现
映射是一个集合,可以使用类似处理数组和切片的方式迭代映射中的元素。但映射是无序的集合,无序的原因是映射的实现使用了散列表.
映射的散列表包含一组桶。
在存储、删除或者查找键值对的时候,所有操作都要先选择一个桶。把操作映射时指定的键传给映射的散列函数,就能选中对应的桶。
这个散列函数的目的是生成一个索引,这个索引最终将键值对分布到所有可用的桶里。对 go 语言的映射来说,生成的散列键的一部分,具体来说是低位(lob),被用来选择桶。
桶的内部实现。映射使用两个数据结构来存储数据,
第一个是数组,内部存储用于选择桶的散列键的高八位值。用于区分每个键值对要存在桶里的那一项。第二个是字节数组,用于存储键值对。该字节数组先依次存储了这个桶里所有的键,之后依次存储了这个桶里所有的值。实现这种键值对的存储方式目的在于减少每个桶所需的内存。
映射存储的增加,索引分布越均匀,访问键值对的速度就越快,随着映射存储的增加,索引分布越均匀,访问键值对的速度就越快。映射通过合理数量的桶来平衡键值对的分布
创建和初始化
go 语言中有很多种方法可以创建并初始化映射,可以使用内置的make 函数,也可以使用映射字面量。
package main import ( "fmt" ) func main() { // 创建一个映射,键的类型是 string,值的类型是 int dict := make(map[string]int) // 创建一个映射,键和值的类型都是 string // 使用两个键值对初始化映射 dict_ := map[string]string{"red": "#da1337", "orange": "#e95a22"} fmt.println(dict) fmt.print(dict_) } ====== map[] map[orange:#e95a22 red:#da1337]
创建映射时,更常用的方法是使用映射字面量。映射的初始长度会根据初始化时指定的键值对的数量来确定。
映射的键可以是任何值。这个值的类型可以是内置的类型,也可以是结构类型,只要这个值可以使用==运算符做比较
切片、函数以及包含切片的结构类型由于具有引用语义,不能作为映射的键,使用这些类型会造成编译错误
package main import ( "fmt" ) func main() { // 创建一个映射,使用字符串切片作为映射的键 dict := map[[]string]int{} fmt.println(dict) } ==== [running] go run "d:golandprojectscode-masterdemohello.go" # command-line-arguments demohello.go:10:45: duplicate key "red" in map literal previous key at demohello.go:10:28 [done] exited with code=2 in 0.902 seconds
声明一个存储字符串切片的映射
// 创建一个映射,使用字符串切片作为值 dict := map[int][]string{}
使用映射
键值对赋值给映射,是通过指定适当类型的键并给这个键赋一个值来完成的
为映射赋值
// 创建一个空映射,用来存储颜色以及颜色对应的十六进制代码 colors := map[string]string{} // 将 red 的代码加入到映射 colors["red"] = "#da1337"
可以通过声明一个未初始化的映射来创建一个值为nil的映射,不能用于存储键值对.
// 创建一个空映射,用来存储颜色以及颜色对应的十六进制代码 colors := map[string]string{} // 将 red 的代码加入到映射 colors["red"] = "#da1337"
从映射取值时有两个选择:
第一个选择是,可以同时获得值,以及一个表示这个键是否存在的标志,
从映射获取值并判断键是否存在
// 获取键 blue 对应的值 value := colors["blue"] // 这个键存在吗? if value != "" { fmt.println(value) }
另一个选择是,只返回键对应的值,然后通过判断这个值是不是零值来确定键是否存在
从映射获取值,并通过该值判断键是否存在
// 获取键 blue 对应的值 value := colors["blue"] // 这个键存在吗? if value != "" { fmt.println(value) }
在go语言里,通过键来索引映射时,即便这个键不存在也总会返回一个值。在这种情况下,返回的是该值对应的类型的零值
迭代映射里的所有值和迭代数组或切片一样,使用关键字 range
使用range 迭代映射
// 创建一个映射,存储颜色以及颜色对应的十六进制代码colors := map[string]string{<!--{c}%3c!%2d%2d%20%2d%2d%3e-->"aliceblue": "#f0f8ff","coral": "#ff7f50","darkgray": "#a9a9a9","forestgreen": "#228b22",}// 显示映射里的所有颜色for key, value := range colors {<!--{c}%3c!%2d%2d%20%2d%2d%3e-->fmt.printf("key: %s value: %sn", key, value)}// 创建一个映射,存储颜色以及颜色对应的十六进制代码 colors := map[string]string{ "aliceblue": "#f0f8ff", "coral": "#ff7f50", "darkgray": "#a9a9a9", "forestgreen": "#228b22", } // 显示映射里的所有颜色 for key, value := range colors { fmt.printf("key: %s value: %sn", key, value) }
想把一个键值对从映射里删除,就使用内置的delete 函数
从映射中删除一项
// 删除键为 coral 的键值对delete(colors, "coral")// 显示映射里的所有颜色for key, value := range colors {<!--{c}%3c!%2d%2d%20%2d%2d%3e-->fmt.printf("key: %s value: %sn", key, value)}// 删除键为 coral 的键值对 delete(colors, "coral") // 显示映射里的所有颜色 for key, value := range colors { fmt.printf("key: %s value: %sn", key, value) }
在函数间传递映射
在函数间传递映射并不会制造出该映射的一个副本。实际上,当传递映射给一个函数,并对这个映射做了修改时,所有对这个映射的引用都会察觉到这个修改,这个特性和切片类似,保证可以用很小的成本来复制映射
package mainimport ("fmt")func main() {<!--{c}%3c!%2d%2d%20%2d%2d%3e-->// 创建一个映射,存储颜色以及颜色对应的十六进制代码colors := map[string]string{<!--{c}%3c!%2d%2d%20%2d%2d%3e-->"aliceblue": "#f0f8ff","coral": "#ff7f50","darkgray": "#a9a9a9","forestgreen": "#228b22",}// 显示映射里的所有颜色for key, value := range colors {<!--{c}%3c!%2d%2d%20%2d%2d%3e-->fmt.printf("key: %s value: %sn", key, value)}fmt.println("调用函数来移除指定的键")// 调用函数来移除指定的键removecolor(colors, "coral")// 显示映射里的所有颜色for key, value := range colors {<!--{c}%3c!%2d%2d%20%2d%2d%3e-->fmt.printf("key: %s value: %sn", key, value)}}// removecolor 将指定映射里的键删除func removecolor(colors map[string]string, key string) {<!--{c}%3c!%2d%2d%20%2d%2d%3e-->delete(colors, key)}package main import ( "fmt" ) func main() { // 创建一个映射,存储颜色以及颜色对应的十六进制代码 colors := map[string]string{ "aliceblue": "#f0f8ff", "coral": "#ff7f50", "darkgray": "#a9a9a9", "forestgreen": "#228b22", } // 显示映射里的所有颜色 for key, value := range colors { fmt.printf("key: %s value: %sn", key, value) } fmt.println("调用函数来移除指定的键") // 调用函数来移除指定的键 removecolor(colors, "coral") // 显示映射里的所有颜色 for key, value := range colors { fmt.printf("key: %s value: %sn", key, value) } } // removecolor 将指定映射里的键删除 func removecolor(colors map[string]string, key string) { delete(colors, key) }
[running] go run "d:golandprojectscode-masterdemohello.go" key: coral value: #ff7f50 key: darkgray value: #a9a9a9 key: forestgreen value: #228b22 key: aliceblue value: #f0f8ff 调用函数来移除指定的键 key: aliceblue value: #f0f8ff key: darkgray value: #a9a9a9 key: forestgreen value: #228b22 [done] exited with code=0 in 1.419 seconds
映射的增长没有容量或者任何限制。同时内置函数 len可以用来获取切片或者映射的长度。但是内置函数 cap只能用于切片。
以上就是go语言映射内部实现及基础功能实战的详细内容,更多关于go语言映射内部实现和基础功能的资料请关注<计算机技术网(www.ctvol.com)!!>其它相关文章!
需要了解更多python教程分享Go语言映射内部实现及基础功能实战,都可以关注python教程分享栏目—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/pythontutorial/1067895.html