Go | 一篇学会map

59 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

🎐 放在前面说的话

大家好,我是沥沥樱 👧🏻

本科在读,此为日常捣鼓.

如有不对,请多指教,也欢迎大家来跟我讨论鸭 👏👏👏

还有还有还有很重要的,麻烦大可爱们动动小手,给沥沥樱点颗心心♥,沥沥樱需要鼓励嗷呜~

emmm....之前一直听别人说map map自己也用过,但是并不知道具体是干嘛的,只知道是集合的意思,可能大家会觉得搞笑,这不是基础么?怎么会有搞代码的人不知道呢?没关系,我就是那个人,今天我就来学一下map

Let’s get it!

map

map概念

  • map是一种通过key来获取value的一个数据结构,其底层存储方式为数组,在存储时key不能重复,当key重复时,value进行覆盖,又被称为字段或者关联数组
  • map在程序设计中经常使用,且作为一种最基础的数据结构,很多编程语言本身提供的api都会有实现

声明方式

声明是不会分配内存的,需要用make初始化分配内存,分配内存后才能被赋值和使用

var map变量名 map[key类型]value类型

key 支持类型

  • bool
  • int
  • string
  • channel
  • 指针
  • 接口、结构体、数组等

value 支持类型

和key基本一样,常用的有:

  • string
  • map
  • struct
  • int等数字类型

举例:

var a map[string]int
var b map[int]string
var c map[string]map[string]string

栗子

func main() {
	//map的声明和注意事项
	var a map[string]string
	//在使用map前,需要先make , make的作用就是给map分配数据空间
	a = make(map[string]string, 10)
	a["first"] = "小红"  
	a["second"] = "小米" 
	a["first"] = "沥沥樱" 
	a["fore"] = "小李"   
	fmt.Println(a)
}

打印: map[first:沥沥樱 fore:小李 second:小米]

栗子解说

  • 声明后一定要先make才能使用map
    • 内建函数make分配并且初始化一个类型为切片、映射或者通道的对象
    • func make(Type,size IntegerType) Type
    • 映射:初始分配的创建取决于size,但是产生的映射长度为0.size可以省略,这种情况下就会分配一个小的起始大小
  • 当key重复时,value进行覆盖
  • value是可以重复的
  • k-y存储是无序的
  • make 内置函数项目

map 的两种使用方法

方式一

也就是我们上面用到的,比较常见的一种:

var a map[string]string
a = make(map[string]string,10)

方式二

sex := make(map[string]string)
sex["f1"] = "男孩子"
sex["fm2"] = "女孩子"
fmt.Println(sex)

map类型基本操作方法

go语言的map类型的初始化、添加、修改、删除、获取、自增、遍历、获取所有key到一个切片、按key排序、nil判等、切片类型转换为key、map作为函数参数等基本使用方法,废话不多说,直接用代码描述,直观,简单,易理解!

func main() {
	// map 初始化1
	map1 := make(map[string]bool)
	fmt.Printf("map1 初始化:%v\n", map1)

	//map 初始化2
	map2 := map[string]int{
		"php":   1,
		"mysql": 2,
		"go":    3,
	}
	fmt.Printf("map2 初始化:%v\n", map2)

	//map 初始化3
	var a map[string]string
	//在使用map前,需要先make , make的作用就是给map分配数据空间
	a = make(map[string]string, 10)
	a["first"] = "小红"
	a["second"] = "小米"
	a["first"] = "沥沥樱"
	a["fore"] = "小李"
	fmt.Println(a)

	//map 修改和添加
	map3 := map[string]int{
		"沥沥樱":  19,
		"lisa": 26,
		"北":    18,
	}
	map3["沥沥樱"] = 33 // 存在的key是修改
	map3["小红"] = 6   // 不存在的key是添加
	fmt.Printf("map3 修改和添加:%v\n", map3)

	//map 删除
	map4 := map[string]int{
		"watermelon": 10,
		"pear":       18,
		"orange":     15,
	}
	delete(map4, "orange")
	delete(map4, "banana") // key不存在也没关系
	fmt.Printf("map4 删除:%v\n", map4)

	//map 获取
	map5 := map[string]int{
		"rice":  33,
		"bread": 2,
		"milk":  1,
	}
	rice := map5["rice"] //能取到值 33
	fmt.Printf("map5 获取: rice 能取到值: %d\n", rice)
	juice := map5["juice"] //取不到,默认0值
	fmt.Printf("map5 获取: juice 取不到值,默认0值: %d\n", juice)

	//map 自增
	map6 := map[string]int{
		"yanwang": 1000,
	}
	map6["yanwang"]++
	map6["xiaogui"]++ //默认0值也能自增
	fmt.Printf("map6 自增: %v\n", map6)

	//map 遍历,顺序不确定
	map7 := map[string]int{
		"tiger":    1,
		"elephant": 1,
		"monkey":   20,
		"duck":     60,
	}
	fmt.Print("map7 遍历: ")
	for k, v := range map7 {
		fmt.Printf("键: %s, 值: %d\t", k, v)
	}

	//map 获取所有key到一个切片
	map8 := map[string]int{
		"Monday":    1,
		"Tuesday":   2,
		"Wednesday": 3,
		"Thursday":  4,
		"Friday":    5,
		"Saturday":  6,
		"Sunday":    7,
	}
	weeks := make([]string, 0, len(map8))
	for d, _ := range map8 {
		weeks = append(weeks, d)
	}
	fmt.Printf("map8 键集合: %v\n", weeks)
	// 排序键集合
	sort.Strings(weeks) //sort排序会改变参数
	fmt.Printf("map8 排序后键集合: %v\n", weeks)
	// 输出排序后map
	fmt.Println("map8 排序后遍历:")
	for _, d := range weeks {
		fmt.Printf("%s: %d\t", d, map8[d])
	}
	fmt.Println()

	// map的0值是nil
	var map9 map[string]int
	fmt.Printf("map9 == nil is: %t\n", map9 == nil)
	// nil的map插入元素会异常,先创建再插入
	//map9["insert"] = 10
	map9 = map[string]int{}
	map9["insert"] = 10
	fmt.Printf("map9 nil创建后再插入: %v\n", map9)

	// map 取值可以返回双值
	map10 := map[string]int{
		"January":  1,
		"February": 2,
	}
	fmt.Printf("map10 : %v\n", map10)
	January, ok1 := map10["January"]
	fmt.Printf("map10 取双值,January:%v, ok: %v\n", January, ok1)
	March, ok2 := map10["March"]
	fmt.Printf("map10 取双值,March:%v, ok: %v\n", March, ok2)

	// map 切片类型转换为 K
	var map11 = make(map[string]int)
	var list = []string{"hello"}
	map11[k(list)] = 3
	fmt.Printf("map11 切片类型转换为K: %v\n", map11)

	// map 函数传参
	var map12 = map[string]int{
		"zhang": 15,
	}
	fmt.Printf("map12 原始值:%v\n", map12)
	assign(map12)
	fmt.Printf("map12 函数assign之后值:%v\n", map12)
	modify(map12)
	fmt.Printf("map12 函数modify之后值:%v\n", map12)
}

// 将切片转换为可判等类型
func k(list []string) string {
	return fmt.Sprintf("%q", list)
}

// 通过赋值改变 map, 不起作用
func assign(m map[string]int) {
	m = map[string]int{
		"li": 16,
	}
}

// 通过修改元素改变 map
func modify(m map[string]int) {
	m["li"] = 16
}

打印:
map1 初始化:map[]
map2 初始化:map[go:3 mysql:2 php:1]
map[first:沥沥樱 fore:小李 second:小米]
map3 修改和添加:map[lisa:26 北:18 小红:6 沥沥樱:33]
map4 删除:map[pear:18 watermelon:10]
map5 获取: rice 能取到值: 33
map5 获取: juice 取不到值,默认0值: 0
map6 自增: map[xiaogui:1 yanwang:1001]
map7 遍历: 键: duck, 值: 60 键: tiger, 值: 1 键: elephant, 值: 1 键: monkey, 值: 20 \
map8 键集合: [Monday Tuesday Wednesday Thursday Friday Saturday Sunday]
map8 排序后键集合: [Friday Monday Saturday Sunday Thursday Tuesday Wednesday]
map8 排序后遍历:
Friday: 5 Monday: 1 Saturday: 6 Sunday: 7 Thursday: 4 Tuesday: 2 Wednesday: 3
map9 == nil is: true
map9 nil创建后再插入: map[insert:10]
map10 : map[February:2 January:1]
map10 取双值,January:1, ok: true
map10 取双值,March:0, ok: false
map11 切片类型转换为K: map[["hello"]:3]
map12 原始值:map[zhang:15]
map12 函数assign之后值:map[zhang:15]
map12 函数modify之后值:map[li:16 zhang:15]

🎉 放在后面说的话

以上总结了map的概念、使用,以及map类型的基本操作方法。