大家好,我是阳哥。内容比较硬核,建议先收藏再观看。

前言

有好多初学GO和GoFrame的小伙伴搞不清楚map怎么用。

不少刚入门的小伙伴都被Go语言中map的无序性“坑过”。尤其是PHP转Go的小伙伴,不要问我是怎么知道的~

这篇文章就是给初学的小伙伴们答疑解惑的,会为大家介绍:

为什么Go语言中的map是无序的,如何自定义实现map的排序?

(Ps:这部分不作为这篇文章的重点,感兴趣的小伙伴可以看我之前整理的这篇文章:)

GoFrame的gmap相比于Go原生的map有什么优势?为什么天然支持排序和有序遍历!?

GoFrame的gmap有哪些使用技巧?

(注意:我是使用的GoFrame最新的V2版本为大家总结分享的。)

先说结论

mapHashMapTreeMapListMapTreeMapTreeMapListMap

使用技巧

map
HashMapHashMapListMapTreeMap
HashMaphashMap := gmap.New(true)

一图胜千言

GoFrame gmap 基本介绍:

map
mapHashMapTreeMapListMap

实例化示例:

实践得真知

打印结果

通过打印结果我们可以发现:

  1. hashmap的键列表和值列表返回值的顺序没有规律,随机返回
  2. listmap键列表和值列表有序返回,且顺序和写入顺序一致
  3. treemap键列表和值列表也有序返回,但是不和写入顺序一致,按自然数升序返回

这也佐证了我开篇提到的使用技巧。

为了让大家更好的理解gmap,下面介绍一下gmap的基础使用和一些进阶技巧。

基础概念

GoFrame框架(下文简称gf)提供的数据类型,比如:字典gmap、数组garray、集合gset、队列gqueue、树形结构gtree、链表glist都是支持设置并发安全开关的。

支持设置并发安全开关

对比sync.Map

Go语言提供的原生map不是并发安全的map类型

Go语言从1.9版本开始引入了并发安全的sync.Map,但gmap比较于标准库的sync.Map性能更加优异,并且功能更加丰富。

对性能测试感兴趣的小伙伴可以详细看下,不作为这篇文章的重点。

基础使用

  1. gmap.New(true) 在初始化的时候开启并发安全开关
  2. 通过 Set() 方法赋值,通过 Sets() 方法批量赋值
  3. 通过 Size() 方法获取map大小
  4. 通过 Get() 根据key获取value值
  5. ...

更多操作大家可以直接查看下方的代码示例,也欢迎大家动手复刻

为了方便大家更好的查看效果,在下方代码段中标明了打印结果:

运行结果

上面介绍的基础使用比较简单,下面介绍进阶使用。

合并 merge

注意:Merge()的参数需要是map的引用类型,也就是参数需要传map的取址符。

打印结果

序列化

正如之前的文章 介绍的,gf框架提供的数据类型不仅支持设置并发安全开关,也都支持序列化和反序列化。

json序列化和反序列化:序列化就是转成json格式,反序列化就是json转成其他格式类型(比如:map、数组、对象等)

打印结果

踩坑

//var m gmap.Map

在进行序列化操作时,必须实例化map

只是声明map而不进行实例化,是无法序列化成功的

另外一个需要注意的知识点就是过滤空值了:

过滤空值

打印结果

还有一个非常好用的特性,键值对反转:

键值对反转 Flip

打印结果

出栈(随机出栈)

这个出栈的知识点和我开篇的使用技巧呼应上了:

运行结果

踩坑

注意:多次测试后发现是随机出栈,不能理所当然的认为按顺序出栈。

我们深入思考一下原因:其实很简单,因为gmap的底层实现是hashmap,本身就是无序的,当然不可能按顺序出栈了。

总结

好了,我们再来回顾一下这篇文章的重点:

mapHashMapHashMapListMapTreeMapHashMaphashMap := gmap.New(true)json

一起学习

公众号:程序员升级打怪之旅

微信号:wangzhongyang1993