Arthur's Blog
Toggle navigation
Arthur's Blog
首页
Go语言四十二章经
PHP内核
Redis教程
Go教程
人人都是产品经理
标签
归档
关于
《Go语言四十二章经》第十三章 字典(Map)
Go语言四十二章经
2021-01-27 10:09:44
25
0
0
admin
Go语言四十二章经
# <center>《Go语言四十二章经》第十三章 字典(Map)</center> 作者:李骁 ## 13.1 字典(Map) **map 是引用类型**,可以使用如下声明: ```Go var map1 map[keytype]valuetype var map1 map[string]int ``` ([keytype] 和 valuetype 之间允许有空格,但是 Gofmt 移除了空格) 在声明的时候不需要知道 map 的长度,map 是可以动态增长的。 未初始化的 map 的值是 nil。 key 可以是任意可以用 == 或者 != 操作符比较的类型,比如 string、int、float。所以数组、切片和结构体不能作为 key (译者注:含有数组切片的结构体不能作为 key,只包含内建类型的 struct 是可以作为 key 的),但是指针和接口类型可以。如果要用结构体作为 key 可以提供 Key() 和 Hash() 方法,这样可以通过结构体的域计算出唯一的数字或者字符串的 key。 value 可以是任意类型的;通过使用空接口类型,我们可以存储任意值,但是使用这种类型作为值时需要先做一次类型断言。map 也可以用函数作为自己的值,这样就可以用来做分支结构:key 用来选择要执行的函数。 map 传递给函数的代价很小:在 32 位机器上占 4 个字节,64 位机器上占 8 个字节,无论实际上存储了多少数据。 **通过 key 在 map 中寻找值是很快的,比线性查找快得多,但是仍然比从数组和切片的索引中直接读取要慢 100 倍;所以如果你很在乎性能的话还是建议用切片来解决问题。** map 可以用 {key1: val1, key2: val2} 的描述方法来初始化,就像数组和结构体一样。 map 是 引用类型 的: 内存用 make 方法来分配。 map 的初始化: ```Go var map1 = make(map[keytype]valuetype) ``` map 容量: 和数组不同,map 可以根据新增的 key-value 对动态的伸缩,因此它不存在固定长度或者最大限制。但是你也可以选择标明 map 的初始容量 capacity,就像这样:make(map[keytype]valuetype,cap)。 例如: ```Go map2 := make(map[string]float32, 100) ``` 当 map 增长到容量上限的时候,如果再增加新的 key-value 对,map 的大小会自动加 1。所以出于性能的考虑,对于大的 map 或者会快速扩张的 map,即使只是大概知道容量,也最好先标明。 在一个 nil 的slice中添加元素是没问题的,但对一个map做同样的事将会生成一个运行时的panic。 ```Go Works: package main func main() { var s []int s = append(s, 1) } Fails: package main func main() { var m map[string]int m["one"] = 1 // 错误 } ``` map的key访问,val1, isPresent := map1[key1] 或者 val1 = map1[key1] 的方法获取 key1 对应的值 val1。 一般判断是否某个key存在,不使用值判断,而使用下面的方式: ```Go if _, ok := x["two"]; !ok { fmt.Println("no entry") } ``` **用切片作为 map 的值** 既然一个 key 只能对应一个 value,而 value 又是一个原始类型,那么如果一个 key 要对应多个值怎么办?例如,当我们要处理unix机器上的所有进程,以父进程(pid 为整形)作为 key,所有的子进程(以所有子进程的 pid 组成的切片)作为 value。通过将 value 定义为 []int 类型或者其他类型的切片,就可以优雅的解决这个问题。 这里有一些定义 map 的例子: ```Go // 声明但未初始化map,此时是map的零值状态 map1 := make(map[string]string, 5) map2 := make(map[string]string) // 创建了初始化了一个空的的map,这个时候没有任何元素 map3 := map[string]string{} // map中有三个值 map4 := map[string]string{"a": "1", "b": "2", "c": "3"} ``` 从 map1 中删除 key1: 直接 delete(map1, key1) 就可以。如果 key1 不存在,该操作不会产生错误。 ```Go Delete(map4, "a") ``` map 默认是无序的,不管是按照 key 还是按照 value 默认都不排序。 如果你想为 map 排序,需要将 key(或者 value)拷贝到一个切片,再对切片排序(使用 sort 包)。 ## 13.2 "range"语句中更新引用元素的值 在"range"语句中生成的数据的值是真实集合元素的拷贝。它们不是原有元素的引用。 这意味着更新这些值将不会修改原来的数据。同时也意味着使用这些值的地址将不会得到原有数据的指针。 ```Go package main import "fmt" func main() { data := []int{1, 2, 3} for _, v := range data { v *= 10 // 通常数据项不会改变 } fmt.Println("data:", data) // 程序输出: [1 2 3] } ``` 如果你需要更新原有集合中的数据,使用索引操作符来获得数据。 ```Go package main import "fmt" func main() { data := []int{1, 2, 3} for i, _ := range data { data[i] *= 10 } fmt.Println("data:", data) // 程序输出 data: [10 20 30] } ``` >本书《Go语言四十二章经》内容在github上同步地址:https://github.com/ffhelicopter/Go42 >本书《Go语言四十二章经》内容在简书同步地址: https://www.jianshu.com/nb/29056963 > >虽然本书中例子都经过实际运行,但难免出现错误和不足之处,烦请您指出;如有建议也欢迎交流。 >联系邮箱:roteman@163.com
上一篇:
Go语言四十二章经
下一篇:
《Go语言四十二章经》第四十二章 WEB框架(Gin)
0
喜欢
25
微博
微信
腾讯微博
QQ空间
人人网
提交
登录
后评论.
没有帐号?
现在注册.
0
评论
More...
Table of content
没有帐号? 现在注册.