github.com/weedge/lib@v0.0.0-20230424045628-a36dcc1d90e4/container/sort_map/readme.md (about) 1 #### 介绍 2 3 golang的map结构遍历(range map)的时候是无序的,因为底层的map存放数据是在hash表中, 可以通过汇编代码查看到调用的地方: 4 5 - runtime.mapiterinit 6 - runtime.mapiternext 7 8 ```assembly 9 0x009b 00155 (main.go:11) LEAQ type.map[int32]string(SB), AX 10 0x00a2 00162 (main.go:11) PCDATA $2, $0 11 0x00a2 00162 (main.go:11) MOVQ AX, (SP) 12 0x00a6 00166 (main.go:11) PCDATA $2, $2 13 0x00a6 00166 (main.go:11) LEAQ ""..autotmp_3+24(SP), AX 14 0x00ab 00171 (main.go:11) PCDATA $2, $0 15 0x00ab 00171 (main.go:11) MOVQ AX, 8(SP) 16 0x00b0 00176 (main.go:11) PCDATA $2, $2 17 0x00b0 00176 (main.go:11) LEAQ ""..autotmp_2+72(SP), AX 18 0x00b5 00181 (main.go:11) PCDATA $2, $0 19 0x00b5 00181 (main.go:11) MOVQ AX, 16(SP) 20 0x00ba 00186 (main.go:11) CALL runtime.mapiterinit(SB) 21 0x00bf 00191 (main.go:11) JMP 207 22 0x00c1 00193 (main.go:11) PCDATA $2, $2 23 0x00c1 00193 (main.go:11) LEAQ ""..autotmp_2+72(SP), AX 24 0x00c6 00198 (main.go:11) PCDATA $2, $0 25 0x00c6 00198 (main.go:11) MOVQ AX, (SP) 26 0x00ca 00202 (main.go:11) CALL runtime.mapiternext(SB) 27 0x00cf 00207 (main.go:11) CMPQ ""..autotmp_2+72(SP), $0 28 0x00d5 00213 (main.go:11) JNE 193 29 ``` 30 31 **runtime.mapiterinit**: 32 33 ```go 34 ... 35 // decide where to start 36 r := uintptr(fastrand()) 37 if h.B > 31-bucketCntBits { 38 r += uintptr(fastrand()) << 31 39 } 40 it.startBucket = r & bucketMask(h.B) 41 it.offset = uint8(r >> h.B & (bucketCnt - 1)) 42 43 // iterator state 44 it.bucket = it.startBucket 45 .... 46 ``` 47 48 无序的原因: <u>在开始处理循环逻辑的时候,就做了随机播种</u> 49 50 为了解决这个无序的问题,将map结构转换成slice结构,通过sort.Slice()来排序; 51 52 #### 功能 53 54 - [x] 支持map[int64]int64 key/value的升/降排序: SortIntIntMapByValue, SortIntIntMapByValueDesc, SortIntIntMapByKey, SortIntIntMapByKeyDesc 55 - [x] 支持map[int64]string key/value的升/降排序: SortIntStringMapByValue, SortIntStringMapByValueDesc, SortIntStringMapByKey, SortIntStringMapByKeyDesc 56 - [x] 支持map[string]string key/value的升/降排序: SortStringStringMapByValue, SortStringStringMapByValueDesc, SortStringStringMapByKey, SortStringStringMapByKeyDesc 57 - [x] 支持map[string]int64 key/value的升/降排序: SortStringIntMapByValue, SortStringIntMapByValueDesc, SortStringIntMapByKey, SortStringIntMapByKeyDesc 58 59 #### 总结 60 61 这个实现有点体力活,思路都是一样的,只是不同的map k/v类型 定义的 Len,Swap,Less 不同,后续go(1.17已经支持)支持模版了,用模版实现下 62 63 #### reference 64 65 1. [Go maps in action](https://go.dev/blog/maps) 66 2. [map源码解析](https://github.com/cch123/golang-notes/blob/master/map.md) 67