4. golang map 基本使用-灵析社区

cathoy

什么是 map?

map 是由一组 <key, value> 对组成的抽象数据结构,并且同一个 key 只会出现一次。

  1. <key,value> 组成
  2. 每个 key 只会出现一次

map 基本使用

初始化 map

// 初始化 - 不指定长度
aMap := make(map[string]string)
// 初始化 - 指定长度
bMap := make(map[string]string,16)
// 声明一个 map 为 nil,不能向其添加元素,会直接panic; 可以读取,源码会返回零值
cMap := map[string]string
// 支持在声明的时候填充元素, 此时 map 不为 nil
dMap := map[string]string{}

通过 key 获取 value

func main() {
    scoreMap := make(map[string]int)
    scoreMap["小红"] = 90
    scoreMap["小明"] = 80
    // 如果 key 存在 ok 为 true, v 为对应的值;不存在 ok 为 false,v 为值类型的零值
    v, ok := scoreMap["张三"]
    if ok {
       fmt.Println(v)
    }
        
    // 也可以不用 ok 模式,直接取 key
    v2 := scoreMap["小明"]
    // 一个不存在的 key 会返回对应类型的零值
    v3 := scoreMap["xx"]
    fmt.Println(v2,v3)
}

map 遍历

func main() {
    scoreMap := make(map[string]int)
    scoreMap["小红"] = 90
    scoreMap["小明"] = 80
    scoreMap["小号"] = 60
    for k, v := range scoreMap {
        fmt.Println(k, v)
    }
}

只遍历 key

func main() {
    scoreMap := make(map[string]int)
    scoreMap["小红"] = 90
    scoreMap["小明"] = 80
    scoreMap["小号"] = 60
    for k := range scoreMap {
        fmt.Println(k)
    }
}

遍历map时的元素顺序与添加键值对的顺序无关,更准确的说法应该是:迭代 map 的结果是无序的。关于此有两点原因:

  1. map 在扩容后,会发生 key 的搬迁,遍历 map 的结果就不可能按原来的顺序了。(那如果我不做删除和插入操作,按理说每次遍历这样的 map 都会返回一个固定顺序的 key/value 序列吧,然而并非如此)
  2. 从 go 1.0 以后,map 就变得完全无序了,当我们在遍历 map 时,并不是固定地从 0 号 bucket 开始遍历,每次都是从一个随机值序号的 bucket 开始遍历,并且是从这个 bucket 的一个随机序号的 cell 开始遍历。这样,即使你是一个写死的 map,仅仅只是遍历它,也不太可能会返回一个固定序列的 key/value 对了。

删除键值对

func main(){
	scoreMap := make(map[string]int)
	scoreMap["小红"] = 90
	scoreMap["小明"] = 80
	scoreMap["小号"] = 60
	delete(scoreMap, "小明")//将小明:100从map中删除
	for k,v := range scoreMap{
	    fmt.Println(k, v)
	}
}

删除 key 并不会释放内存,只是底层对应 value 位置赋值为空,key 位置都不一定清理内存。

按顺序遍历 map

先取出 key,按某种顺序排序后,对 key 进行遍历即可。

func main() {
    rand.Seed(time.Now().UnixNano()) //初始化随机数种子
    var scoreMap = make(map[string]int, 200)
    for i := 0; i < 100; i++ {
        key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
        value := rand.Intn(100)          //生成0~99的随机整数
        scoreMap[key] = value
    }

    //取出map中的所有key存入切片keys
    var keys = make([]string, 0, 200)
    for key := range scoreMap {
        keys = append(keys, key)
    }
    //对切片进行排序
    sort.Strings(keys)
    //按照排序后的key遍历map
    for _, key := range keys {
        fmt.Println(key, scoreMap[key])
    }
}

map 特性

map 有很多特性,都与其底层实现息息相关,比如:

  1. map 是引用类型、无序键值对集合、range 迭代随机次序返回
  2. map 中的 key 必须是可比较的(key 值类型必须支持 ==、!=)
  3. map 可判断是否等于 nil,但不支持比较操作
  4. 访问不存在的 key 返回对应零值(map 为 nil 时,也适用)
  5. map[key] 不支持寻址操作(& map[key] )(map 元素是无法取址的)- 因为扩容的存在,取地址没有意义
  6. 删除不存在的 key,不会引发错误
  7. 并发不安全,同时读写 map 会 panic

阅读量:529

点赞量:0

收藏量:0