当前位置: 首页 > 工具软件 > go-spacemesh > 使用案例 >

【Go】(六)Go基础 -- Map

云瑞
2023-12-01

Map

  • Map是一个拥有key value对的元素的无序集合,key的值是唯一的
  • Go里面的Map就是Hash Table的引用,是引用类型,类似Pointer和Slice

一、声明和初始化

// 这样初始化默认是一个nil类型,没有引用任何散列表
var m map[string]int

fmt.Println(m == nil) // true

// 这样赋值就会出错
m["a"] = 1

// 初始化的时候,使用make
m = make(map[string]int)
fmt.Println(m == nil) // false

// 这种方式跟make的效果一样
m := map[string]int{}

// 可以初始化有默认值的map
commits := map[string]int{
    "rsc": 3711,
    "r":   2138,
    "gri": 1908,
    "adg": 912,
}

  • map的key需要是同一数据类型,map的value也需要是同一数据类型
  • Key是任何可比较类型的值(就是指可以用 == != < > <= >= 这些符号进行比较的值)
    • boolean, numeric, string
    • pointer,
    • channel,
    • interface types
    • structs or arrays that contain only those types.
  • Key类型不可以是以下的值
    • map
    • list
    • slices
    • functions
  • Value是任何类型的值

二、使用

2.1.基本使用

// set and get
m["a"] = 66
i := m["a"]

// 如果key不存在,则返回value所属类型的默认值
// 比如int就是0, string就是空字符串
// 以下j == 0
j := m["b"]

// move entry, delete成功或者失败都不返回任何值
delete(m, "b")

// 获取map的长度
n := len(m)

// 测试一个key是否存在
// 如果不存在,i==0,ok==false
i, ok := m["b"]
// 仅仅检测key有没有,使用如下方式
_, ok := m["b"]


// 迭代
for key, value := range m {
    fmt.Println("Key:", key, "Value:", value)
}


// 编译错误,map元素不是一个变量,不能取地址
// 原因是map的增长可能会导致已有的元素被重新散列到新的存储位置,这样地址就会变
_ = &m["a"] 


2.2.顺序迭代

map的迭代是无序的,如果需要顺序迭代,要自己实现

import "sort"

var m map[int]string
var keys []int
for k := range m {
    keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
    fmt.Println("Key:", k, "Value:", m[k])
}

因为已经确定了m的长度,所以初始化keys slice的时候,直接指定长度会更加高效

keys := make([]int, 0, len(m))

2.3.判断两个map是否相同

不能直接判断两个map是否相同,需要自己实现


func compareMapEqual (x, y map[string]int) bool {
	if len(x) != len(y):
		return false
	for k, xv := range(x){
		if yv, ok := y[k]; !ok || xv != yv{
			return false
		}
	}
	return true
}

2.4.用map实现set

https://juejin.cn/post/6844903857101733902
https://geektutu.com/post/hpg-empty-struct.html

go中没有set类型,可以借助map key唯一的特点实现

如果使用bool作为value类型,会占用1个字节,100w条数据就会多占1MB左右的空间,使用空struct就会更节约内存

unsafe.Sizeof(struct{}{})  == 0

type void struct{}
var v void

set := make(map[string]void)

// set
set["a"] = v

// get
_, ok := set["b"]

// delete
delete(set, "b")


// len
len(set)

// for loop
for k := range set{
	fmt.Println(k)
}

 类似资料: