Golang Map类型的使用(增删查改)

 更新时间:2024年05月20日 11:08:57   作者:2021dragon  
在Go中,map是哈希表的引用,是一种key-value数据结构,本文主要介绍了Golang Map类型的使用,具有一定的参考价值,感兴趣的可以了解一下

Map介绍

Map介绍

  • 在Go中,map是哈希表的引用,是一种key-value数据结构。map类型写作map[K]V,其中K和V分别对应key和value的类型。
  • map中所有的key都是相同的类型,所有的value也是相同的类型,但key和value可以是不同的类型,value通常使用自定义类型。
  • map内部需要通过判断两个key是否相等以确保每个键的唯一性,因此key的数据类型必须是可比较,如果key是自定义类型,则要求自定义类型中的所有字段是可比较的。

map的示意图如下:

在这里插入图片描述

map中仅包含一个指向底层哈希表的指针,属于引用类型,当map类型变量进行赋值或传参时,本质就是将map中指向哈希表的指针的值进行拷贝,因此最终两个map变量底层指向的是同一个哈希表,其中一个变量对哈希表修改会影响到另一个map变量。如下:

在这里插入图片描述

Map的定义方式

方式一:make map

在定义map时,可以通过make创建指定初始容量的map。如下:

package main

import (
	"fmt"
	"unsafe"
)

func main() {
	// 方式一:make map
	var m = make(map[string]string, 10)
	fmt.Printf("m = %v\n", m)                     // m = map[]
	fmt.Printf("m len = %v\n", len(m))            // m len = 0
	fmt.Printf("m size = %d\n", unsafe.Sizeof(m)) // m size = 8
}

说明一下:

  • map定义后需要先通过make函数分配内存空间,然后才能使用。make是Go中的内建函数,可以用于分配并初始化一个map,其第一个参数表示map的类型,第二个参数表示初始容量,第二个参数若省略则使用默认的初始容量。
  • 在调用make函数创建map时提供初始容量,以便底层哈希表开辟足够多的哈希桶,这样可以避免后续在插入键值对时哈希表的频繁扩容(重新哈希),从而提高性能。
  • 通过len函数可以获取map中键值对的数量,但无法通过cap函数获取map的容量,map底层的哈希表会自动扩容以适应需要存储的键值对数量。

方式二:指定具体的键值对

在定义map时,也可以直接指定具体的键值对。如下:

package main

import (
	"fmt"
)

func main() {
	// 方式二:指定具体的键值对
	var m = map[string]string{
		"四川省": "川",
		"陕西省": "陕",
		"广东省": "粤",
	}
	fmt.Printf("m = %v\n", m)          // m = map[四川省:川 广东省:粤 陕西省:陕]
	fmt.Printf("m len = %d\n", len(m)) // m len = 3
}

说明一下:

  • 通过指定具体键值对创建map时,Go运行时也会在底层创建对应的哈希表,并将指定的键值对插入到哈希表中。

Map的增删查改

新增和修改Map元素

新增和修改Map元素

Go中通过map名[key] = value的方式在map中新增和修改键值对。如下:

package main

import "fmt"

func main() {
	// 新增和修改Map元素
	var m = map[string]string{
		"四川省": "川",
		"陕西省": "陕",
		"广东省": "粤",
	}
	m["浙江省"] = "浙"                     // 新增
	m["四川省"] = "川~"                    // 修改
	fmt.Printf("m = %v\n", m)          // m = map[四川省:川~ 广东省:粤 浙江省:浙 陕西省:陕]
	fmt.Printf("m len = %d\n", len(m)) // m len = 4
}

说明一下:

  • map中各个键值对的key值不能重复,在以map名[key] = value的方式操作map中的键值对时,如果对应的key值不存在则视为向map中新增键值对,如果对应的key值存在则视为修改map中对应键值对的value。

查找Map元素

查找Map元素

Go中通过map名[key]的方式查找map中的元素。如下:

package main

import "fmt"

func main() {
	// 查找Map元素
	var m = map[string]string{
		"四川省": "川",
		"陕西省": "陕",
		"广东省": "粤",
	}
	var key = "四川省"
	value, ok := m[key] // 查找
	if !ok {
		fmt.Printf("没有key为%s的键值对\n", key)
	} else {
		fmt.Printf("%s的简称为%s\n", key, value) // 四川省的简称为川
	}
}

说明一下:

  • 通过map名[key]的方式访问map中的元素将会得到两个值,如果map中存在对应key值的键值对,那么第一个值则是与key对应的value,第二个值为true;如果map中不存在对应key值的键值对,那么第一个值将是value对应类型的默认值,第二个值为false。
  • 通过map名[key]的方式访问map中的元素时,可以根据得到的第二个值来判断map中是否存在对应key值的键值对,也可以选择只用一个变量来接收其返回值,相当于忽略了它的第二个返回值。

删除Map元素

删除Map元素

Go中通过delete函数删除map中指定key值的键值对。如下:

package main

import "fmt"

func main() {
	// 删除Map元素
	var m = map[string]string{
		"四川省": "川",
		"陕西省": "陕",
		"广东省": "粤",
	}
	delete(m, "广东省") // 删除
	fmt.Printf("m = %v\n", m) // m = map[四川省:川 陕西省:陕]
}

说明一下:

  • delete是Go中的内建函数,用于删除map中指定key值的键值对,如果map中不存在对应的键值对,则delete不进行任何操作。
  • Go中没有提供删除map中所有键值对的方法,如果希望删除map中所有的键值对,可以遍历map中的键值对并逐个进行删除,或者通过make函数重新为当前map分配内存空间,此时原先map底层的哈希表将由GC回收。

遍历Map元素

遍历Map元素

Go中通过for range循环的方式对map元素的遍历。如下:

package main

import "fmt"

func main() {
	// 遍历Map元素
	var m = map[string]string{
		"四川省": "川",
		"陕西省": "陕",
		"广东省": "粤",
	}
	// 遍历map元素
	for key, value := range m {
		fmt.Printf("<key:%s, value:%s>\n", key, value)
	}
}

说明一下:

  • 在for range循环中遍历map时,每次迭代会返回两个值,第一个是当前键值对的key,第二个是当前键值对的value,当遍历结束后会自动退出for range循环。
  • map中的键值对是无序的,每次遍历map得到的键值对序列都是不可预测的。

Map元素排序

Map元素排序

map中的元素是无序的,想要按照key值遍历键值对,可以采用以下方式:

  • 获取map中所有键值对的key,得到keys序列。
  • 根据需求对keys序列进行排序。
  • 遍历keys序列,根据key值访问map中的键值对。

使用案例如下:

package main

import (
	"fmt"
	"sort"
)

func main() {
	// map元素排序
	var m = map[int]string{
		1: "周一",
		7: "周日",
		3: "周三",
		2: "周二",
		5: "周五",
		4: "周四",
		6: "周六",
	}
	// 1、获取map中所有的key
	var keys []int
	for key, _ := range m {
		keys = append(keys, key)
	}
	// 2、对所有的key进行排序
	sort.Ints(keys)
	// 3、遍历有序的key,根据key访问其value
	for _, key := range keys {
		fmt.Printf("<key:%d, value:%s>\n", key, m[key])
	}
}

运行程序后可以看到,输出的键值对信息是按key值排序的。如下:

在这里插入图片描述

说明一下:

  • Ints是sort包中的一个函数,用于对int类型的切片按升序进行排序。
  • sort包中还有对其他类型切片排序的函数,比如Float64s、Strings等。

Map切片

Map切片

如果一个切片中存储元素的数据类型是map,那么我们称之为map切片。如下:

package main

import "fmt"

func AddStudent(students []map[string]string,
	name string, gender string, class string) []map[string]string {
	var student = map[string]string{
		"name":   name,
		"gender": gender,
		"class":  class,
	}
	students = append(students, student)
	return students
}

func main() {
	// map切片
	var students []map[string]string
	students = AddStudent(students, "Alice", "female", "class 2")
	students = AddStudent(students, "Bob", "male", "class 1")
	for i := 0; i < len(students); i++ {
		fmt.Printf("第%d个学生的信息如下:\n", i+1)
		for key, value := range students[i] {
			fmt.Printf("\t%s: %s\n", key, value)
		}
	}
}

上述代码中定义了一个map切片,切片中的每一个map存储着一个学生的信息,我们通过AddStudent函数向map切片中添加了两个学生的信息,并通过遍历切片中的map输出了学生的信息。运行结果如下:

在这里插入图片描述

说明一下:

  • 通过append函数向切片末尾追加元素时,append函数会对切片进行检测,如果该切片底层没有引用任何数组(nil切片),那么会先给切片分配一个底层数组,然后再将元素追加到切片中。
  • 切片是引用类型,传参时采用引用的方式进行传递,函数内部的切片与原始切片底层引用的是同一个数组,函数内对切片的操作会影响到原始切片。但AddStudent函数在添加学生信息到切片后仍需要将追加后的切片返回,并在调用AddStudent函数的地方用原始切片接收返回值,目的是更新原始切片的长度字段和容量字段,否则在遍历切片中的学生信息时仍无法观察到添加的学生信息。

到此这篇关于Golang Map类型的使用(增删查改)的文章就介绍到这了,更多相关Golang Map类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • 谈论Go 什么时候会触发 GC问题

    谈论Go 什么时候会触发 GC问题

    Go 语言作为一门新语言,在早期经常遭到唾弃的就是在垃圾回收(下称:GC)机制中 STW(Stop-The-World)的时间过长。下面文章就对此话题展开,感兴趣的小伙伴可以参考下面文章的内容
    2021-09-09
  • golang API开发过程的中的自动重启方式(基于gin框架)

    golang API开发过程的中的自动重启方式(基于gin框架)

    这篇文章主要介绍了golang API开发过程的中的自动重启方式(基于gin框架),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • golang解析json数据的4种方法总结

    golang解析json数据的4种方法总结

    在日常工作中每一名开发者,不管是前端还是后端,都经常使用 JSON,下面这篇文章主要给大家介绍了关于golang解析json数据的4种方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • Golang中unicode码和中文的互相转换函数使用

    Golang中unicode码和中文的互相转换函数使用

    这篇文章主要为大家介绍了Golang中unicode码和中文的互相转换函数使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • golang socket断点续传大文件的实现方法

    golang socket断点续传大文件的实现方法

    今天小编就为大家分享一篇golang socket断点续传大文件的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-07-07
  • Go 数据库查询与结构体映射的示例详解

    Go 数据库查询与结构体映射的示例详解

    本文主要介绍了如何使用Go语言进行数据库查询并将查询结果映射到结构体中,文章详细讲解了结构体字段导出和db标签的使用方法,并通过示例代码展示了如何正确地进行数据库查询和结果映射
    2024-11-11
  • Golang使用minio替代文件系统的实战教程

    Golang使用minio替代文件系统的实战教程

    本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对象以及设置过期策略等,需要的朋友可以参考下
    2025-01-01
  • GO excelize读取excel进行时间类型转换的示例代码(自动转换)

    GO excelize读取excel进行时间类型转换的示例代码(自动转换)

    我们经常会遇到如何自动识别excel中的时间类型数据并转化成对应的 "Y-m-d H:i:s"类型数据,本文小编给大家介绍了GO excelize读取excel进行时间类型转换的示例代码(自动转换),需要的朋友可以参考下
    2024-10-10
  • 一文教你打造一个简易的Golang日志库

    一文教你打造一个简易的Golang日志库

    这篇文章主要为大家详细介绍了如何使用不超过130行的代码,通过一系列golang的特性,来打造一个简易的golang日志库,感兴趣的小伙伴可以了解一下
    2023-06-06
  • golang实现ping命令的完整代码

    golang实现ping命令的完整代码

    这篇文章给大家介绍了如何使用golang实现ping命令,文中给大家介绍了完整的实现代码,并有详细的图文讲解,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02

最新评论