go语言map映射

GO语言Map映射

GO语言Map 映射

Map 映射 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

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


值的类型 值的数量 值的索引
数组: 相同 固定 下标
切片: 相同 动态 下标
结构体: 不相同 固定 属性名
映射: 相同 动态 key

映射的实现

因为映射也是一个数据集合,所以,也可以使用类似处理数组和切片的方式来迭代映射中的元素。但 映射是无序集合,所以即使以同样的顺序保存键值对,每次迭代映射时,元素的顺序也可能不一样。

无序的原因是映射的本质使用了 散列表

map 在底层使用哈希(hash)来实现的,在C:\Program Files\Go\src\hash\maphash\maphash.go ,map是一个hash数组列表,由一个个bucket 组成

每一个元素都被称为bucket的结构体,每一个bucket 可以保存8个键值对,所有元素被hash算法填入到数组的bucket中,bucket填满后,将通过 一个overflow指针来扩展一个bucket,从而来形成链表,以此来解决hash冲突的问题。map就是一个bucket指针型的一堆数组


定义 Map

可以使用内建函数 make 也可以使用 map 关键字来定义 Map:

//使用make 函数,创建一个映射,键的类型是string,值的类型是int
dict := make(map[string]int)


//创建一个映射,键值类型都是string,并进行初始化
teacher := map[string]string{"zhangsan":"Chinese","lisi":"English"}



//如果仅仅声明map,而不进行 初始化,那么就会创建一个空映射,空映射不能存放键值对.所以
//方法一:
var student map[string]string
student = make(map[string]string) //初始化

//方法二:
var student map[string]string = make(map[string]string)

如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对

映射的 键的可以是任何类型内置类型或者结构体都可以,需要确定这个值可以使用 == 运算符做比较。但是如切片,函数,这种引用类型的可以作为映射的键

映射的 值 可以是任何类型



元素赋值与获取元素值

指定适当的类型键,并给这个键赋一个值就完成了映射的键值对赋值

赋值直接定义键值对,自动添加。键名必须唯一 .如果 键名重复,则会修改之前的值

如果想象获取元素的值,使用键名获取

//赋值
package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "红色"
	colors["blue"] = "蓝色"
	fmt.Println(colors)
  //键名重复,则修改键的值
	colors["red"] = "红"
	fmt.Println(colors)
}


//输出结果:
map[blue:蓝色 red:红色]
map[blue:蓝色 red:红]

//通过键名,获取对应的值
package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "红色"
	colors["blue"] = "蓝色"
	//使用定义的映射,然后加上下标,下标为键名
	fmt.Println(colors["red"])
	fmt.Println(colors["blue"])
}

//输出结果:
红色
蓝色


查找与遍历、

查找

从映射去值时,有两种方式。

第一种方式是:获得值以及一个表达这个值是否存在的标志

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "红色"
	colors["blue"] = "蓝色"

	//value 是red 对应的值。 exists 是布尔类型,判断键是否存在
	value, exists := colors["red"]
	fmt.Println(value, exists)
	
	if exists {
		fmt.Println("键存在")
	}

	//重新赋值value和exists。
	//value 是black 对应的值,如果black不存在,则返回string类型的默认值,即 空
	value, exists = colors["black"]
	fmt.Println(value, exists)
	if !exists {
		fmt.Println("键不存在")
	}
}
红色 true
键存在
 false
键不存在

//输出结果:

第二种方式是,只返回键对应的值,在判断这个值是否为0值(int类型),或者是否为空值(string类型)。以此来判断键是否存在。这种方式只能用在映射存的的值都是非0值或者非空值

package main

import "fmt"

func main() {
   colors := map[string]string{}
   colors["red"] = "红色"
   colors["blue"] = "蓝色"

   //获取red 键对应的值。如果red键不存在,则结果为对应数值类型的默认值。string 类型默认为空
   value := colors["red"]
   //判断这个键是否存在
   if value != "" {
   	fmt.Println("键存在")
   	fmt.Println(value)
   }
}

//输出结果:
键存在
红色

遍历

通过使用range 可以迭代映射里的所有值

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "红色"
	colors["blue"] = "蓝色"

	//使用range 遍历所有信息
	for key, value := range colors {
		fmt.Printf("key:%s,value:%s \n", key, value)
	}
}

//输出结果:
key:red,value:红色 
key:blue,value:蓝色 


delete函数删除集合的元素

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "红色"
	colors["blue"] = "蓝色"
	colors["yellow"] = "黄色"
	colors["green"] = "绿色"
	fmt.Println("删除前:", colors)
	//删除元素
	delete(colors, "red")
	fmt.Println("删除后:", colors)
}

//输出结果:
删除前: map[blue:蓝色 green:绿色 red:红色 yellow:黄色]
删除后: map[blue:蓝色 green:绿色 yellow:黄色]

<br<

将映射传递给函数

在函数键传递映射并不会制造出该映射的副本。当传递映射给函数并对这个映射做了修改时,所有对这个映射的引用都会察觉到这个修改

package main

import "fmt"

func main() {
	colors := map[string]string{}
	colors["red"] = "红色"
	colors["blue"] = "蓝色"
	colors["yellow"] = "黄色"
	colors["green"] = "绿色"
	fmt.Println("修改前:", colors)

	//将映射作为值,传递给函数
	test(colors)
	fmt.Println("修改后:", colors)
}

func test(m map[string]string) {
	m["black"] = "黑色"
}


//输出结果:
修改前: map[blue:蓝色 green:绿色 red:红色 yellow:黄色]
修改后: map[black:黑色 blue:蓝色 green:绿色 red:红色 yellow:黄色]
posted @ 2022-04-04 22:10  知己一语  阅读(68)  评论(0编辑  收藏  举报