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学习总结笔记

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

相关文章
|
16天前
|
Go
go语言常量的类型
【10月更文挑战第20天】
23 2
|
17天前
|
存储 Go
|
18天前
|
Java 编译器 测试技术
go语言避免不必要的内存分配
【10月更文挑战第18天】
26 1
|
19天前
|
存储 算法 Java
Go语言的内存管理机制
【10月更文挑战第25天】Go语言的内存管理机制
21 2
|
2月前
|
存储 Go 索引
Go to Learn Go之映射
Go to Learn Go之映射
36 7
|
2月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
2月前
|
编译器 Linux API
基于类型化 memoryview 让 Numpy 数组和 C 数组共享内存
基于类型化 memoryview 让 Numpy 数组和 C 数组共享内存
36 0
|
2月前
|
存储 Go
Go: struct 结构体类型和指针【学习笔记记录】
本文是Go语言中struct结构体类型和指针的学习笔记,包括结构体的定义、成员访问、使用匿名字段,以及指针变量的声明使用、指针数组定义使用和函数传参修改值的方法。
|
3月前
|
Python
Python变量的作用域_参数类型_传递过程内存分析
理解Python中的变量作用域、参数类型和参数传递过程,对于编写高效和健壮的代码至关重要。正确的应用这些概念,有助于避免程序中的错误和内存泄漏。通过实践和经验积累,可以更好地理解Python的内存模型,并编写出更优质的代码。
34 2
|
3月前
|
存储 缓存 Go
在 Go 中如何复制切片和映射?
【8月更文挑战第31天】
81 0