您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Go 语言 Map 如何顺序读取?

时间:2023-05-19 13:37:59  来源: AlwaysBeta  作者:
在遍历 Map 时,并不是固定地从 0 号 Bucket 开始遍历,每次都是从一个随机值序号的 Bucket 开始遍历,并且是从这个 Bucket 的一个随机序号的 Cell 开始遍历。

Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。

然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。

现象

先看一段代码示例:

package main

import "fmt"

func main() {
    m := map[string]int{
        "Apple":  1,
        "banana": 2,
        "orange": 3,
    }

    for k, v := range m {
        fmt.Printf("key=%s, value=%dn", k, v)
    }
}

当我们多执行几次这段代码时,就会发现,输出的顺序是不同的。

原因

首先,Go 语言 map 的底层实现是哈希表,在进行插入时,会对 key 进行 hash 运算。这也就导致了数据不是按顺序存储的,和遍历的顺序也就会不一致。

第二,map 在扩容后,会发生 key 的搬迁,原来落在同一个 bucket 中的 key,搬迁后,有些 key 可能就到其他 bucket 了。

而遍历的过程,就是按顺序遍历 bucket,同时按顺序遍历 bucket 中的 key。

搬迁后,key 的位置发生了重大的变化,有些 key 被搬走了,有些 key 则原地不动。这样,遍历 map 的结果就不可能按原来的顺序了。

最后,也是最有意思的一点。

那如果说我已经初始化好了一个 map,并且不对这个 map 做任何操作,也就是不会发生扩容,那遍历顺序是固定的吗?

答:也不是。

Go 杜绝了这种做法,主要是担心程序员会在开发过程中依赖稳定的遍历顺序,因为这是不对的。

所以在遍历 map 时,并不是固定地从 0 号 bucket 开始遍历,每次都是从一个随机值序号的 bucket 开始遍历,并且是从这个 bucket 的一个随机序号的 cell 开始遍历。

如何顺序读取

如果希望按照特定顺序遍历 map,可以先将键或值存储到切片中,然后对切片进行排序,最后再遍历切片。

改造一下上面的代码,让它按顺序输出:

package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]int{
        "apple":  1,
        "banana": 2,
        "orange": 3,
    }

    // 将 map 中的键存储到切片中
    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }

    // 对切片进行排序
    sort.Strings(keys)

    // 按照排序后的顺序遍历 map
    for _, k := range keys {
        fmt.Printf("key=%s, value=%dn", k, m[k])
    }
}

在上面的代码中,首先将 map 中的键存储到一个切片中,然后对切片进行排序。

最后,按照排序后的顺序遍历 map。这样就可以按照特定顺序输出键值对了。



Tags:Go 语言   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除。
▌相关推荐
在遍历 Map 时,并不是固定地从 0 号 Bucket 开始遍历,每次都是从一个随机值序号的 Bucket 开始遍历,并且是从这个 Bucket 的一个随机序号的 Cell 开始遍历。Go 语言中的 map 是...【详细内容】
2023-05-19  Tags: Go 语言  点击:(0)  评论:(0)  加入收藏
Go 语言中的 map 是一个非常常用的数据结构,它允许我们快速地存储和检索键值对。然而,在并发场景下使用 map 时,还是有一些问题需要注意的。本文将探讨 Go 语言中的 map 是否...【详细内容】
2023-05-15  Tags: Go 语言  点击:(9)  评论:(0)  加入收藏
快速排序是由东尼·霍尔所发明的一种排序算法,时间复杂度是 O(nlogn), 是不稳定排序算法。快速排序使用分治思想,通过一趟排序将要排序的数据分割成独立的两部分,其中一部...【详细内容】
2023-05-08  Tags: Go 语言  点击:(18)  评论:(0)  加入收藏
作 者 | 牛学蔚(蔚俊)本文介绍了Go 微服务体系发展与选型,过去一年Dubbo-go 社区的飞速发展以及对未来的展望。一、Go 微服务体系发展与选型随着微服务技术的快速发展,其在各...【详细内容】
2023-04-11  Tags: Go 语言  点击:(24)  评论:(0)  加入收藏
在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。切片是一种引...【详细内容】
2023-04-03  Tags: Go 语言  点击:(38)  评论:(0)  加入收藏
本文转载自微信公众号「洋芋编程」,作者蛮荆 。转载本文请联系洋芋编程公众号。在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决...【详细内容】
2023-03-21  Tags: Go 语言  点击:(52)  评论:(0)  加入收藏
本文我们介绍怎么使用命令行工具 micro new 创建一个 gRPC 服务,并且怎么构建和运行服务。​01 介绍Go 开源项目 Micro​ 为我们提供一套微服务解决方案,它主要包含两个部分...【详细内容】
2023-03-06  Tags: Go 语言  点击:(51)  评论:(0)  加入收藏
本文我们介绍了跨平台文件监听库 fsnotify,它主要用于自动监听文件中的内容变更。我们通过 fsnotify 源码和示例代码,介绍了该库支持的功能和使用方式。​1、介绍Go 语言作为...【详细内容】
2023-02-26  Tags: Go 语言  点击:(57)  评论:(0)  加入收藏
本文我们通过在 Gin 构建的应用中,使用 Zap 记录请求日志,介绍了 Zap 的使用方式,最后还通过 lumberjack 日志切割库进行切割日志。​1、介绍我们在之前的文章中介绍过标准库 l...【详细内容】
2023-02-13  Tags: Go 语言  点击:(83)  评论:(0)  加入收藏
Hello,大家好,又见面了!上一遍我们将 channel 相关基础以及使用场景。这一篇,还需要再次进阶理解channel 阻塞问题。以下创建一个chan类型为int,cap 为3。ch := make(chan string...【详细内容】
2022-01-04  Tags: Go 语言  点击:(524)  评论:(0)  加入收藏
▌简易百科推荐
在遍历 Map 时,并不是固定地从 0 号 Bucket 开始遍历,每次都是从一个随机值序号的 Bucket 开始遍历,并且是从这个 Bucket 的一个随机序号的 Cell 开始遍历。Go 语言中的 map 是...【详细内容】
2023-05-19     AlwaysBeta  Tags:Go 语言   点击:(0)  评论:(0)  加入收藏
在生产环境中,如mysql数据库服务、rabbit-mq消息队列服务、redis缓存服务等。为了安全,这些服务的通常端口都是不对外网开放的。有时候,我们需要本地访问这些服务,要如何设置呢?...【详细内容】
2023-05-16  互联网解决方案服务  今日头条  Tags:golang   点击:(12)  评论:(0)  加入收藏
Go 语言中的 map 是一个非常常用的数据结构,它允许我们快速地存储和检索键值对。然而,在并发场景下使用 map 时,还是有一些问题需要注意的。本文将探讨 Go 语言中的 map 是否...【详细内容】
2023-05-15  AlwaysBeta  微信公众号  Tags:Go 语言   点击:(9)  评论:(0)  加入收藏
Golang中的sync包实现了两种锁:互斥锁(Mutex)和读写锁(RWMutex)。互斥锁(sync.Mutex) 使用Lock方法加锁,使用Unlock方法解锁,Golang从1.18新增了TryLock方法,用于尝试获取锁,返回成功或...【详细内容】
2023-05-15  路多辛  今日头条  Tags:Golang   点击:(9)  评论:(0)  加入收藏
众所周知,自媒体写作是一项需要不断创新的工作,而其中最常见的问题就是“原创难”。为了应对这一问题,人们开始寻找各种“伪原创”方法。而在这些方法中,go语言无疑是最受欢迎的...【详细内容】
2023-05-07  京京爱美食    Tags:Go语言   点击:(13)  评论:(0)  加入收藏
unsafe是Golang中的一个包,提供了一些不安全的操作,例如指针操作和类型转换,这些操作可以绕过Go语言的类型安全检查和垃圾回收机制,可以用于编写低层次的系统代码或进行一些高性...【详细内容】
2023-05-05  大厂背锅侠  今日头条  Tags:Go语言   点击:(5)  评论:(0)  加入收藏
这篇开始记录整数的格式化处理,首先学习下%c格式 可以看到,参数是Unicode编码或字符。我们知道,字符实质是一个整数,如果用Unicode编码,一般指的是UTF-16。fmt.Printf("%c\n",&#3...【详细内容】
2023-04-17  编程牛  今日头条  Tags:Go   点击:(31)  评论:(0)  加入收藏
作 者 | 牛学蔚(蔚俊)本文介绍了Go 微服务体系发展与选型,过去一年Dubbo-go 社区的飞速发展以及对未来的展望。一、Go 微服务体系发展与选型随着微服务技术的快速发展,其在各...【详细内容】
2023-04-11  阿里云云栖号     Tags:Go 语言   点击:(24)  评论:(0)  加入收藏
作者:xindong本文针对Golang与Java的基础语法、结构体函数、异常处理、并发编程及垃圾回收、资源消耗等各方面的差异进行对比总结,有不准确、不到位的地方还请大家不吝赐教。...【详细内容】
2023-04-07  腾讯技术工程  微信公众号  Tags:Golang   点击:(39)  评论:(0)  加入收藏
在 Go 语言中,有一个很常用的数据结构,那就是切片(Slice)。切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。切片是一种引...【详细内容】
2023-04-03  yongxinz  AlwaysBeta  Tags:Go 语言   点击:(38)  评论:(0)  加入收藏
站内最新
站内热门
站内头条