// 这样初始化默认是一个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,
}
// 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"]
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))
不能直接判断两个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
}
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)
}