Golang-Map有序输出——使用orderedmap库实现
前言
工作中遇到一个问题:需要导出一个MySQL表格,表格内容由sql查询得来。但现在发现,所导出的表格中,各列的顺序不确定。多次导出, 每一次的序列顺序也是不定的。
因此确定是后端,Map使用相关导致的问题。自己想法是——创一个map[int]map{}
类型,即map套map。里面的map保存原有内容,int保存序号。
经网络搜索,发现已经有开源库提供了此功能,即https://github.com/iancoleman/orderedmap
库。因此对他进行学习。
功能概述
Golang内置的Map是无需的,而OrderedMap
则是提供了一个有顺序的Map。其顺序是插入时的顺序。
下面是官方文档中提供的功能描述:
package mainimport ("encoding/json""github.com/iancoleman/orderedmap""sort"
)func main() {// use New() instead of o := map[string]interface{}{}o := orderedmap.New()// use SetEscapeHTML() to whether escape problematic HTML characters or not, defaults is trueo.SetEscapeHTML(false)// use Set instead of o["a"] = 1o.Set("a", 1)// add some value with special characterso.Set("b", "\\.<>[]{}_-")// use Get instead of i, ok := o["a"]val, ok := o.Get("a")// use Keys instead of for k, v := range okeys := o.Keys()for _, k := range keys {v, _ := o.Get(k)}// use o.Delete instead of delete(o, key)o.Delete("a")// serialize to a json string using encoding/jsonbytes, err := json.Marshal(o)prettyBytes, err := json.MarshalIndent(o, "", " ")// deserialize a json string using encoding/json// all maps (including nested maps) will be parsed as orderedmapss := `{"a": 1}`err := json.Unmarshal([]byte(s), &o)// sort the keyso.SortKeys(sort.Strings)// sort by Pairo.Sort(func(a *orderedmap.Pair, b *orderedmap.Pair) bool {return a.Value().(float64) < b.Value().(float64)})
}
其主要用法如下:
通过orderedmap.New()
新建一个Map。
通过o.Set("a", 1)
设置Map中的元素内容。 (注意:key必须是string)
通过o.Get("a")
获取map内容。
通过keys
达到for range效果。
通过o.Delete("a")
进行元素删除。
通过SortKeys
和Sort
进行排序。
源码阅读
OrderedMap
的源码,包含注释等在内,一共266行,可谓是十分简短。
其中,一共有如下的方法可使用:
OrderedMap
的数据结构
New()
出来的那个Map是这样:
type OrderedMap struct {keys []stringvalues map[string]interface{}escapeHTML bool
}
其中:escapeHTML
是用来表示是否转义HTML字符,默认为true表示转义。可以调用SetEscapeHTML(false)方法来设置不转义HTML字符。
剩余keys
是[]string,values
是map。
OrderedMap
有序输出的原理
做这样一个测试:
func main() {o := orderedmap.New()o.Set("key2", "v2")o.Set("key3", "v3")o.Set("key1", 1)fmt.Println(o.Keys())fmt.Println(o.Values())}
其中,keys和values分别用于返回所有的key和value。
func (o *OrderedMap) Keys() []string {return o.keys
}func (o *OrderedMap) Values() map[string]interface{} {return o.values
}
输出结果为:
我们可以看到,其key是按输入顺序进行排列的切片,value是保存了对应key和value的map。
在输出时,通过定序的key
,去访问不定序的value
,最终输出时实现定序的效果。(定序:指与输入顺序相同)。
基础方法
初始化
通过New方法生成一个OrderedMap
,其中可以通过SetEscapeHTML
对该参数进行设置。
func New() *OrderedMap {o := OrderedMap{}o.keys = []string{}o.values = map[string]interface{}{}o.escapeHTML = truereturn &o
}func (o *OrderedMap) SetEscapeHTML(on bool) {o.escapeHTML = on
}
值的设置、查看及删除
通过Get
获取指定key值对应的value。
通过Set
对键值对进行设置。
通过Delete
删除键值对。
func (o *OrderedMap) Get(key string) (interface{}, bool) {val, exists := o.values[key]return val, exists
}func (o *OrderedMap) Set(key string, value interface{}) {_, exists := o.values[key]if !exists {o.keys = append(o.keys, key)}o.values[key] = value
}func (o *OrderedMap) Delete(key string) {// check key is in use_, ok := o.values[key]if !ok {return}// remove from keysfor i, k := range o.keys {if k == key {o.keys = append(o.keys[:i], o.keys[i+1:]...)break}}// remove from valuesdelete(o.values, key)
}
获取所有kv值
通过Keys()
获取所有的key。
通过Values()
获取所有的Value。
func (o *OrderedMap) Keys() []string {return o.keys
}func (o *OrderedMap) Values() map[string]interface{} {return o.values
}
Sort
和SortKeys
方法
SortKeys()
方法
// SortKeys Sort the map keys using your sort func
func (o *OrderedMap) SortKeys(sortFunc func(keys []string)) {sortFunc(o.keys)
}
即根据传入的方法规则,对key值进行排序。例如,按字母顺序排:
o.SortKeys(sort.Strings)
测试:
func main() {o := orderedmap.New()o.Set("key2", "v2")o.Set("key3", "v3")o.Set("key1", 1)fmt.Println(o.Keys())fmt.Println(o.Values())o.SortKeys(sort.Strings)fmt.Println(o.Keys())fmt.Println(o.Values())
}
结果:
Sort()
方法
源码如下:
// Sort Sort the map using your sort func
func (o *OrderedMap) Sort(lessFunc func(a *Pair, b *Pair) bool) {pairs := make([]*Pair, len(o.keys))for i, key := range o.keys {pairs[i] = &Pair{key, o.values[key]}}sort.Sort(ByPair{pairs, lessFunc})for i, pair := range pairs {o.keys[i] = pair.key}
}
其中,pair
如下:
type Pair struct {key stringvalue interface{}
}
该方法内,首先通过pair保留每一个键值对。之后哦通过传入的lessFunc
进行排序,再按照排序后的顺序,赋值到内部,从而实现排序。
用法示例:
// sort by Pair
o.Sort(func(a *orderedmap.Pair, b *orderedmap.Pair) bool {return a.Value().(float64) < b.Value().(float64)
})
Json
相关
UnmarshalJSON
方法,用于将JSON转换为有序MAP。
func (o *OrderedMap) UnmarshalJSON(b []byte) error {if o.values == nil {o.values = map[string]interface{}{}}err := json.Unmarshal(b, &o.values)if err != nil {return err}dec := json.NewDecoder(bytes.NewReader(b))if _, err = dec.Token(); err != nil { // skip '{'return err}o.keys = make([]string, 0, len(o.values))return decodeOrderedMap(dec, o)
}
MarshalJSON
反之,序列化为JSON。
func (o OrderedMap) MarshalJSON() ([]byte, error) {var buf bytes.Bufferbuf.WriteByte('{')encoder := json.NewEncoder(&buf)encoder.SetEscapeHTML(o.escapeHTML)for i, k := range o.keys {if i > 0 {buf.WriteByte(',')}// add keyif err := encoder.Encode(k); err != nil {return nil, err}buf.WriteByte(':')// add valueif err := encoder.Encode(o.values[k]); err != nil {return nil, err}}buf.WriteByte('}')return buf.Bytes(), nil
}
最后还有decodeOrderedMap
和decodeSlice
两个方法,是辅助json转换时候所用的,在此不再阐述。
总结&心得
1、通过OrderedMap
可以实现MAP的有序化,按输入顺序输出map的内容,或按自定义规则排序后进行输出。
2、使用OrderedMap
会导致性能下降,不要过度依赖。
相关文章:

Golang-Map有序输出——使用orderedmap库实现
前言 工作中遇到一个问题:需要导出一个MySQL表格,表格内容由sql查询得来。但现在发现,所导出的表格中,各列的顺序不确定。多次导出, 每一次的序列顺序也是不定的。 因此确定是后端,Map使用相关导致的问题。…...

基础数学问题整理
最近刷了一些关于基础数学问题的题目,大致是关于组合数、分解质因数还有一些思维题,题目来自洛谷的【数学1】基础数学问题 - 题单 - 洛谷,很多思路还是之前没有见过的,都是简单到一般难度的题目(橙、题、绿题ÿ…...

【Linux】环境基础开发工具的使用(一)
前言:在此之前我们学习了一些Linux的权限,今天我们进一步学习Linux下开发工具的使用。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:Linux的深度刨析 👈 💯代码仓库:卫卫周大胖的学习日记…...
突破编程_C++_面试(基础知识(5))
面试题9:什么是内存地址 内存地址是指计算机内存中存储变量或对象的地址。内存空间大小就是寻址能力,即能访问到多少个地址,比如 32 位机器内存空间大小就是 2^32 4294967296,也就是 4 GB 。每个变量或对象在内存中都有一个唯一…...
十分钟掌握Go语言==运算符与reflect.DeepEqual函数处理interface{}值的比较规则
在 Go 语言中,interface{} 类型是一种特殊的接口类型,它表示任意类型的值。你可以使用 运算符来检测任意两个 interface{} 类型值的相等性,比较的规则和一般的接口类型一样,需要满足以下条件: 两个 interface{} 值的…...

Unity3d Shader篇(一)— 顶点漫反射着色器解析
文章目录 前言一、顶点漫反射着色器是什么?1. 顶点漫反射着色器的工作原理 二、编写顶点漫反射着色器1. 定义属性2. 创建 SubShader3. 编写着色器程序段4. 完成顶点着色器5. 完成片段着色器 三、效果四、总结 前言 在 Unity 中,Shader 可以用来实现各种…...

WordPress主题YIA的文章页评论内容为什么没有显示出来?
有些WordPress站长使用YIA主题后,在YIA主题设置的“基本”中没有开启“一键关闭评论功能”,而且文章也是允许评论的,但是评论框却不显示,最关键的是文章原本就有的评论内容也不显示,这是为什么呢? 根据YIA主…...

选择低代码应该注意什么?如何选择?
我查看了几乎所有的介绍低代码的总结和分析报告,几乎都没有把低代码最底层的产品逻辑说清楚。今天我尝试不用复杂的技术名词,也不用代码,把这个事儿给大家说明白,低代码到底怎么回事儿!(人云亦云那些&#…...

橘子学linux调优之工具包的安装
今天在公司无聊的弄服务器,想着有些常用的工具包安装一下,这里就简单记录一下。 一、sysstat的安装和使用 1、安装 我是通过源码的方式安装的,这样的好处在于可以自由选择你的版本,很直观。 直接去github上找到sysstat的地址&a…...

函数的连续与间断【高数笔记】
【连续】 分类,分几个?每类特点? 连续条件,是同时满足还是只需其一? 【间断】 分类,分几个大类,又分几个小类?每类特点? 间断条件,是同时满足还是只需其一&am…...
游戏如何选择服务器
选择游戏服务器是一个综合性的过程,涉及到的因素包括但不限于游戏类型和规模、硬件配置、网络质量、安全性、服务商的声誉以及地理分布等。以下是一些具体的指导原则: 游戏类型和规模:根据游戏的具体需求来选择合适的服务器。例如࿰…...
ubuntu20安装mysql8
1.安装 sudo apt update sudo apt install mysql-server-8.0 -y2.查看运行状态 yantaoubuntu20:~$ sudo systemctl status mysql ● mysql.service - MySQL Community ServerLoaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset:>Active: active …...

07 SB3之@HttpExchange(TBD)
HttpExchange是SpringBoot3的新特性. Spring Boot3 提供了新的 HTTP 的访问能力,封装了Http底层细节. 通过接口简化 HTTP远程访问,类似 Feign 功能。 SpringBoot 中定义接口提供 HTTP 服务 --> 框架生成的代理对象实现此接口 --> 框架生成的代理…...
Redis数据淘汰策略
Redis作为一种高性能的键值存储数据库,通常用于缓存和提高数据检索速度。然而,由于内存资源有限,当内存不足以容纳所有数据时,Redis就需要采取一些策略来删除部分数据,以确保新的数据能够被写入。这就引入了数据淘汰策…...

Git的一些基本操作
初始git 我们给出下面的一个场景,在大学里,一些老师在我们做完实验之后喜欢让我们交实验报告,假设我们有一个比较追求完美的老师和一个勤奋的学生,这个学生叫做小帅,那天小帅桑勤奋的完成实验报告,在第二天…...
Spring Boot中异步线程池@Async
很多业务场景需要使用异步去完成,比如:发送短信通知。要完成异步操作一般有两种: 1、消息队列MQ 2、线程池处理。 我们来看看Spring框架中如何去使用线程池来完成异步操作,以及分析背后的原理。 一. Spring异步线程池的接口类 …...

ArcGIS学习(五)坐标系-2
3.不同基准面坐标系之间的转换 在上一关中,我们学习了ArcGIS中的投影(投影栅格)工具,并以"WGS1984地理坐标系与WGS1984的UTM投影坐标系的转换”为例进行讲解。 "WGS1984地理坐标系与WGS1984的UTM投影坐标系的转换”代表的是同一个基准面下的两个坐标的转换。 …...

2024Node.js零基础教程(小白友好型),nodejs新手到高手,(五)NodeJS入门——http模块
044_http模块_创建HTTP服务端 hello,大家好,那这个小节我们来使用 nodejs 创建一个 http 的服务,有了这个 http 服务之后,我们就可以处理浏览器所发送过来的请求,并且还可以给这个浏览器返回响应。 顺便说一下&#x…...
sklearn.preprocessing 标准化、归一化、正则化
文章目录 数据标准化的原因作用归一化最大最小归一化针对规模化有异常的数据标准化线性比例标准化法log函数标准化法正则化Normalization标准化的意义数据标准化的原因 某些算法要求样本具有零均值和单位方差;需要消除样本不同属性具有不同量级时的影响: ① 数量级的差异将导…...
Windows系统编程(一) 文件与目录操作
以下程序需要包含<Windows.h>头文件 创建打开文件 HANDLE hFile CreateFile("D:\\rkvir.ini", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 此处打开文件,参数依次 已有文件的路径,注意…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...