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

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

相关文章
|
23天前
|
存储 编译器 C语言
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)一
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)一
24 2
|
1天前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
6 0
|
1天前
|
监控 Linux
深入了解Linux的pmap命令:进程内存映射的利器
`pmap`是Linux下分析进程内存映射的工具,显示内存区域、权限、大小等信息。通过`/proc/[pid]/maps`获取数据,特点包括详细、实时和灵活。参数如`-x`显示扩展信息,`-d`显示设备。示例:`pmap -x 1234`查看进程1234的映射。注意权限、实时性和准确性。结合其他工具定期监控,排查内存问题。
|
4天前
|
Go
go反射获取变量类型、值、结构体成员、结构体方法
go反射获取变量类型、值、结构体成员、结构体方法
7 0
|
1月前
|
Java
<Java SE> 5道递归计算,创建数组,数组遍历,JVM内存分配...
<Java SE> 5道递归计算,创建数组,数组遍历,JVM内存分配
40 2
|
18天前
|
JSON Go 数据格式
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(4)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
18天前
|
Java 编译器 Go
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(3)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
18天前
|
存储 安全 Go
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(2)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
18天前
|
Java Go 索引
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(1)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
23天前
|
存储 编译器 C语言
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)二
C语言学习记录——数据的存储(数据类型、类型的基本归类、整型在内存中的存储、大小端介绍、浮点型在内存中的存储)二
16 0