Go-映射类型详解(遍历、增删改查、判断相等、内存等)

简介: Go-映射类型详解(遍历、增删改查、判断相等、内存等)

介绍

  • 引用类型
  • Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索value。
  • key 类似于索引,指向数据的值,key必须可以使用==运算符来比较,不能重复。
  • Map 是使用 hash 表来实现的。
  • map自动扩容

声明

方式1

var map 变量名 map[key_type]value_type

代码

var m map[string]string

方式2

make函数

func make(Type, size IntegerType) Type

内建函数make分配并初始化一个类型为切片、映射、或通道的对象。其第一个实参为类型,而非值。make的返回类型与其参数相同,而非指向它的指针。其具体结果取决于具体的类型:


映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个小的起始大小。

map的键必须是可以通过操作符==来比较的数据类型。int、布尔、string、或包含前面的struct、数组等

声明时直接make

var 变量名 = make(map[key_type][value_type])

代码

var m1 = make(map[string]string,5)

初始化

key:value形式,添加到花括号中。

代码

m2 := map[string]string{"野王":"赵云"}

添加/修改

map[key] = value形式,没有会添加,有了会覆盖。

代码

1.  m1["上官"] = "言为心声"
2.  m1["婉儿"] = "字为心画"
3.  m2["野王"] = "老虎"
4.  m2["上单"] = "吕布"

删除

func delete(m map[Type]Type1, key Type)

内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作。

delete(m1,"上官")

清空:重新make,没有其他语言类似clear的函数

查找

m[key]返回值和是否存在(bool类型)

  val,flag := m2["野王"]
  if flag{
    fmt.Println("野王:",val)
  }

内存

查看源码

src->runtime->map.go

// A header for a Go map.
type hmap struct {
  // Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
  // Make sure this stays in sync with the compiler's definition.
  count     int // # live cells == size of map.  Must be first (used by len() builtin)
  flags     uint8
  B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
  noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
  hash0     uint32 // hash seed
  buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
  oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
  nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)
  extra *mapextra // optional fields
}
// A bucket for a Go map.
type bmap struct {
  // tophash generally contains the top byte of the hash value
  // for each key in this bucket. If tophash[0] < minTopHash,
  // tophash[0] is a bucket evacuation state instead.
  tophash [bucketCnt]uint8
  // Followed by bucketCnt keys and then bucketCnt elems.
  // NOTE: packing all the keys together and then all the elems together makes the
  // code a bit more complicated than alternating key/elem/key/elem/... but it allows
  // us to eliminate padding which would be needed for, e.g., map[int64]int8.
  // Followed by an overflow pointer.
}

是哈希表实现,拉链法解决冲突。

遍历

for range

  for key,value := range m2{
    fmt.Println(key,value)
  }

注意:由于是无序的,go的设计者将遍历做了随机化处理,可就是说两次遍历的结果很可能不一样

排序

对key排序,然后遍历

  m2["野王2"] = "赵云"
  m2["野王3"] = "玛玛哈哈"
  m2["上单2"] = "马超"
  keys := []string{}
  for key,_ := range m2{
    keys = append(keys, key)
  }
  sort.Strings(keys)
  fmt.Println("上单和野王排行榜:")
  for _,key := range keys{
    fmt.Println(key,m2[key])
  }

注意:不是线程安全的,如果需要线程安全的,可以使用sync/Map,等到包的那一节会详细展开。

相等

和slice一样,map之间不能使用==直接比较,map可以和nil使用==比较,我们可以使用循环来判断。

  ok := func(m1,m2 map[string]string) bool{
    if len(m1) != len(m2){
      return false
    }
    for k,v := range m1{
      if v2,ok := m2[k]; !ok || v!=v2{
        return false
      }
    }
    return true
  } (m1,m2)
  fmt.Println("m1和m2相等?",ok)

全部代码

package main
import (
  "fmt"
  "sort"
)
func main() {
  //-------------声明---------------
  var m map[string]string
  //----------声明并分配空间------
  var m1 = make(map[string]string,5)
  m2 := map[string]string{"野王":"赵云"}
  //---------添加和修改---------------
  m1["上官"] = "言为心声"
  m1["婉儿"] = "字为心画"
  m2["野王"] = "老虎"
  m2["上单"] = "吕布"
  fmt.Println("m m1 m2:",m,m1,m2)
  //----------删除-------------------
  delete(m1,"上官")
  fmt.Println("m1:",m1)
  //------------查找-------------
  val,flag := m2["野王"]
  if flag{
    fmt.Println("野王:",val)
  }
  //------------遍历-------------
  for key,value := range m2{
    fmt.Println(key,value)
  }
    //------------排序------------
  m2["野王2"] = "赵云"
  m2["野王3"] = "玛玛哈哈"
  m2["上单2"] = "马超"
  keys := []string{}
  for key,_ := range m2{
    keys = append(keys, key)
  }
  sort.Strings(keys)
  fmt.Println("上单和野王排行榜:")
  for _,key := range keys{
    fmt.Println(key,m2[key])
  }
}

截图

2020062310470442.png

注意

  • key必须可以使用==比较,所以,数组是可以作为key的,但切片不行,类似于Python中的tuple和list
  • 向map存数据前需要make或初始化,仅使用var声明的是不行的,仅声明的话,那是nil

参考

更多Go相关内容:Go-Golang学习总结笔记

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。

相关文章
go语言中遍历映射(map)
go语言中遍历映射(map)
427 8
|
9月前
|
弹性计算 定位技术 数据中心
阿里云服务器配置选择方法:付费类型、地域及CPU内存配置全解析
阿里云服务器怎么选?2025最新指南:就近选择地域,降低延迟;长期使用选包年包月,短期灵活选按量付费;企业选2核4G5M仅199元/年,个人选2核2G3M低至99元/年,高性价比爆款推荐,轻松上云。
1080 11
|
9月前
|
Java 编译器 Go
【Golang】(5)Go基础的进阶知识!带你认识迭代器与类型以及声明并使用接口与泛型!
好烦好烦好烦!你是否还在为弄不懂Go中的泛型和接口而烦恼?是否还在苦恼思考迭代器的运行方式和意义?本篇文章将带你了解Go的接口与泛型,还有迭代器的使用,附送类型断言的解释
397 3
|
存储 JSON Go
Go语言之空接口与类型断言
本文介绍了 Go 语言中空接口(`interface{}`)和类型断言的核心概念及其应用。空接口可存储任意类型数据,适用于通用函数、动态数据结构与 JSON 解析等场景;类型断言用于将接口变量还原为具体类型,推荐使用带 `ok` 的写法以避免程序崩溃。此外,文章通过示例讲解了 `type switch` 类型判断与 JSON 处理技巧,并总结了空接口的注意事项,强调滥用可能导致类型安全性降低。内容深入浅出,帮助开发者灵活运用这些特性。
374 15
|
算法 Go
Go语言模拟集合类型-《Go语言实战指南》
在 Go 语言中,虽然没有内建的集合(Set)类型,但可以通过 `map` 实现其功能。常用方式包括 `map[T]bool` 和更节省内存的 `map[T]struct{}`。前者以布尔值表示元素存在性,后者利用零内存开销的空结构体。文章介绍了集合的基本操作(添加、删除、判断、遍历),并通过封装示例展示如何创建自定义 Set 类型。这种实现方式适用于去重、唯一标记及集合运算等场景,简洁高效且易于扩展。
|
存储 JSON JavaScript
[go]byte类型, string 类型, json 类型
本文介绍了Go语言中byte类型的基本概念、特点及用法。byte是8位无符号整数,取值范围为0-255,常用于二进制数据操作,如网络通信和文件读写。文章还详细说明了byte与字符串的转换、遍历byte数据以及与其他类型间的转换。此外,探讨了Go中json.Marshal和json.Unmarshal函数实现[]byte与JSON间的转换,并对比了[]byte与JSON的区别,帮助开发者更好地理解其应用场景与差异。
421 2
|
Go 开发者
Go语言内存共享与扩容机制 -《Go语言实战指南》
本文深入探讨了Go语言中切片的内存共享机制与自动扩容策略。切片作为动态数组的抽象,其底层结构包含指针、长度和容量。多个切片可能共享同一底层数组,修改一个切片可能影响其他切片。当切片容量不足时,`append`会触发扩容,新容量按指数增长以优化性能。为避免共享导致的副作用,可通过`copy`创建独立副本或在函数中使用只读方式处理。最后总结了最佳实践,帮助开发者高效使用切片,写出更优代码。
328 10
|
存储 算法 Go
Go语言实战:错误处理和panic_recover之自定义错误类型
本文深入探讨了Go语言中的错误处理和panic/recover机制,涵盖错误处理的基本概念、自定义错误类型的定义、panic和recover的工作原理及应用场景。通过具体代码示例介绍了如何定义自定义错误类型、检查和处理错误值,并使用panic和recover处理运行时错误。文章还讨论了错误处理在实际开发中的应用,如网络编程、文件操作和并发编程,并推荐了一些学习资源。最后展望了未来Go语言在错误处理方面的优化方向。
248 5
|
存储 Go
go语言中映射
go语言中映射
250 11
go语言for遍历映射(map)
go语言for遍历映射(map)
614 12

热门文章

最新文章