遍历Map源码分析 (GO1.16.2)
Posted xxx小M
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了遍历Map源码分析 (GO1.16.2)相关的知识,希望对你有一定的参考价值。
代码
func MapTest() {
var aMap = map[int64]int64{
1: 10,
2: 20,
3: 30,
}
for k, v := range aMap {
fmt.Println(k, v)
}
}
编译
go tool compile -N -l -S ./test_map.go > ./test_map.s
汇编结果
"".MapTest STEXT size=912 args=0x0 locals=0x208 funcid=0x0
0x0000 00000 (./test_map.go:13) TEXT "".MapTest(SB), ABIInternal, $520-0
0x0000 00000 (./test_map.go:13) MOVQ (TLS), CX
0x0009 00009 (./test_map.go:13) LEAQ -392(SP), AX
0x0011 00017 (./test_map.go:13) CMPQ AX, 16(CX)
0x0015 00021 (./test_map.go:13) PCDATA $0, $-2
0x0015 00021 (./test_map.go:13) JLS 902
0x001b 00027 (./test_map.go:13) PCDATA $0, $-1
0x001b 00027 (./test_map.go:13) SUBQ $520, SP
0x0022 00034 (./test_map.go:13) MOVQ BP, 512(SP)
0x002a 00042 (./test_map.go:13) LEAQ 512(SP), BP
0x0032 00050 (./test_map.go:13) FUNCDATA $0, gclocals·3e27b3aa6b89137cce48b3379a2a6610(SB)
0x0032 00050 (./test_map.go:13) FUNCDATA $1, gclocals·4b48a54b979a44c0a517bad5b8d15a09(SB)
0x0032 00050 (./test_map.go:13) FUNCDATA $2, "".MapTest.stkobj(SB)
0x0032 00050 (./test_map.go:14) MOVQ $0, "".b+224(SP)
0x003e 00062 (./test_map.go:15) XORPS X1, X1
0x0041 00065 (./test_map.go:15) MOVUPS X1, ""..autotmp_7+368(SP)
0x0049 00073 (./test_map.go:15) MOVUPS X1, ""..autotmp_7+384(SP)
0x0051 00081 (./test_map.go:15) MOVUPS X1, ""..autotmp_7+400(SP)
0x0059 00089 (./test_map.go:15) LEAQ ""..autotmp_8+80(SP), DI
0x005e 00094 (./test_map.go:15) XORPS X0, X0
0x0061 00097 (./test_map.go:15) PCDATA $0, $-2
0x0061 00097 (./test_map.go:15) LEAQ -48(DI), DI
0x0065 00101 (./test_map.go:15) DUFFZERO $258
0x0078 00120 (./test_map.go:15) PCDATA $0, $-1
0x0078 00120 (./test_map.go:15) LEAQ ""..autotmp_7+368(SP), AX
0x0080 00128 (./test_map.go:15) MOVQ AX, ""..autotmp_9+240(SP)
0x0088 00136 (./test_map.go:15) TESTB AL, (AX)
0x008a 00138 (./test_map.go:15) LEAQ ""..autotmp_8+80(SP), AX
0x008f 00143 (./test_map.go:15) MOVQ AX, ""..autotmp_7+384(SP)
0x0097 00151 (./test_map.go:15) LEAQ ""..autotmp_7+368(SP), AX
0x009f 00159 (./test_map.go:15) MOVQ AX, ""..autotmp_10+304(SP)
0x00a7 00167 (./test_map.go:15) PCDATA $1, $1
0x00a7 00167 (./test_map.go:15) CALL runtime.fastrand(SB)
0x00ac 00172 (./test_map.go:15) MOVQ ""..autotmp_10+304(SP), AX
0x00b4 00180 (./test_map.go:15) TESTB AL, (AX)
0x00b6 00182 (./test_map.go:15) MOVL (SP), CX
0x00b9 00185 (./test_map.go:15) MOVL CX, 12(AX)
0x00bc 00188 (./test_map.go:15) LEAQ ""..autotmp_7+368(SP), AX
0x00c4 00196 (./test_map.go:15) MOVQ AX, "".aMap+232(SP)
0x00cc 00204 (./test_map.go:16) MOVQ $1, ""..autotmp_11+72(SP)
0x00d5 00213 (./test_map.go:16) MOVQ $10, ""..autotmp_12+64(SP)
0x00de 00222 (./test_map.go:16) MOVQ ""..autotmp_11+72(SP), AX
0x00e3 00227 (./test_map.go:16) MOVQ "".aMap+232(SP), CX
0x00eb 00235 (./test_map.go:16) LEAQ type.map[int64]int64(SB), DX
0x00f2 00242 (./test_map.go:16) MOVQ DX, (SP)
0x00f6 00246 (./test_map.go:16) MOVQ CX, 8(SP)
0x00fb 00251 (./test_map.go:16) MOVQ AX, 16(SP)
0x0100 00256 (./test_map.go:16) PCDATA $1, $2
0x0100 00256 (./test_map.go:16) CALL runtime.mapassign_fast64(SB)
0x0105 00261 (./test_map.go:16) MOVQ 24(SP), AX
0x010a 00266 (./test_map.go:16) MOVQ AX, ""..autotmp_13+296(SP)
0x0112 00274 (./test_map.go:16) TESTB AL, (AX)
0x0114 00276 (./test_map.go:16) MOVQ ""..autotmp_12+64(SP), CX
0x0119 00281 (./test_map.go:16) MOVQ CX, (AX)
0x011c 00284 (./test_map.go:17) MOVQ $2, ""..autotmp_11+72(SP)
0x0125 00293 (./test_map.go:17) MOVQ $20, ""..autotmp_12+64(SP)
0x012e 00302 (./test_map.go:17) MOVQ ""..autotmp_11+72(SP), AX
0x0133 00307 (./test_map.go:17) MOVQ "".aMap+232(SP), CX
0x013b 00315 (./test_map.go:17) LEAQ type.map[int64]int64(SB), DX
0x0142 00322 (./test_map.go:17) MOVQ DX, (SP)
0x0146 00326 (./test_map.go:17) MOVQ CX, 8(SP)
0x014b 00331 (./test_map.go:17) MOVQ AX, 16(SP)
0x0150 00336 (./test_map.go:17) CALL runtime.mapassign_fast64(SB)
0x0155 00341 (./test_map.go:17) MOVQ 24(SP), AX
0x015a 00346 (./test_map.go:17) MOVQ AX, ""..autotmp_14+288(SP)
0x0162 00354 (./test_map.go:17) TESTB AL, (AX)
0x0164 00356 (./test_map.go:17) MOVQ ""..autotmp_12+64(SP), CX
0x0169 00361 (./test_map.go:17) MOVQ CX, (AX)
0x016c 00364 (./test_map.go:18) MOVQ $3, ""..autotmp_11+72(SP)
0x0175 00373 (./test_map.go:18) MOVQ $30, ""..autotmp_12+64(SP)
0x017e 00382 (./test_map.go:18) MOVQ ""..autotmp_11+72(SP), AX
0x0183 00387 (./test_map.go:18) MOVQ "".aMap+232(SP), CX
0x018b 00395 (./test_map.go:18) LEAQ type.map[int64]int64(SB), DX
0x0192 00402 (./test_map.go:18) MOVQ DX, (SP)
0x0196 00406 (./test_map.go:18) MOVQ CX, 8(SP)
0x019b 00411 (./test_map.go:18) MOVQ AX, 16(SP)
0x01a0 00416 (./test_map.go:18) CALL runtime.mapassign_fast64(SB)
0x01a5 00421 (./test_map.go:18) MOVQ 24(SP), AX
0x01aa 00426 (./test_map.go:18) MOVQ AX, ""..autotmp_15+280(SP)
0x01b2 00434 (./test_map.go:18) TESTB AL, (AX)
0x01b4 00436 (./test_map.go:18) MOVQ ""..autotmp_12+64(SP), CX
0x01b9 00441 (./test_map.go:18) MOVQ CX, (AX)
0x01bc 00444 (./test_map.go:20) MOVQ "".aMap+232(SP), AX
0x01c4 00452 (./test_map.go:20) MOVQ AX, ""..autotmp_4+248(SP)
0x01cc 00460 (./test_map.go:20) LEAQ ""..autotmp_5+416(SP), DI
0x01d4 00468 (./test_map.go:20) XORPS X0, X0
0x01d7 00471 (./test_map.go:20) PCDATA $0, $-2
0x01d7 00471 (./test_map.go:20) LEAQ -32(DI), DI
0x01db 00475 (./test_map.go:20) NOP
0x01e0 00480 (./test_map.go:20) DUFFZERO $273
0x01f3 00499 (./test_map.go:20) PCDATA $0, $-1
0x01f3 00499 (./test_map.go:20) MOVQ ""..autotmp_4+248(SP), AX
0x01fb 00507 (./test_map.go:20) LEAQ type.map[int64]int64(SB), CX
0x0202 00514 (./test_map.go:20) MOVQ CX, (SP)
0x0206 00518 (./test_map.go:20) MOVQ AX, 8(SP)
0x020b 00523 (./test_map.go:20) LEAQ ""..autotmp_5+416(SP), AX
0x0213 00531 (./test_map.go:20) MOVQ AX, 16(SP)
0x0218 00536 (./test_map.go:20) PCDATA $1, $3
0x0218 00536 (./test_map.go:20) CALL runtime.mapiterinit(SB)
0x021d 00541 (./test_map.go:20) JMP 543
0x021f 00543 (./test_map.go:20) CMPQ ""..autotmp_5+416(SP), $0
0x0228 00552 (./test_map.go:20) JNE 559
0x022a 00554 (./test_map.go:20) JMP 886
0x022f 00559 (./test_map.go:20) MOVQ ""..autotmp_5+416(SP), AX
0x0237 00567 (./test_map.go:20) TESTB AL, (AX)
0x0239 00569 (./test_map.go:20) MOVQ (AX), AX
0x023c 00572 (./test_map.go:20) MOVQ AX, "".k+56(SP)
0x0241 00577 (./test_map.go:20) MOVQ ""..autotmp_5+424(SP), AX
0x0249 00585 (./test_map.go:20) TESTB AL, (AX)
0x024b 00587 (./test_map.go:20) MOVQ (AX), AX
0x024e 00590 (./test_map.go:20) MOVQ AX, "".v+48(SP)
0x0253 00595 (./test_map.go:21) XORPS X0, X0
0x0256 00598 (./test_map.go:21) MOVUPS X0, ""..autotmp_6+336(SP)
0x025e 00606 (./test_map.go:21) MOVUPS X0, ""..autotmp_6+352(SP)
0x0266 00614 (./test_map.go:21) LEAQ ""..autotmp_6+336(SP), AX
0x026e 00622 (./test_map.go:21) MOVQ AX, ""..autotmp_17+272(SP)
0x0276 00630 (./test_map.go:21) MOVQ "".k+56(SP), AX
0x027b 00635 (./test_map.go:21) MOVQ AX, (SP)
0x027f 00639 (./test_map.go:21) PCDATA $1, $4
0x027f 00639 (./test_map.go:21) NOP
0x0280 00640 (./test_map.go:21) CALL runtime.convT64(SB)
0x0285 00645 (./test_map.go:21) MOVQ 8(SP), AX
0x028a 00650 (./test_map.go:21) MOVQ AX, ""..autotmp_18+264(SP)
0x0292 00658 (./test_map.go:21) MOVQ ""..autotmp_17+272(SP), CX
0x029a 00666 (./test_map.go:21) TESTB AL, (CX)
0x029c 00668 (./test_map.go:21) LEAQ type.int64(SB), DX
0x02a3 00675 (./test_map.go:21) MOVQ DX, (CX)
0x02a6 00678 (./test_map.go:21) LEAQ 8(CX), DI
0x02aa 00682 (./test_map.go:21) PCDATA $0, $-2
0x02aa 00682 (./test_map.go:21) CMPL runtime.writeBarrier(SB), $0
0x02b1 00689 (./test_map.go:21) JEQ 696
0x02b3 00691 (./test_map.go:21) JMP 876
0x02b8 00696 (./test_map.go:21) MOVQ AX, 8(CX)
0x02bc 00700 (./test_map.go:21) JMP 702
0x02be 00702 (./test_map.go:21) PCDATA $0, $-1
0x02be 00702 (./test_map.go:21) MOVQ "".v+48(SP), AX
0x02c3 00707 (./test_map.go:21) MOVQ AX, (SP)
0x02c7 00711 (./test_map.go:21) CALL runtime.convT64(SB)
0x02cc 00716 (./test_map.go:21) MOVQ 8(SP), AX
0x02d1 00721 (./test_map.go:21) MOVQ AX, ""..autotmp_19+256(SP)
0x02d9 00729 (./test_map.go:21) MOVQ ""..autotmp_17+272(SP), CX
0x02e1 00737 (./test_map.go:21) TESTB AL, (CX)
0x02e3 00739 (./test_map.go:21) LEAQ type.int64(SB), DX
0x02ea 00746 (./test_map.go:21) MOVQ DX, 16(CX)
0x02ee 00750 (./test_map.go:21) LEAQ 24(CX), DI
0x02f2 00754 (./test_map.go:21) PCDATA $0, $-2
0x02f2 00754 (./test_map.go:21) CMPL runtime.writeBarrier(SB), $0
0x02f9 00761 (./test_map.go:21) JEQ 765
0x02fb 00763 (./test_map.go:21) JMP 869
0x02fd 00765 (./test_map.go:21) MOVQ AX, 24(CX)
0x0301 00769 (./test_map.go:21) JMP 771
0x0303 00771 (./test_map.go:21) PCDATA $0, $-1
0x0303 00771 (./test_map.go:21) MOVQ ""..autotmp_17+272(SP), AX
0x030b 00779 (./test_map.go:21) TESTB AL, (AX)
0x030d 00781 (./test_map.go:21) JMP 783
0x030f 00783 (./test_map.go:21) MOVQ AX, ""..autotmp_16+312(SP)
0x0317 00791 (./test_map.go:21) MOVQ $2, ""..autotmp_16+320(SP)
0x0323 00803 (./test_map.go:21) MOVQ $2, ""..autotmp_16+328(SP)
0x032f 00815 (./test_map.go:21) MOVQ AX, (SP)
0x0333 00819 (./test_map.go:21) MOVQ $2, 8(SP)
0x033c 00828 (./test_map.go:21) MOVQ $2, 16(SP)
0x0345 00837 (./test_map.go:21) PCDATA $1, $3
0x0345 00837 (./test_map.go:21) CALL fmt.Println(SB)
0x034a 00842 (./test_map.go:21) JMP 844
0x034c 00844 (./test_map.go:20) LEAQ ""..autotmp_5+416(SP), AX
0x0354 00852 (./test_map.go:20) MOVQ AX, (SP)
0x0358 00856 (./test_map.go:20) CALL runtime.mapiternext(SB)
0x035d 00861 (./test_map.go:20) NOP
0x0360 00864 (./test_map.go:20) JMP 543
0x0365 00869 (./test_map.go:21) PCDATA $0, $-2
0x0365 00869 (./test_map.go:21) CALL runtime.gcWriteBarrier(SB)
0x036a 00874 (./test_map.go:21) JMP 771
0x036c 00876 (./test_map.go:21) CALL runtime.gcWriteBarrier(SB)
0x0371 00881 (./test_map.go:21) JMP 702
0x0376 00886 (./test_map.go:24) PCDATA $0, $-1
0x0376 00886 (./test_map.go:24) PCDATA $1, $-1
0x0376 00886 (./test_map.go:24) MOVQ 512(SP), BP
0x037e 00894 (./test_map.go:24) ADDQ $520, SP
0x0385 00901 (./test_map.go:24) RET
0x0386 00902 (./test_map.go:24) NOP
0x0386 00902 (./test_map.go:13) PCDATA $1, $-1
0x0386 00902 (./test_map.go:13) PCDATA $0, $-2
0x0386 00902 (./test_map.go:13) CALL runtime.morestack_noctxt(SB)
0x038b 00907 (./test_map.go:13) PCDATA $0, $-1
0x038b 00907 (./test_map.go:13) JMP 0
下面会对这段代码进行精简分段分析
创建空字典b
0x0032 00050 (./test_map.go:14) MOVQ $0, "".b+224(SP)
只有一行,直接指向0指针
创建非空字典aMap
0x003e 00062 (./test_map.go:15) XORPS X1, X1 // X1 = (int128)0
0x0041 00065 (./test_map.go:15) MOVUPS X1, ""..autotmp_7+368(SP) // autotmp_7(hmap).count = (int)0
// autotmp_7(hmap).flags = (uint8)0
// autotmp_7(hmap).B = (uint8)0
// autotmp_7(hmap).noverflow = (uint16)0
// autotmp_7(hmap).hash0 = (uint32)0
0x0049 00073 (./test_map.go:15) MOVUPS X1, ""..autotmp_7+384(SP) // autotmp_7(hmap).buckets = (unsafe.Pointer)0
// autotmp_7(hmap).oldbuckets= (unsafe.Pointer)0
0x0051 00081 (./test_map.go:15) MOVUPS X1, ""..autotmp_7+400(SP) // autotmp_7(hmap).nevacuate = (uintptr)0
// autotmp_7(hmap).extra = (*mapextra)0
0x0059 00089 (./test_map.go:15) LEAQ ""..autotmp_8+80(SP), DI
0x005e 00094 (./test_map.go:15) XORPS X0, X0
0x0061 00097 (./test_map.go:15) PCDATA $0, $-2
0x0061 00097 (./test_map.go:15) LEAQ -48(DI), DI
0x0065 00101 (./test_map.go:15) DUFFZERO $258
0x0078 00120 (./test_map.go:15) PCDATA $0, $-1
0x0078 00120 (./test_map.go:15) LEAQ ""..autotmp_7+368(SP), AX // AX = (*hmap)&autotmp_7
0x0080 00128 (./test_map.go:15) MOVQ AX, ""..autotmp_9+240(SP) // autotmp_9 = AX = (*hmap)&autotmp_7
0x0088 00136 (./test_map.go:15) TESTB AL, (AX)
0x008a 00138 (./test_map.go:15) LEAQ ""..autotmp_8+80(SP), AX // AX = &autotmp_8
0x008f 00143 (./test_map.go:15) MOVQ AX, ""..autotmp_7+384(SP) // autotmp_7(hmap).buckets = AX = &autotmp_8
0x0097 00151 (./test_map.go:15) LEAQ ""..autotmp_7+368(SP), AX // AX = &autotmp_7(hmap)
0x009f 00159 (./test_map.go:15) MOVQ AX, ""..autotmp_10+304(SP) // autotmp_10 = AX = &autotmp_7(hmap)
0x00a7 00167 (./test_map.go:15) PCDATA $1, $1
0x00a7 00167 (./test_map.go:15) CALL runtime.fastrand(SB)
0x00ac 00172 (./test_map.go:15) MOVQ ""..autotmp_10+304(SP), AX // AX = autotmp_10 = (*hmap)&autotmp_7
0x00b4 00180 (./test_map.go:15) TESTB AL, (AX)
0x00b6 00182 (./test_map.go:15) MOVL (SP), CX // CX = (int32)runtime.fastrand(SB)
0x00b9 00185 (./test_map.go:15) MOVL CX, 12(AX) // autotmp_7(hmap).hash0 = CX = runtime.fastrand(SB)
0x00bc 00188 (./test_map.go:15) LEAQ ""..autotmp_7+368(SP), AX // AX = (*hmap)&autotmp_7
0x00c4 00196 (./test_map.go:15) MOVQ AX, "".aMap+232(SP) // aMap = AX = (*hmap)&autotmp_7
得到一个指针变量aMap指向*hmap
type hmap struct {
// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
// Make sure this stays in sync with the compiler\'s definition.
count int // # live cells == size of map. Must be first (used by len() builtin)
flags uint8
B uint8 // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
hash0 uint32 // hash seed
buckets unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
nevacuate uintptr // progress counter for evacuation (buckets less than this have been evacuated)
extra *mapextra // optional fields
}
其中
hmap.buckets = &autotmp_8
hmap.hash0 = (int32)runtime.fastrand(SB)
其他变量都等于0
赋值
var aMap = map[int64]int64{
1: 10,
2: 20,
3: 30,
}
有三个值分别赋值,都是一样的,这里只讲aMap[1] = 10
截取汇编:
0x00cc 00204 (./test_map.go:16) MOVQ $1, ""..autotmp_11+72(SP) // autotmp_11 = 1
0x00d5 00213 (./test_map.go:16) MOVQ $10, ""..autotmp_12+64(SP) // autotmp_12 = 10
0x00de 00222 (./test_map.go:16) MOVQ ""..autotmp_11+72(SP), AX // AX = autotmp_11 = 1
0x00e3 00227 (./test_map.go:16) MOVQ "".aMap+232(SP), CX // CX = aMap
0x00eb 00235 (./test_map.go:16) LEAQ type.map[int64]int64(SB), DX // DX = type.map[int64]int64(SB)
0x00f2 00242 (./test_map.go:16) MOVQ DX, (SP)
0x00f6 00246 (./test_map.go:16) MOVQ CX, 8(SP)
0x00fb 00251 (./test_map.go:16) MOVQ AX, 16(SP)
0x0100 00256 (./test_map.go:16) PCDATA $1, $2
0x0100 00256 (./test_map.go:16) CALL runtime.mapassign_fast64(SB) // runtime.mapassign_fast64(type.map[int64]int64(SB), aMap, AX)
0x0105 00261 (./test_map.go:16) MOVQ 24(SP), AX // AX = runtime.mapassign_fast64
0x010a 00266 (./test_map.go:16) MOVQ AX, ""..autotmp_13+296(SP) // autotmp_13 = runtime.mapassign_fast64
0x0112 00274 (./test_map.go:16) TESTB AL, (AX)
0x0114 00276 (./test_map.go:16) MOVQ ""..autotmp_12+64(SP), CX // CX = autotmp_12 = 2
0x0119 00281 (./test_map.go:16) MOVQ CX, (AX) // *AX = CX = 2
其中
func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
if h == nil { // 空字典报错
panic(plainError("assignment to entry in nil map"))
}
if h.flags&hashWriting != 0 { // 写入状态
throw("concurrent map writes")
}
hash := t.hasher(noescape(unsafe.Pointer(&key)), uintptr(h.hash0)) // 生成哈希值
// Set hashWriting after calling t.hasher for consistency with mapassign.
h.flags ^= hashWriting // 设置写入状态
if h.buckets == nil { // 生成buckets
h.buckets = newobject(t.bucket) // newarray(t.bucket, 1)
}
again:
bucket := hash & bucketMask(h.B) // 判断去那个桶
if h.growing() { // 如果在扩展桶
growWork_fast64(t, h, bucket)
}
b := (*bmap)(add(h.buckets, bucket*uintptr(t.bucketsize))) // 定位到相应的桶
var insertb *bmap // 最终插入到哪个桶
var inserti uintptr // 插入到桶的哪个坑(一共bucketCnt(8)个)
var insertk unsafe.Pointer // 由上面计算得到的key的位置
bucketloop:
for {
for i := uintptr(0); i < bucketCnt; i++ {
if isEmpty(b.tophash[i]) {
if insertb == nil {
insertb = b
inserti = i
}
if b.tophash[i] == emptyRest { // 找到最后一个空格子,跳出进行插入
break bucketloop
}
continue // 找到空格子但是不是最后一个,忽略找下一个
}
k := *((*uint64)(add(unsafe.Pointer(b), dataOffset+i*8)))
if k != key { // 不为空,就判断下key会不会相等
continue
}
insertb = b
inserti = i
goto done // key相等,不用插入key了,直接去done,找到值插入进好了
}
// 桶里面没找到
ovf := b.overflow(t) // 看看有没有溢出桶桶
if ovf == nil { // 没有,退出
break
}
b = ovf // 有的话,下一个桶继续找
}
// Did not find mapping for key. Allocate new cell & add entry.
// 如果超过装载因子,或者溢出桶数量超过最大值,则扩展桶
if !h.growing() && (overLoadFactor(h.count+1, h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
hashGrow(t, h)
goto again // Growing the table invalidates everything, so try again
}
if insertb == nil {
// 当前的桶和溢出桶都满了,则新建一个桶
insertb = h.newoverflow(t, b)
inserti = 0 // not necessary, but avoids needlessly spilling inserti
}
// 成功到找到了插入位置
// 插入tophash
insertb.tophash[inserti&(bucketCnt-1)] = tophash(hash) // mask inserti to avoid bounds checks
// 插入 key
insertk = add(unsafe.Pointer(insertb), dataOffset+inserti*8)
// store new key at insert position
*(*uint64)(insertk) = key
h.count++
done:
// 获取字典的值位置
elem := add(unsafe.Pointer(insertb), dataOffset+bucketCnt*8+inserti*uintptr(t.elemsize))
// 设置和检查flags
if h.flags&hashWriting == 0 {
throw("concurrent map writes")
}
h.flags &^= hashWriting
return elem
}
每种字典的bmap的key和value都不一样,下面是本例子的 mapint64
const bucketCnt = 8
type bmap struct {
tophash [bucketCnt]uint8
key [bucketCnt]int64 // int64就是map的key的类型
elem [bucketCnt]int64 // int64就是map的value的类型
overflow *bmap // 下一个溢出bmap
}
遍历
func mapiterinit(t *maptype, h *hmap, it *hiter) {
if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 {
throw("hash_iter size incorrect") // see cmd/compile/internal/gc/reflect.go
}
it.t = t
it.h = h
// grab snapshot of bucket state
it.B = h.B
it.buckets = h.buckets
if t.bucket.ptrdata == 0 {
// Allocate the current slice and remember pointers to both current and old.
// This preserves all relevant overflow buckets alive even if
// the table grows and/or overflow buckets are added to the table
// while we are iterating.
h.createOverflow()
it.overflow = h.extra.overflow
it.oldoverflow = h.extra.oldoverflow
}
// decide where to start
r := uintptr(fastrand())
if h.B > 31-bucketCntBits {
r += uintptr(fastrand()) << 31
}
it.startBucket = r & bucketMask(h.B)
it.offset = uint8(r >> h.B & (bucketCnt - 1))
// iterator state
it.bucket = it.startBucket
// Remember we have an iterator.
// Can run concurrently with another mapiterinit().
if old := h.flags; old&(iterator|oldIterator) != iterator|oldIterator {
atomic.Or8(&h.flags, iterator|oldIterator)
}
mapiternext(it)
}
以上是关于遍历Map源码分析 (GO1.16.2)的主要内容,如果未能解决你的问题,请参考以下文章
Android 插件化VirtualApp 源码分析 ( 目前的 API 现状 | 安装应用源码分析 | 安装按钮执行的操作 | 返回到 HomeActivity 执行的操作 )(代码片段
Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段
Android 事件分发事件分发源码分析 ( Activity 中各层级的事件传递 | Activity -> PhoneWindow -> DecorView -> ViewGroup )(代码片段
Groovymap 集合 ( map 集合遍历 | 使用 map 集合的 each 方法遍历 map 集合 | 代码示例 )