[Golang]Map的一个绝妙特性

golang 红黑树map实现 //------------------------------------------------------------------------------ // rbtree.go // 红黑树 //------------------------------------------------------------------------------ package rbmap const ( RED bool = true BLACK bool = false ) type no. 阅读详情

原文链接:http://studygolang.com/articles/2494


好了,现在回来看看这个文章。

过去几周,我看到的人们对Go语言的热情和语言的发展势头真是让我无比惊叹。这里面的一部分原因可能是和Gophercon 2014有关,在我写这篇文章的时候,刚刚举办完。我对那些能参加的人真是羡慕,嫉妒,恨啊!从会议计划和讨论话题来看,会议确实很棒。另外能够去和Rob Pike神搞个基,以及看看那些家伙用Go创造出来的好东西也是很不错的。另外我感觉最近关于Go的博客数量也爆发了。而且,很多人开始重点地将Go在他们的服务中使用。比如Digital Ocean,大规模云计算创业公司,刚刚宣布他们把一大坨Perl代码改为Go实现,并且极大地改进了诸如响应时间等问题。

我从来不会写那种屌丝级必备的“哇塞,我用Golang两周了,真的好棒啊!”这种文章。因为我觉得这些文章没有啥意思,零价值。但是,最近我遇到了一个Go特性,而且我认为这个特性非常酷,并且在我看来反映出了Go作为一门牛逼语言的基本姿态。

Go的map元素遍历顺序(使用range关键字)是随机的,而不是遵循元素的添加顺序。这是什么意思?很特别么?

Maps

Map的简单介绍。
从Andrew Gerrand的关于maps的文章直接偷过来用。

计算机科学里面最有用的数据结构之一就是hash表。不同的hash表实现提供了很多独特的特性。但是基本上都包括元素查询,添加和删除。Go提供了一个内置的类型map,这个类型实现了hash表的基本功能。

所以在Go语言里面如果你需要使用hash表,那么就用map吧。因为Go是强类型语言,所以你必须为map的键和对应的值指定具体的类型。这些键或值的类型可以是字符串,整型,指向结构体的指针等。一个常见的用法就是键和值都是字符串类型。
go m := make(map[string]string)

使用方法很简单。在元素被赋值之前,key可以不存在,甚至在被取值的时候也可以不存在(这样就返回零值,零值对于不同的类型是不同的,比如整型是0,而字符串是空字符串"")。

m["bandName"] = "Funny Bones"             // "create"
websiteTitle := m["bandName"] + " Music"  // "read"
m["bandName"] = "Moon Taxi"               // "update"
delete(m, "bandName")                     // "delete"
fmt.Printf(m["bandName"])                 // prints nothing since m["bandName"] == ""

 

可以使用range关键字来遍历map的所有元素。

<pre name="code" class="plain">for key, value := range m {
  fmt.Println("Key:", key, "Value:", value)
}


 
 

遍历顺序
第一眼看上去,Go程序员或许会以为下面的代码输出:

<pre name="code" class="plain">package main

import "fmt"

func main() {
  blogArticleViews := map[string]int{
      "unix": 0,
      "python": 1,
      "go": 2,
      "javascript": 3,
      "testing": 4,
      "philosophy": 5,
      "startups": 6,
      "productivity": 7,
      "hn": 8,
      "reddit": 9,
      "C++": 10,
  }
  for key, views := range blogArticleViews {
      fmt.Println("There are", views, "views for", key)
  }
}


 
 

会是这样的:

<pre name="code" class="plain">$ go run map_iteration_order.go
There are 0 views for unix
There are 1 views for python
There are 2 views for go
There are 3 views for javascript
There are 4 views for testing
There are 5 views for philosophy
There are 6 views for startups
There are 7 views for productivity
There are 8 views for hn
There are 9 views for reddit
There are 10 views for C++


 
 

但从Go 1版本开始,map的遍历顺序是随机的。也就是说下面的结果更有可能:

<pre name="code" class="plain">$ go run map_iteration_order.go
There are 3 views for javascript
There are 5 views for philosophy
There are 10 views for C++
There are 0 views for unix
There are 1 views for python
There are 2 views for go
There are 4 views for testing
There are 6 views for startups
There are 7 views for productivity
There are 8 views for hn
There are 9 views for reddit


 
 

Go语言的设计者们注意到人们过于依赖这种通常情况下key的存储顺序和key的添加顺序一致的特性。所以他们把key的遍历顺序随机化了。因此,如果你希望key的输出顺序和添加顺序一致的话,你需要自己去追踪哪个值存储在哪个位置,就像这样:

<pre name="code" class="plain">package main

import (
    "fmt"
    "sort"
)

func main() {
    var m = map[string]int{
        "unix":         0,
        "python":       1,
        "go":           2,
        "javascript":   3,
        "testing":      4,
        "philosophy":   5,
        "startups":     6,
        "productivity": 7,
        "hn":           8,
        "reddit":       9,
        "C++":          10,
    }
    var keys []string
    for k := range m {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        fmt.Println("Key:", k, "Value:", m[k])
    }
}


 
 

上面的代码是又一次厚颜无耻地从Andrew 的大作偷过来直接用的。

我觉得大家对这个特性的态度可以分为两类。
第一类人会有各种反应,从不明白为什么要这么做,到有点不爽,甚至是强烈反对。这些人大部分是喜欢弄些有潜在危险性的或者小技巧的代码,并且他们希望Go语言的设计者也能满足他们的愿望。
另一类人倒是能够完全接受,而且很感激Go设计者们能够为他们着想,不断完善和改进Go语言。

为什么这很特别?

一句话:态度。

这个无伤大雅的语言特性在我看来恰是作为通用语言哲学的一个闪光点。没有过于灵活地允许马马虎虎的代码,Go强迫你从一开始就把事情弄得直接一点。Go程序员参考里面说如果他们的程序可以编译(而且代码符合Go的风格),那么代码有很大的可能可以像预期的那样工作,这种模模糊糊却不错的感觉也有Go严谨性的贡献。没有诡异的类型bug,丢失分号等等错误。

尤其是,在Andrew的参考文章中,他指出这是Go的设计者们所作出的改变。他们不再允许人们依赖于那些破破烂烂的假设。我最痛恨的一点就是那些破烂的,到处是bug的功能(这发生在交付的产品中,或者是编程语言,等等很多地方),通过权衡,接受,从而变成了一个特性,另外尝试修复这些"特性"真的是很恶心。很明显的,PHP和JavaScript的语言文化就是因为各种原因往这个方向发展的(他们使用它,但是注定要付出代价,而且很多东西到最后都是没有解决的)。

例如,PHP的一个最大的缺点是,针与干草堆的问题(在干草堆里面找针)。我理想中的语言所应该具有的特点和这种不一致性格格不入。这也是为什么我发现Go的设计者拒绝糟糕的异常和泛型设计。他们就是想做正确的事情,当然他们知道这需要花费时间。他们不着急,而且向语言中添加特性比删除特性容易多了。

总结
Go是一种令人愉悦的语言,而且很多方面都是经过深思熟虑的。不要因为它缺少一些你常用的功能,比如泛型和动态类型,而急于去评断和批评它。如果你自己愿意试一试,你会发现你不一定需要这些功能。而且,你通过使用简单的并行功能会写出更简单,整洁,优雅的代码。

Go一直在坚定地成长和发展中,这也是Go所能带来的乐趣之一。它绝对是可靠的,而且可以用于生产环境中。同时Go的性能和稳定性也在不断地提高。看看下面由Rob Pike最近贴出来的对比Go 1和最新版(快1.3了)的对比。


treeMap实现分组数据树形结构 treeMap实现分组数据树形结构,在通过Redis和MySQL数据库ID生成序列ID 立即下载

相关推荐

攻防世界 web高手进阶区 9分题 Web_python_flask_sql_injection

继续ctf的旅程,开始攻防世界web高手进阶区的9分题,本文是Web_python_flask_sql_injection的writeup

闵行小鱼塘 1476

常用数据结构类型(Golang版)

简介 Golang中常用的数据类型如切片,哈希表等实现可能不能满足我们的日常需要,如具有有序性的TreeMap等; 另外某些数据结构实现起来比较麻烦,如二叉堆Heap等; GoDS实现了各种各样的数据结构及匹配算法 GoDS 安装 git clone https://github.com/emirpasic/gods.git gods最后应在src相应的github.com目录下 根接口 type Container interface { Empty() bool Size() int Cle

某热心知名群众的博客 2140

OpenWrt虚拟机磁盘扩容实战:从SquashFS到ext4的完整避坑指南

本文详细介绍了OpenWrt虚拟机磁盘扩容的完整流程,重点对比了SquashFS和ext4文件系统在扩容操作上的关键差异。通过五步安全迁移法和直接分区调整方案,帮助用户有效解决磁盘空间不足问题,同时提供高级技巧和故障排除指南,确保扩容过程顺利无坑。

weixin_29251131的博客 232

算法 | golang 实现 key有序map

摘要: Golang map实现原理是hash map(核心元素是桶,key通过哈希算法被归入不同的bucket中),key是无序的,很多应用场景可能需要map key有序(例如交易所订单撮合),C++ 的stl map 实现了key有序,实际上是TreeMap是基于树(红黑树)的实现方式,即添加到一个有序列表,在O(log n)的复杂度内通过key值找到value,优点是空间要...

terrygmx的博客 8312

pi/4QPSK调制解调原理

文章目录1. π/4\pi/4π/4QPSK 信号的调制原理2. 匹配滤波器与成形滤波器 1. π/4\pi/4π/4QPSK 信号的调制原理 减小相位突变量的QPSK由偏置键控QPSK(OK-QPSK)和 π/4\pi/4π/4偏置的QPSK( π/4\pi/4π/4QPSK)。由于 π/4\pi/4π/4QPSK是用差分相位编码产生的(因此也叫做 π/4\pi/4π/4DQPSK),能有效地进行差分解调和鉴频器解调,在一些不易提取相干载波的场合很有用。 在常规的QPSK中,输入数据经过串/并变换后,分成

gemengxia的博客 2万+

PIDNet实战:如何在Cityscapes数据集上实现93.2 FPS的实时语义分割(附完整训练代码)

本文提供了在Cityscapes数据集上实现实时语义分割模型PIDNet的完整工程实践指南。PIDNet凭借其独特的比例-积分-微分三分支架构,在CVPR 2023上取得了速度与精度的出色平衡。文章详细介绍了从环境配置、数据预处理、模型训练到性能优化与部署的全流程,并分享了实现93.2 FPS高推理速度的关键技巧与代码。

weixin_29047919的博客 377

golang 获取map所有key的方式

最佳方式:根据map的长度,新建一个数组,遍历map逐个压入 方法1: func getKeys1(m map[int]int) []int { // 数组默认长度为map长度,后面append时,不需要重新申请内存和拷贝,效率较高 j := 0 keys := make([]int, len(m)) for k := range m { keys[j] = k j++ }...

papaya的博客 7万+

Simulink开发项1000例实战专栏--实例148:构建一个完整的电动汽车电池SOH评估仿真模型,包括电池建模模块、数据采集模块、SOH估算算法模块以及性能评估模块

电动汽车的动力电池是其核心部件,而电池的健康状态(State of Health, SOH)直接影响车辆的续航能力和使用寿命。SOH通常定义为当前电池容量与初始容量的比值,用百分比表示。通过基于MATLAB/Simulink平台的SOH评估仿真,可以实时监测电池的退化情况,并为电池管理系统(BMS)提供决策依据。本项目旨在构建一个完整的电动汽车电池SOH评估仿真模型,包括电池建模模块、数据采集模块、SOH估算算法模块以及性能评估模块,并通过仿真验证SOH评估的准确性。

xiaoheshang_123的博客 342

TreeMap升序排序

定义工具类 public class TreeMapUtil implements Comparator{ @Override public int compare(Object o1, Object o2) { String i1=(String)o1; String i2=(String)o2;         return -i1.compareTo(i2); }

m0_37367272的博客 467

嵌入式通信协议框架的四层架构设计与实现

本文详细介绍一种模块化的嵌入式通信协议框架设计,采用四层架构:硬件抽象层统一管理数据收发与缓冲,隔离硬件差异;协议管理层通过特征识别自动路由多协议数据,支持动态扩展;协议处理层独立实现各协议解析/构建,确保校验安全与零拷贝效率;应用层采用表驱动模式处理业务逻辑,与协议细节解耦。 该架构已应用于工业控制等领域,具备强类型安全、高扩展性和平台无关性特点,显著提升复通信场景下的开发效率与系统可靠性。提供完整代码实现与设计要点分析,助力开发者构建高效通信栈。

Bit_Dong的博客 2465

数学建模Matlab算法,第七章 对策论

对策论作为研究竞争与决策的数学理论,从零和对策到非常数和对策,为分析各类博弈问题提供了系统框架。其核心要素包括局中人、策略集和赢得函数,通过稳定解、Nash平衡点等概念揭示竞争规律。该理论广泛应用于经济、军事、政治等领域,不仅提供具体分析工具,更改变了决策思维方式,强调在互动中实现理性选择。对策论既揭示了竞争本质,也凸显合作价值,为解决社会矛盾、促进共赢发展提供了重要启示,在全球化背景下将发挥更大作用。

unber的博客 114

Golang

跟我一起写 Makefile(一) istio源码解析系列(一)-istio开发环境搭建 Golang学习–TOML配置处理

来啊 快活啊 1108

第14.11章 高翔博士最新开源框架Lightning-LM源码解读(十一):离线定位模块全解析,从激光匹配到位姿图优化的极致优化

本文介绍了Lightning-LM离线定位模块的技术架构与实现细节。该模块基于3D激光雷达与IMU融合,采用改进版NDT匹配算法实现高精度定位,具备动态图层更新、多源信息融合等特性。核心流程包括数据预处理、激光里程计处理、IMU预测与点云去畸变、位姿图优化等环节,通过轻量级miao库实现高效增量优化。文章详细解析了模块的代码结构、关键函数功能及数据流,为SLAM系统的开发与优化提供了实践参考。

行知SLAM 376

除了技术能力,什么决定了软件工程师的上限?答案是“品味”

在这篇文章中,我们将一起拆解“技术品味”这个看似玄妙的概念,学习如何识别自己和他人身上的“坏品味”(比如对“最佳实践”的盲从),并探索一条培养“好品味”的实践路径,帮助我们Go开发者在日常的权衡与决策中,做出更成熟的选择。只有理解了为什么Go是现在这个样子,我们才能在使用这门语言时,做出同样充满“品味”的、与项目需求相匹配的决策,从而真正发挥出Go语言的全部威力,成为一名真正成熟的软件工程师。你总是在不同的工程价值观之间做艰难的取舍,比如在“性能”和“可读性”之间,或者在“开发速度”和“正确性”之间。

TonyBai 1124

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Qwen3-ASR-0.6B与Claude Code技能结合:智能编程助手

本文介绍了如何在星图GPU平台自动化部署Qwen3-ASR-0.6B镜像,构建智能编程助手。该方案结合语音识别与代码生成技术,让开发者通过语音描述即可自动生成可执行代码,典型应用于快速原型开发和学习编程等场景,显著提升开发效率。

weixin_35756373的博客 100

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

知识图谱笔记工具架构解析:构建个人第二大脑的技术实现原理

在信息爆炸的数字时代,如何高效管理知识、建立个人知识体系成为现代知识工作者的核心挑战。新一代知识图谱笔记工具通过双向链接技术模拟大脑神经元连接,实现了从线性笔记到网状知识图谱的革命性转变。本文将从技术架构、实现原理到实战应用,深度解析知识图谱笔记工具如何成为个人知识管理的"第二大脑",为技术爱好者和进阶用户提供全面的技术视角和实践指导。 ## 技术定位与核心价值主张 知识图谱笔记工具不仅仅是传

gitblog_01187的博客 979

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Python:概述与基础语法(一)

本文是一份全面的 Python 入门指南,涵盖了 Python 的发展历史、语言特点、应用领域、安装配置、基础语法以及进阶学习路线。文章从 Python 的设计哲学和解释型语言特性讲起,详细介绍了在 Windows、macOS 和 Linux 系统上的安装步骤,包括环境变量配置和常见问题解决。接着讲解了 Python 基础语法,包括变量、数据类型、类型转换等核心概念。最后为初学者规划了 Web 开发、数据分析、自动化/爬虫和 AI/机器学习四个方向的学习路径,并提供了丰富的学习资源推荐。

WindsProgrammer的博客 629

Python深度学习:从入门到实战

亲爱的读者,欢迎您翻开这本书。我们即将探索的,是深度学习的宇宙——一个由数据、算法与算力构筑的奇妙世界。它既是严谨的科学,也是创造的艺术,更是一条通往未来智慧的修行之路。本书将带您从最基础的数学原理出发,亲手搭建神经网络,驾驭Transformer等前沿模型,最终将智慧转化为现实世界的价值。请放下畏惧,保持好奇。这不仅是一次知识的学习,更是一场思维的远行。来,随我一起,开启这趟非凡的旅程吧。

weixin_45747731的博客 300

Go 语言映射(Maps)深度解析:高效键值对存储的终极方案

Go 语言中的映射(Map)是一种高效的键值对存储结构,基于哈希表实现,具有无序性、高效性和类型安全等特性。映射的创建可以通过make函数或字面量初始化,支持增删改查等核心操作。Go 1.21 引入了maps包,提供了更多实用工具函数。在使用映射时,需注意初始化、零值处理、并发安全及键类型选择等常见陷阱。性能优化方面,建议预分配容量、选择合适的值类型及批量操作。映射在 Go 生态中占据核心地位,广泛应用于非结构化数据处理、配置管理及统计场景。

Tekin 是深耕技术 20 年的全栈实战派专家,精通 Go/Python/Java 等多语言开发。博客专注技术原理与实战结合,深度解析 Python 高阶编程、Go 语言架构、数据库优化等硬核内容。涵盖并发编程、机器学习、云原生等前沿领域,通过真实案例拆 1418
上一篇: golang语言中map的初始化及使用
下一篇: 前端架构
hellochenlu
博客等级 码龄14年 97粉丝 184原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值