Golang通脉之map详情

目录
  • 1、定义
  • 2、基本使用
  • 3、判断键是否存在
  • 4、map的遍历
  • 5、delete()函数删除map元素
  • 6、指定顺序遍历map
  • 7、map类型的切片
  • 8、value为切片类型的map
  • 9、map是引用类型

Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现。

map 是一种无序的键值对的集合。map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值 map 是一种集合,所以可以像迭代数组和切片那样迭代它。不过,map 是无序的,无法决定它的返回顺序,这是因为 map 是使用 hash 表来实现的,Go语言中的map是引用类型,必须初始化才能使用。

使用map过程中需要注意的几点:

  • map是无序的,每次打印出来的map都会不一样,它不能通过index获取,而必须通过key获取
  • map的长度是不固定的,也就是和slice一样,也是一种引用类型
  • 内置的len函数同样适用于map,返回map拥有的key的数量
  • map的key可以是所有可比较的类型,如布尔型、整数型、浮点型、复杂型、字符串型……也可以键。

1、定义

Go语言中 map的定义语法如下:

map[KeyType]ValueType

其中

  • KeyType:表示键的类型。
  • ValueType:表示键对应的值的类型。

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

语法为:

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

其中cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。

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

/* 声明变量,默认 map 是 nil */
var mapVariable map[KeyType]ValueType

/* 使用 make 函数 */
mapVariable = make(map[keyType]ValueType)
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }

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

2、基本使用

map中的数据都是成对出现的:

func main() {
 scoreMap := make(map[string]int, 8)
 scoreMap["张三"] = 90
 scoreMap["小明"] = 100
 fmt.Println(scoreMap)
 fmt.Println(scoreMap["小明"])
 fmt.Printf("type of a:%T\n", scoreMap)
}

输出:

map[小明:100 张三:90]
100
type of a:map[string]int

map也支持在声明的时候填充元素,例如:

func main() {
 userInfo := map[string]string{
  "username": "张三",
  "password": "123456",
 }
 fmt.Println(userInfo) //
}

3、判断键是否存在

Go语言中有个判断map中键是否存在的特殊写法,格式如下:

value, ok := map[key]
func main() {
 /* 创建集合 */
   countryCapitalMap := make(map[string]string)

   /* map 插入 key-value 对,各个国家对应的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 // 如果key存在ok为true,v为对应的值;不存在ok为false,v为值类型的零值
 v, ok := countryCapitalMap["United States"]
 if ok {
  fmt.Println("Capital of United States is", captial)
   }else {
      fmt.Println("Capital of United States is not present")
   }
}

4、map的遍历

Go语言中使用for range遍历map

func main() {
 countryCapitalMap := make(map[string]string)
   /* map 插入 key-value 对,各个国家对应的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 for k, v := range countryCapitalMap {
  fmt.Println(k, v)
 }
}

只想遍历key的时候,可以按下面的写法:

func main() {
 countryCapitalMap := make(map[string]string)
   /* map 插入 key-value 对,各个国家对应的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 for k := range countryCapitalMap {
  fmt.Println(k)
 }
}

注意: 遍历map时的元素顺序与添加键值对的顺序无关。

5、delete()函数删除map元素

使用delete()内建函数从map中删除一组键值对,删除函数不返回任何值,delete()函数的格式如下:

delete(map, key)

其中,

  • map:表示要删除键值对的map
  • key:表示要删除的键值对的键
func main(){
 countryCapitalMap := make(map[string]string)
   /* map 插入 key-value 对,各个国家对应的首都 */
   countryCapitalMap["France"] = "Paris"
   countryCapitalMap["Italy"] = "Rome"
   countryCapitalMap["Japan"] = "Tokyo"
   countryCapitalMap["India"] = "New Delhi"
 delete(countryCapitalMap, "France")//将"France":"Paris"从map中删除
 for k,v := range scoreMap{
  fmt.Println(k, v)
 }
}

6、指定顺序遍历map

func main() {
 rand.Seed(time.Now().UnixNano()) //初始化随机数种子

 var scoreMap = make(map[string]int, 200)

 for i := 0; i < 100; i++ {
  key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
  value := rand.Intn(100)          //生成0~99的随机整数
  scoreMap[key] = value
 }
 //取出map中的所有key存入切片keys
 var keys = make([]string, 0, 200)
 for key := range scoreMap {
  keys = append(keys, key)
 }
 //对切片进行排序
 sort.Strings(keys)
 //按照排序后的key遍历map
 for _, key := range keys {
  fmt.Println(key, scoreMap[key])
 }
}

7、map类型的切片

下面的代码切片中的元素为map类型时的操作:

func main() {
 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]["username"] = "张三"
 mapSlice[0]["password"] = "123456"
 mapSlice[0]["address"] = "深圳"
 for index, value := range mapSlice {
  fmt.Printf("index:%d value:%v\n", index, value)
 }
}

8、value为切片类型的map

下面的代码演示了map中值为切片类型的操作:

func main() {
 var sliceMap = make(map[string][]string, 3)
 fmt.Println(sliceMap)
 fmt.Println("after init")
 key := "中国"
 value, ok := sliceMap[key]
 if !ok {
  value = make([]string, 0, 2)
 }
 value = append(value, "北京", "上海")
 sliceMap[key] = value
 fmt.Println(sliceMap)
}

9、map是引用类型

与切片相似,map是引用类型。当将map分配给一个新变量时,它们都指向相同的内部数据结构。因此,一个的变化会反映另一个:

func main() {
    personSalary := map[string]int{
        "steve": 12000,
        "jamie": 15000,
    }
    personSalary["mike"] = 9000
    fmt.Println("Original person salary", personSalary)
    newPersonSalary := personSalary
    newPersonSalary["mike"] = 18000
    fmt.Println("Person salary changed", personSalary)

}

运行结果:

Original person salary map[steve:12000 jamie:15000 mike:9000] 
Person salary changed map[steve:12000 jamie:15000 mike:18000]

map不能使用操作符进行比较。只能用来检查map是否为空。否则会报错:invalid operation: map1 == map2 (map can only be comparedto nil)

到此这篇关于Golang通脉之map详情的文章就介绍到这了,更多相关Golang map内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Golang 使用Map实现去重与set的功能操作

    假设现在有一个需求 将以下 url 保存起来,要求不重复 www.baidu.com www.sina.com.cn www.hao123.com www.baidu.com www.hao123.com 可以利用 map 的 key 唯一性的问题处理 package main var set = map[string]bool { } func main() { ... url := xxx if set[url] { // 表示集合中已经存在 return } set[url] = true

  • golang 如何获取map所有key的方式

    最佳方式:根据map的长度,新建一个数组,遍历map逐个压入 方法1(效率很高): func getKeys1(m map[int]int) []int { // 数组默认长度为map长度,后面append时,不需要重新申请内存和拷贝,效率很高 j := 0 keys := make([]int, len(m)) for k := range m { keys[j] = k j++ } return keys } 方法2(效率很高): func getKeys2(m map[int]int) [

  • golang判断key是否在map中的代码

    个人常用函数 func IsContain(items []string, item string) bool { for _, eachItem := range items { if eachItem == item { return true } } return false } 使用方法 var word := "my" var sentence := []string{"my","word","in","a

  • golang struct, map, json之间的相互转换

    本文用于记录我在 golang 学习阶段遇到的类型转换问题,针对的是 json .map.struct 之间相互转换的问题,用到的技术 json .mapstructure.reflect 三个类库 公共代码区域 package main import ( "encoding/json" "fmt" "testing" ) type UserInfoVo struct { Id string `json:"id"` UserN

  • 解决Golang map range遍历结果不稳定问题

    闲言少叙,本文主要是想介绍一个Golang开发常见的一个问题.然而,此问题对于初学者来说却经常容易陷入坑中. 问题 我在写一段代码时,使用了Golang的map数据结构,目的是想用map缓存计数结果.简单来说map的键也是整型的,且以递增顺序存储.我的最初想法是,在统计结束后,按照map中存储的键有序输出值.可是,当我运行程序时,结果并不是我想要的,而且有一定概率运行结果不同. 问题代码 func sortByBits(arr []int) []int { var bitmap = make(m

  • Golang 空map和未初始化map的注意事项说明

    可以对未初始化的map进行取值,但取出来的东西是空: var m1 map[string]string fmt.Println(m1["1"]) 不能对未初始化的map进行赋值,这样将会抛出一个异常: panic: assignment to entry in nil map var m1 map[string]string m1["1"] = "1" 通过fmt打印map时,空map和nil map结果是一样的,都为map[].所以,这个时候别

  • golang 实现对Map进行键值自定义排序

    看代码吧~ //自定义结构体,用来自定义排序 type RecentlyUpdateListMapSorter []map[string]interface{} //根据MapSorter.Keys进行倒序排序 func (ms *RecentlyUpdateListMapSorter) SortReverse() { sort.Sort(sort.Reverse(ms)) } //自定义排序方法(Len(),Less(),Swap()) func (ms *RecentlyUpdateList

  • Golang通脉之map详情

    目录 1.定义 2.基本使用 3.判断键是否存在 4.map的遍历 5.delete()函数删除map元素 6.指定顺序遍历map 7.map类型的切片 8.value为切片类型的map 9.map是引用类型 Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现. map 是一种无序的键值对的集合.map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值 map 是一种集合,所以可以像迭代数组和切片那样迭代它.不过,map 是无序的,无法决定它的返回

  • Golang通脉之数据类型详情

    目录 1.标识符与关键字 1.1 标识符 1.2 关键字 2.变量 2.1 什么是变量 2.2 变量类型 2.3 变量声明 3.常量 3.1 iota 4.基本数据类型 4.1 整型 4.2 浮点型 4.3 复数 4.4 布尔值 4.5 字符串 4.6 byte和rune类型 4.7 类型转换 5.运算符 5.1 算数运算符 5.2 关系运算符 5.3 逻辑运算符 5.4 位运算符 5.5 赋值运算符 5.6 运算符优先级 1.标识符与关键字 在了解数据类型之前,先了解一下go的标识符和关键字

  • Golang通脉之方法详情

    目录 方法和接收者 指针类型的接收者 值类型的接收者 方法和函数 任意类型添加方法 方法继承 方法重写 结构体和方法补充 方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数.这种特定类型变量叫做接收者(Receiver).接收者的概念就类似于其他语言中的this或者 self. Go 语言中同时有函数和方法.一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针.所有给定类型的方法属于该类型的方法集 方法只是一个函数,它带有一个特殊

  • Golang通脉方法详情

    目录 方法和接收者 指针类型的接收者 值类型的接收者 方法和函数 任意类型添加方法 方法继承 方法重写 结构体和方法补充 方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数.这种特定类型变量叫做接收者(Receiver).接收者的概念就类似于其他语言中的this或者 self. Go 语言中同时有函数和方法.一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针.所有给定类型的方法属于该类型的方法集 方法只是一个函数,它带有一个特殊

  • Golang通脉之流程控制详情

    目录 1.if else(分支结构) 1.1 if条件判断基本写法 1.2 if条件判断特殊写法 2.for(循环结构) 2.1 无限循环 3.for range(键值循环) 4.switch case 5.goto(跳转到指定标签) 6.break(跳出循环) 7.continue(继续下次循环) 前言: 流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的"经脉". Go语言中最常用的流程控制有if和for,而switch和goto主要是为了简化代码.

  • golang 并发安全Map以及分段锁的实现方法

    涉及概念 并发安全Map 分段锁 sync.Map CAS ( Compare And Swap ) 双检查 分断锁 type SimpleCache struct { mu sync.RWMutex items map[interface{}]*simpleItem } 在日常开发中, 上述这种数据结构肯定不少见,因为golang的原生map是非并发安全的,所以为了保证map的并发安全,最简单的方式就是给map加锁. 之前使用过两个本地内存缓存的开源库, gcache, cache2go,其中

  • Golang通脉之类型定义

    目录 1.自定义类型 2.类型定义 2.1 定义结构体 2.2 定义接口 2.3 定义其他的新类型 2.4 定义函数的类型 3.类型别名 4.类型定义和类型别名的区别 5.非本地类型不能定义方法 6.在结构体成员嵌入时使用别名 1.自定义类型 在Go语言中有一些基本的数据类型,如 string . 整型 . 浮点型 . 布尔 等数据类型, Go语言中可以使用 type 关键字来定义自定义类型. type是Go语法里的重要而且常用的关键字,type绝不只是对应于C/C++中的typedef.搞清楚

  • Golang 高效排序数据详情

    目录 1.介绍 2.切片排序 3.自定义集合排序 4总结 1.介绍 在 Golang 语言项目开发中,经常会遇到数据排序问题.Golang 语言标准库 sort 包,为我们提供了数据排序的功能,我们可以直接使用 sort.Sort() 函数进行数据排序,sort.Sort() 函数底层实现是以快排为主,并根据目标数据的具体情况选择不同的排序算法.本文我们介绍 sort 包排序数据的使用方法. 2.切片排序 在 Golang 语言标准库 sort 包中,sort.Sort() 函数用于数据排序,该

  • Golang文件读写操作详情

    目录 一.概念 二.读取文件操作 2.1 打开和关闭文件 defer 语句 2.2 file.Read() 读取文件 Read 方法定义 ReadAt方法定义 一次性读取 循环读取 2.3 bufio 读取文件 2.4 ioutil 读取文件 效率比较 三.写入文件操作 3.1 os.OpenFile()函数 3.2 Write和WriteString 方式写入 3.3 bufio.NewWriter 3.4 ioutil.WriteFile 四.复制文件 4.1 通过ioutil进行复制 4.

  • Golang实现对map的并发读写的方法示例

    在Golang多协程的情况下使用全局map时,如果不做线程同步,会出现panic的情况. 为了解决这个问题,通常有两种方式: 第一种是最常见的使用互斥锁或者读写锁的方法: 第二种是比较符合Golang特色的方法,启动单个协程对map进行读写,当其他协程需要读写map时,通过channel向这个协程发送信号即可. 写了一个模拟程序对map中的一项进行读或者写,后台一直运行的协程阻塞的接受读写信号,并对map进行操作,但是读操作的时候没想好怎么返回这个值. 后来想到用传引用的方式,定义结构体,第一个

随机推荐