Go语言-映射

Go语言-映射,第1张

目录

前言

1、映射的实现

2、元素赋值

3、查找与遍历

4、元素删除

5、将映射传递给函数


前言

映射是一种数据结构,用于存储一系列无序的键值对,映射基于键来存储。

映射功能强大的地方是,能够基于键快速检索数据。键就像索引一样,指向与该键关联的值。

与 C++、java 不一样,Go 使用映射 (map) 不需要引入任何库。

1、映射的实现

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

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 语法如下:

dict := make(map[string]int)

//创建一个映射时,键的类型string,值的类型int
dict := map[string]string{"name":"zhangsan","address":"beijing"}

//创建一个映射时,键、值类型都是string,并对两个键值进行初始化

映射的键可以是任何值,这个值的类型并不限制,内置类型或者结构体都可以,需要确定这个值可以使用 == 运算符做比较。需要注意的是,切片、函数以及包含切片的结构类型由于是引用类型,均不能作为映射的键。

dict := map[[]string]int{}

//报错:incomparable map key type []string
dict := map[int][]string{}

//切片作为值,不可作为键
2、元素赋值

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

示例:

package main

import "fmt"

//映射赋值
func main() {
	colors := map[string]string{}
	//赋值直接定义键值对,自动添加
	//键名不可以重复,必须唯一
	//
	colors["red"] = "红色"
	colors["bule"] = "蓝色"
	colors["bule"] = "蓝"
	colors["black"] = "黑"
	colors["hei"] = "黑"
	colors[""] = "无色"
	fmt.Println(colors[""])
	fmt.Println(colors["black"])
	fmt.Println(colors)
}

//运行结果为:
无色
黑
map[:无色 black:黑 bule:蓝 hei:黑 red:红色]

与切片类似,通过声明一个未初始化的映射可以创建一个值为nil的映射,nil映射不能用于存储键值对,否则,会产生语言运行时错误。

var colors := map[string]string    //创建一个nil的映射

colors["red"] = "#da133"

运行报错:
panic: assignment to entry in nil map
goroutine 1 [running]:
3、查找与遍历

从映射取值时有两种方式。

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

package main

import "fmt"

//映射赋值
func main() {
	colors := map[string]string{}
	//赋值直接定义键值对,自动添加

	colors["red"] = "红色"
	colors["bule"] = "蓝色"

	//第一种方式获取值并且判断值是否存在
	value, exe := colors["bule"]
	if exe {
		fmt.Println(value)
	} else {
		fmt.Println("不存在")
	}
}

//运行结果为:
蓝色

第二种方式:只返回键对应的值,再判断这个值是否有零值,以此来确定键是否存在。这种方式只能用在映射存储的值都是非零值的情况。

package main

import "fmt"

func main() {
	//第二种方式获取值
	disc := map[string]int{"1": 10, "2": 20, "3": 30}

	value := disc["2"]
	if value != 0 {
		fmt.Println(value)
	} else {
		fmt.Println("不存在")
	}
}

//运行结果为:
20

遍历 map 中所有值。

package main

import "fmt"

func main() {
	//遍历map中所有值
	disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}

	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}
}

//运行结果为:
key=5,value=0
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=0
4、元素删除

内置函数 delete() 用于删除容器内的元素。

删除格式:

delete(myMap,"1234")

//从myMap中删除键位1234的键对时,如果1234这个键不存在,那么就什么都不发生,也不会有任何副作用。
//但是如果传入的map变量是nil,该调用将导致程序抛出异常(panic)。

示例:

package main

import "fmt"

func main() {
	//遍历map中所有值
	disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}

	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}
	//删除元素
	fmt.Println("删除后---------------------------------")
	delete(disc, "2")
	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}
}

//运行结果位:
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=0
key=5,value=0
删除后---------------------------------
key=5,value=0
key=1,value=10
key=3,value=30
key=4,value=0
5、将映射传递给函数

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

package main

import "fmt"

func main() {
	//遍历map中所有值
	disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}

	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}
	//映射传参处理
	fmt.Println("处理后------")
	test(disc)
	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}
}
func test(m map[string]int) {
	m["4"] = 40
}

//运行结果为:
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=0
key=5,value=0
处理后------
key=1,value=10
key=2,value=20
key=3,value=30
key=4,value=40
key=5,value=0

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/990693.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存