Go中的字典Map增删改查、排序及其值类型

 更新时间:2024年09月17日 09:52:46   作者:Sunny_Future  
本文详细介绍了Go语言中Map的基本概念、声明初始化、增删改查操作、反转、排序以及如何判断键是否存在等操作,Map是一种基于键值对的无序数据结构,键必须是支持相等运算符的类型,值可以是任意类型,初始化Map时推荐指定容量以提高性能

1、Map 简述

  • 哈希表,引用类型,必须初始化才能使用
  • 一种无序的基于key-value的数据结构的键值对集合
  • 键必须是支持相等运算符 ("=="、"!=") 类型, 如 number、string、 pointer、array、struct,以及对应的 interface
  • 值可以是任意类型,没有限制

2、Map 声明初始化

2.1 Map 声明

声明格式:

var mapName map[keyType] valueType
// 其中:keyType为键类型,valueType为值类型
// valueType 不仅可以是标注数据类型,也可以是自定义数据类型
type personInfo struct {
	ID      string
	Name    string
	Address string
}

var m1 map[string]int
var m2 map[string]personInfo

map类型的变量默认初始值为nil,需要使用make()函数来分配内存。

语法为:

make(map[KeyType] ValueType, [cap])

其中cap表示map的容量,该参数是可选参数,但推荐在初始化map的时候就为其指定一个合适的容量。

2.1 Map 初始化

2.1.1 声明时填充元素,直接初始化创建

package main

import (
	"fmt"
)

var m1 map[string]float32 = map[string]float32{"Go":1, "Goland": 8.8}

func main() {
	
	// 短命名
	m2 := map[string]float32 {"Go": 1, "python": 6.6}
	m3 := map[int]struct {
		name string
		age  int
	}{
		1: {"user01", 10},  // 可省略元素类型。
		2: {"user02", 20},
	}
	fmt.Printf("全局变量 map m1 : %v\n", m1)   // 全局变量 map m1 : map[Go:1 Goland:8.8]
	fmt.Printf("局部变量 map m2 : %v\n", m2)   // 局部变量 map m2 : map[Go:1 python:6.6]
	fmt.Printf("局部变量 map m3 : %v\n", m3)   // 局部变量 map m3 : map[1:{user01 10} 2:{user02 20}]
}

2.1.2 make () 内置函数 创建

在初始化map的时候就为其指定一个合适的容量,有助于提升性能。

毕竟先申请一大块内存,可避免后续操作时频繁自动扩容。

	// 创建了一个键类型为string,值类型为int的map
	testMap := make(map[string]int)
	testMap["apollo"] = 11
	fmt.Printf("局部变量 map testMap : %v\n", testMap)
	// 局部变量 map testMap : map[apollo:11]

	// 推荐!可以选择是否在创建时指定该scoreMap的初始存储能力,如创建了一个初始存储能力为8的map
	scoreMap := make(map[string]int, 8)
	scoreMap["alex"] = 88
	fmt.Printf("局部变量 map scoreMap : %v\n", scoreMap)
	// 局部变量 map scoreMap : map[alex:88]

3、Map 增删改查 操作

预先声明初始化字典testMap:

	testMap := map[string]string{
		"name": "alex",
		"address": "beijing",
		"age": "18",
	}

3.1 查找

在 Go 中,要从字典中查找指定键时,会返回两个值:

value, ok := map[key]
  • 第一个是真正返回 键key的值value,若key不存在则value为零值 nil
  • 第二个则是否找到的标识,为布尔值类型,查找成功,返回 true,否则返回 false

通常以下面的代码形式实现:

	// 如果key存在ok为true,value为对应的值;不存在ok为false,value为值类型的零值	
	value, ok := testMap["name"]
	if ok{  // 找到 则 ok 为 true
		fmt.Println(value)  // alex
	}else {
		fmt.Println("not found")
	}

亦可 简写:

	if val,ok := testMap["name"]; ok{
		fmt.Println(val)  // alex
	}
	if val,ok := testMap["name01"]; !ok{
		fmt.Println(val)  // val为nil
	}

3.2 插入

直接赋值键值对即可:

	testMap["tel"] = "00700"
	fmt.Println(testMap)  // map[address:beijing age:18 name:alex tel:00700]

3.3 更新

有则新增,无则改之~

	testMap["tel"] = "9888"
	fmt.Println(testMap)  // map[address:beijing age:18 name:alex tel:9888]

3.4 删除

Go内置函数 delete(),用于删除Map容器内的元素,不存在也不会报错!

	fmt.Println(testMap)          // map[address:beijing age:18 name:alex tel:9888]
	delete(testMap, "job")        // 不存在,也不会报错,即不执行任何动作
	delete(testMap, "tel") // 键存在,即删除,无返回值
	fmt.Println(testMap)          // map[address:beijing age:18 name:alex]

3.5 长度

内置函数 len() ,求键值对 元素个数

	fmt.Println(testMap)  // map[address:beijing age:18 name:alex]
	fmt.Println(len(testMap))  // 3

4、Map 反转,key-value 对调

交换字典的键和值,初始化另外一个map,把key、value互换即可:

	fmt.Println(testMap)  // map[address:beijing age:18 name:alex]
	revMap := make(map[string]string, 8)
	for k,v := range testMap{
		revMap[v] = k
	}
	fmt.Println(revMap) // map[18:age alex:name beijing:address]

5、Map 排序

Go 的字典Map是一个无序集合,可以通过分别为字典的键和值创建切片,然后通过对切片进行排序来实现。

值得注意的是:遍历字典也是无序的!

5.1 按照 键key 进行排序

先获取所有key,把key进行排序,再按照排序好的key,进行遍历。

	sortMap := map[string]int{"pony": 80, "barry": 100, "eva": 88}
	sortSlice := make([]string, 0)  // 初始化 长度 为0 ~~~
	for k,_ := range sortMap{
		sortSlice = append(sortSlice, k)
	}
	fmt.Printf("keySlice:%v\n", sortSlice)  // keySlice:[pony barry eva]
	sort.Strings(sortSlice)   // string 类型排序
	fmt.Printf("sorted keySlice:%v\n", sortSlice) // sorted keySlice:[barry eva pony]
	for _, k := range sortSlice{
		fmt.Println(k, sortMap[k])
		// barry 100
		// eva 88
		// pony 80
	}

5.2 按照 值 value 进行排序

先获取所有value,把value进行排序,反转map,再按照排序好的value,进行遍历 反转map。

	sortMap := map[string]int{"pony": 80, "barry": 100, "eva": 88}
	sortSlice := make([]int, 0)  // 初始化 长度 为0 ~~~
	for _, v := range sortMap{
		sortSlice = append(sortSlice, v)
	}
	fmt.Printf("keySlice:%v\n", sortSlice)  // keySlice:[100 88 80]
	sort.Ints(sortSlice)    // int类型 排序
	fmt.Printf("sorted keySlice:%v\n", sortSlice) // sorted keySlice:[80 88 100]

	// 反转 sortMap
	revMap := make(map[int]string, 3)
	for k,v := range sortMap{
		revMap[v] = k
	}

	// 根据 排序好的值,遍历反转的 map
	for _, v := range sortSlice{
		fmt.Println(v, revMap[v])
		// 80 pony
		// 88 eva
		// 100 barry
	}
	// 结果:按照键值对应数字大小进行升序排序的结果

6、Map 判断某个键是否存在

判断 某个 键是否存在,通常用以下格式:

	fmt.Println(testMap)          // map[address:beijing age:18 name:alex]
	isExistKey := "key0"
	if val, ok := testMap[isExistKey]; !ok {
		fmt.Printf("键%v不存在", isExistKey)    // 键key0不存在
	}else{
		fmt.Printf("键%v的值为:%v", isExistKey, val)
	}

7、元素 为 Map 的切片

  • 没有对切片中的map元素进行初始化,即:[{key01:val01 key02:val02}]
	mapSlice := make([]map[string]string, 0)  // 元素为map的slice,初始长度为0
	fmt.Println(mapSlice) // []
	mapSlice = append(mapSlice, map[string]string{
		"name": "alex",
		"address": "beijing",
	})
	fmt.Println(mapSlice) // [map[address:beijing name:alex]]
  • 对切片中的map元素进行初始化,即:[{key01:val01 key02:valo2} {} {} {}]
	var mapSlice = make([]map[string]string, 3)
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
	fmt.Println("after init")
	// 对切片中的map元素进行初始化
	mapSlice[0] = make(map[string]string, 10)
	mapSlice[0]["name"] = "王五"
	mapSlice[0]["password"] = "123456"
	mapSlice[0]["address"] = "红旗大街"
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}

输出:

index:0 value:map[]
index:1 value:map[]
index:2 value:map[]
after init
index:0 value:map[address:红旗大街 name:王五 password:123456]
index:1 value:map[]
index:2 value:map[]
[map[address:红旗大街 name:王五 password:123456] map[] map[]]

8、值 为 Slice 的 Map

map中值为切片类型,即 { key01: [ elem01 elem02] key02:[]}

	sliceMap := make(map[string][]string, 3)
	fmt.Println(sliceMap) // map[]
	key01 := "names"
	value,ok := sliceMap[key01]
	if !ok{
		value = make([] string, 0, 2)
	}
	value = append(value,"tencent","baidu")
	sliceMap[key01] = value
	fmt.Println(sliceMap)  // map[names:[tencent baidu]]

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • golang string、int、int64 float 互相转换方式

    golang string、int、int64 float 互相转换方式

    这篇文章主要介绍了golang string、int、int64 float 互相转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Go中并发控制的实现方式总结

    Go中并发控制的实现方式总结

    在Go实际开发中,并发安全是老生常谈的事情,在并发下,goroutine之间的存在数据资源等方面的竞争,为了保证数据一致性、防止死锁等问题的出现,在并发中需要使用一些方式来实现并发控制,本文给大家总结了几种实现方式,需要的朋友可以参考下
    2023-12-12
  • Golang桥接模式讲解和代码示例

    Golang桥接模式讲解和代码示例

    桥接是一种结构型设计模式,可将业务逻辑或一个大类拆分为不同的层次结构,从而能独立地进行开发,本文将通过代码示例详细给大家介绍一下Golang桥接模式,需要的朋友可以参考下
    2023-06-06
  • Go语言开发前后端不分离项目详解

    Go语言开发前后端不分离项目详解

    这篇文章主要为大家介绍了Go语言开发前后端不分离项目详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • Go项目与Docker结合实现高效部署深入探究

    Go项目与Docker结合实现高效部署深入探究

    在现代软件开发中,使用Docker部署应用程序已经成为一种标准实践,本文将深入探讨如何将Go项目与Docker结合,实现高效、可靠的部署过程,通过详细的步骤和丰富的示例,你将能够迅速掌握这一流程
    2023-12-12
  • GoLand编写 TCP 端口扫描器的详细过程

    GoLand编写 TCP 端口扫描器的详细过程

    TCP,也就是传输控制协议(Transmission Control Protocol),这篇文章主要介绍了Go语言(Golang)编写 TCP 端口扫描器,需要的朋友可以参考下
    2023-05-05
  • golang进行xml文件解析的操作方法

    golang进行xml文件解析的操作方法

    本文介绍了Go语言中解析XML文件的几种方法:小文件解析、大文件流式解析和复杂结构解析,对于小文件,使用标准库中的encoding/xml包;对于大文件,采用流式解析以避免内存溢出,对于复杂结构的XML文件,推荐使用第三方库github.com/beevik/etree
    2024-11-11
  • golang敏感词过滤的实现

    golang敏感词过滤的实现

    本文主要介绍了golang敏感词过滤的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • Go语言生成素数的方法

    Go语言生成素数的方法

    这篇文章主要介绍了Go语言生成素数的方法,实例分析了Go语言生成素数的技巧,需要的朋友可以参考下
    2015-03-03
  • 使用go读取gzip格式的压缩包的操作

    使用go读取gzip格式的压缩包的操作

    这篇文章主要介绍了使用go读取gzip格式的压缩包的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12

最新评论