智慧团建网站登录平台官网,成都科技网站建设哪里有,甘肃网站seo技术厂家,广西知名网站设计前言
工作中遇到一个问题#xff1a;需要导出一个MySQL表格#xff0c;表格内容由sql查询得来。但现在发现#xff0c;所导出的表格中#xff0c;各列的顺序不确定。多次导出#xff0c; 每一次的序列顺序也是不定的。 因此确定是后端#xff0c;Map使用相关导致的问题。…前言
工作中遇到一个问题需要导出一个MySQL表格表格内容由sql查询得来。但现在发现所导出的表格中各列的顺序不确定。多次导出 每一次的序列顺序也是不定的。 因此确定是后端Map使用相关导致的问题。自己想法是——创一个map[int]map{}类型即map套map。里面的map保存原有内容int保存序号。 经网络搜索发现已经有开源库提供了此功能即https://github.com/iancoleman/orderedmap库。因此对他进行学习。
功能概述
Golang内置的Map是无需的而OrderedMap则是提供了一个有顺序的Map。其顺序是插入时的顺序。
下面是官方文档中提供的功能描述
package mainimport (encoding/jsongithub.com/iancoleman/orderedmapsort
)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是[]stringvalues是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[i1:]...)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会导致性能下降不要过度依赖。