Go学习笔记之map的声明和初始化

map

map 是一种无序的键值对的集合。

map最重要的一点是通过key来快速检索数据,key类似于索引,指向数据的值。

map是一种集合,因此我们可以像迭代数组和切片那样迭代它。不过,map是无序的,我们无法决定它的返回顺序,这是因为map是用哈希表来实现的。

map是引用类型,可以使用如下方式声明:

//[keytype] 和 valuetype 之间允许有空格。
var mapname map[keytype]valuetype

其中:

  • mapname为map的变量名。
  • keytype为键类型。
  • valuetype是键对应的值类型。

注意

在声明的时候不需要知道map的长度,因为map是可以动态增长的,未初始化的map的值是nil,使用函数len()可以获取map中键值对的数目。

下面请看两个例子:

例子1:

package main

import (
	"fmt"
)

func main() {
	//初始化一个没有键值对的map
	map1 := map[int]int{}
	//falsae
	fmt.Println(map1 == nil)
	//未进行初始化
	var map2 map[int]int
	//true
	fmt.Println(map2 == nil)

}

例子2:

package main
import "fmt"
func main() {
    var mapLit map[string]int
    var mapAssigned map[string]int
    //初始化一个含有两个键值对的map
    mapLit = map[string]int{"one": 1, "two": 2}
    mapAssigned = mapLit
    
    mapAssigned["two"] = 3
    fmt.Printf("Map literal at \"one\" is: %d\n", mapLit["one"])
    fmt.Printf("Map assigned at \"two\" is: %d\n", mapLit["two"])
    fmt.Printf("Map literal at \"ten\" is: %d\n", mapLit["ten"])
}

输出结果是什么呢?

输出的结果是

Map literal at "one" is: 1
Map assigned at "two" is: 3
Map literal at "ten" is: 0

因为mapAssigned 是 mapList 的引用,对 mapAssigned 的修改也会影响到 mapList 的值。因此在修改mapAssigned[“two”]为3时,mapList["two]也是3。

map还有另外一种创建方式

make(map[keytype]valuetype,cap)

例如:

map2 := make(map[string]int, 100)

当 map 增长到容量上限的时候,如果再增加新的 key-value,map 的大小会自动加 1,所以出于性能的考虑,对于大的 map 或者会快速扩张的 map,即使只是大概知道容量,也最好先标明。

既然一个 key 只能对应一个 value,而 value 又是一个原始类型,那么如果一个 key 要对应多个值怎么办?

答案是:使用切片

例如,当我们要处理 unix 机器上的所有进程,以父进程(pid 为整形)作为 key,所有的子进程(以所有子进程的 pid 组成的切片)作为 value。

通过将 value 定义为 []int 类型或者其他类型的切片,就可以优雅的解决这个问题,示例代码如下所示:

mp1 := make(map[int][]int)
mp2 := make(map[int]*[]int)

补充:为什么map输出是无序的?

遍历map的时候,取随机数,把桶的遍历顺序随机化。原因是golang底层并没有保证这一点,或许(现在/以后)会有特殊情况出现顺序不固定的情况。担心开发者们误解这一点,golang就特意去打乱了这个顺序,让开发者们知道golang底层不保证map每次遍历都是同一个顺序。

Go的Map本质上是“无序的”

“无序”写入:

  • 正常写入(非哈希冲突写入):是hash到某一个bucket上,而不是按buckets顺序写入。
  • 哈希冲突写入:如果存在hash冲突,会写到同一个bucket上,更有可能写到溢出桶去

扩容导致无序

  • 成倍扩容迫使元素顺序变化,等量扩容并没有改变元素顺序

总结无序原因

  • 无序写入
  • 成倍扩容迫使元素顺序变化

总结

到此这篇关于Go学习笔记之map的声明和初始化的文章就介绍到这了,更多相关Go map的声明和初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

你可能感兴趣的:(Go学习笔记之map的声明和初始化)