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