go 生成hash_go基础之map-写在前面(一)

709d2dcc4a8fc996302115d48a1228a5.png

为什么分析map

在计算机编程语言当中,用的最多的数据结构估计就是map。map以他近乎o(1)的查找效率和修改效率让他在大多数场景下都比较受青睐。map的常规的实现方式都是hash+其他数据结构,如java是hash+红黑树,而我现在即将要分析的go的实现方式是hash+链表。我会分析map的几乎每段代码,并且在我的GitHub可以查看到我的分析,注释十分详尽,欢迎批评指正。我的打算是把一些常用的数据结构都分析一遍,如果有志同道合的人,可以联系我。

我的环境

为了给那些感兴趣看源码分析我的博客的同学阅读得更加清晰,列举了我的环境: 1. go1.14.7 amd64; 2. windows和mac接口,linux没有测试,估计没问题 ; 3. goland,目前最好的golang ide,虽然笔者用起来感觉还是不太完美; 4. 着重分析map[string]string,其他类型的源码变化不大

本篇重点

1.go的map和java的map有区别,go中是一个关键字,而java确实可以直接查看源码,那么如何分析go的map源码? 2.调试过程当中,go充斥着大量指针,如何知道指针指向的内容?map的最小单位bmap除了查看tophash,怎么查看里面的其他隐藏字段? 3.go的map源码为何给不同的key的类型设计不同的实现? 4.其他一些查看源码的小技巧:内存对齐、指针偏移、类型大小等等

如何找到map对应的源码

go的map的结构体是hmap,代码位于runtime/map.go,当编译器编译你申明使用map的源码时候,其实是使用了runtime/map*.go,后面对map的增删改查都是执行该代码,故要弄懂map的底层原理只需要分析该源码,也可以断点调试。 我下面有个自己测试的源码,注意我编译之后查看,就可以发现端倪:

package mainimport "fmt"func main() {m1 := make(map[string]string)fmt.Println(m1)m2 := make(map[string]string, 8)fmt.Println(m2)m3 := make(map[string]string, 9)fmt.Println(m3)m4 := map[string]string{}fmt.Println(m4)m3["1"] = "2"for k, v := range m3 {fmt.Println(k)fmt.Println(v)}v1 := m3["1"]fmt.Println(v1)if v2, ok := m3["1"]; ok {fmt.Println(v2)}
}

上面代码有几种不同申明map的方式,对应runtime/map.go也不同。还有赋值和遍历查找的代码。 下面编译得到汇编指令文件,执行

go tool compile -N -l -S main.go > main.txt

生成了汇编指令文件:

"".main STEXT size=1891 args=0x0 locals=0x2880x0000 00000 (main.go:5)    TEXT    "".main(SB), ABIInternal, $648-00x0000 00000 (main.go:5)    MOVQ    TLS, CX0x0009 00009 (main.go:5)    PCDATA  $0, $-20x0009 00009 (main.go:5)    MOVQ    (CX)(TLS*2), CX0x0010 00016 (main.go:5)    PCDATA  $0, $-10x0010 00016 (main.go:5)    LEAQ    -520(SP), AX0x0018 00024 (main.go:5)    CMPQ    AX, 16(CX)0x001c 00028 (main.go:5)    PCDATA  $0, $-20x001c 00028 (main.go:5)    JLS 18810x0022 00034 (main.go:5)    PCDATA  $0, $-10x0022 00034 (main.go:5)    SUBQ    $648, SP0x0029 00041 (main.go:5)    MOVQ    BP, 640(SP)0x0031 00049 (main.go:5)    LEAQ    640(SP), BP0x0039 00057 (main.go:5)    PCDATA  $0, $-20x0039 00057 (main.go:5)    PCDATA  $1, $-20x0039 00057 (main.go:5)    FUNCDATA    $0, gclocals·ad6397d3d33bbb6a31b1320349e23274(SB)0x0039 00057 (main.go:5)    FUNCDATA    $1, gclocals·1bbf1965a34fa71a63e073b1cf2d752a(SB)0x0039 00057 (main.go:5)    FUNCDATA    $2, gclocals·658035074399f748be6dd39603d5113c(SB)0x0039 00057 (main.go:5)    FUNCDATA    $3, "".main.stkobj(SB)0x0039 00057 (main.go:6)    PCDATA  $0, $00x0039 00057 (main.go:6)    PCDATA  $1, $00x0039 00057 (main.go:6)    CALL    runtime.makemap_small(SB)0x003e 00062 (main.go:6)    PCDATA  $0, $10x003e 00062 (main.go:6)    MOVQ    (SP), AX0x0042 00066 (main.go:6)    MOVQ    AX, "".m1+80(SP)0x0047 00071 (main.go:7)    PCDATA  $0, $00x0047 00071 (main.go:7)    PCDATA  $1, $10x0047 00071 (main.go:7)    MOVQ    AX, ""..autotmp_10+200(SP)0x004f 00079 (main.go:7)    PCDATA  $1, $20x004f 00079 (main.go:7)    XORPS   X0, X00x0052 00082 (main.go:7)    MOVUPS  X0, ""..autotmp_9+272(SP)0x005a 00090 (main.go:7)    PCDATA  $0, $10x005a 00090 (main.go:7)    PCDATA  $1, $10x005a 00090 (main.go:7)    LEAQ    ""..autotmp_9+272(SP), AX0x0062 00098 (main.go:7)    MOVQ    AX, ""..autotmp_15+192(SP)0x006a 00106 (main.go:7)    TESTB   AL, (AX)0x006c 00108 (main.go:7)    PCDATA  $0, $20x006c 00108 (main.go:7)    PCDATA  $1, $00x006c 00108 (main.go:7)    MOVQ    ""..autotmp_10+200(SP), CX0x0074 00116 (main.go:7)    PCDATA  $0, $30x0074 00116 (main.go:7)    LEAQ    type.map[string]string(SB), DX0x007b 00123 (main.go:7)    PCDATA  $0, $20x007b 00123 (main.go:7)    MOVQ    DX, ""..autotmp_9+272(SP)0x0083 00131 (main.go:7)    PCDATA  $0, $10x0083 00131 (main.go:7)    MOVQ    CX, ""..autotmp_9+280(SP)0x008b 00139 (main.go:7)    TESTB   AL, (AX)0x008d 00141 (main.go:7)    JMP 1430x008f 00143 (main.go:7)    MOVQ    AX, ""..autotmp_14+520(SP)0x0097 00151 (main.go:7)    MOVQ    $1, ""..autotmp_14+528(SP)0x00a3 00163 (main.go:7)    MOVQ    $1, ""..autotmp_14+536(SP)0x00af 00175 (main.go:7)    PCDATA  $0, $00x00af 00175 (main.go:7)    MOVQ    AX, (SP)0x00b3 00179 (main.go:7)    MOVQ    $1, 8(SP)0x00bc 00188 (main.go:7)    MOVQ    $1, 16(SP)0x00c5 00197 (main.go:7)    CALL    fmt.Println(SB)0x00ca 00202 (main.go:8)    CALL    runtime.makemap_small(SB)0x00cf 00207 (main.go:8)    PCDATA  $0, $10x00cf 00207 (main.go:8)    MOVQ    (SP), AX0x00d3 00211 (main.go:8)    MOVQ    AX, "".m2+72(SP)0x00d8 00216 (main.go:9)    PCDATA  $0, $00x00d8 00216 (main.go:9)    PCDATA  $1, $10x00d8 00216 (main.go:9)    MOVQ    AX, ""..autotmp_10+200(SP)0x00e0 00224 (main.go:9)    PCDATA  $1, $20x00e0 00224 (main.go:9)    XORPS   X0, X00x00e3 00227 (main.go:9)    MOVUPS  X0, ""..autotmp_9+272(SP)0x00eb 00235 (main.go:9)    PCDATA  $0, $10x00eb 00235 (main.go:9)    PCDATA  $1, $10x00eb 00235 (main.go:9)    LEAQ    ""..autotmp_9+272(SP), AX0x00f3 00243 (main.go:9)    MOVQ    AX, ""..autotmp_17+184(SP)0x00fb 00251 (main.go:9)    TESTB   AL, (AX)0x00fd 00253 (main.go:9)    PCDATA  $0, $20x00fd 00253 (main.go:9)    PCDATA  $1, $00x00fd 00253 (main.go:9)    MOVQ    ""..autotmp_10+200(SP), CX0x0105 00261 (main.go:9)    PCDATA  $0, $30x0105 00261 (main.go:9)    LEAQ    type.map[string]string(SB), DX0x010c 00268 (main.go:9)    PCDATA  $0, $20x010c 00268 (main.go:9)    MOVQ    DX, ""..autotmp_9+272(SP)0x0114 00276 (main.go:9)    PCDATA  $0, $10x0114 00276 (main.go:9)    MOVQ    CX, ""..autotmp_9+280(SP)0x011c 00284 (main.go:9)    TESTB   AL, (AX)0x011e 00286 (main.go:9)    JMP 2880x0120 00288 (main.go:9)    MOVQ    AX, ""..autotmp_16+496(SP)0x0128 00296 (main.go:9)    MOVQ    $1, ""..autotmp_16+504(SP)0x0134 00308 (main.go:9)    MOVQ    $1, ""..autotmp_16+512(SP)0x0140 00320 (main.go:9)    PCDATA  $0, $00x0140 00320 (main.go:9)    MOVQ    AX, (SP)0x0144 00324 (main.go:9)    MOVQ    $1, 8(SP)0x014d 00333 (main.go:9)    MOVQ    $1, 16(SP)0x0156 00342 (main.go:9)    CALL    fmt.Println(SB)0x015b 00347 (main.go:10)   PCDATA  $0, $10x015b 00347 (main.go:10)   LEAQ    type.map[string]string(SB), AX0x0162 00354 (main.go:10)   PCDATA  $0, $00x0162 00354 (main.go:10)   MOVQ    AX, (SP)0x0166 00358 (main.go:10)   MOVQ    $9, 8(SP)0x016f 00367 (main.go:10)   MOVQ    $0, 16(SP)0x0178 00376 (main.go:10)   CALL    runtime.makemap(SB)0x017d 00381 (main.go:10)   PCDATA  $0, $10x017d 00381 (main.go:10)   MOVQ    24(SP), AX0x0182 00386 (main.go:10)   PCDATA  $1, $30x0182 00386 (main.go:10)   MOVQ    AX, "".m3+64(SP)0x0187 00391 (main.go:11)   PCDATA  $0, $00x0187 00391 (main.go:11)   PCDATA  $1, $40x0187 00391 (main.go:11)   MOVQ    AX, ""..autotmp_10+200(SP)0x018f 00399 (main.go:11)   PCDATA  $1, $50x018f 00399 (main.go:11)   XORPS   X0, X00x0192 00402 (main.go:11)   MOVUPS  X0, ""..autotmp_9+272(SP)0x019a 00410 (main.go:11)   PCDATA  $0, $10x019a 00410 (main.go:11)   PCDATA  $1, $40x019a 00410 (main.go:11)   LEAQ    ""..autotmp_9+272(SP), AX0x01a2 00418 (main.go:11)   MOVQ    AX, ""..autotmp_19+176(SP)0x01aa 00426 (main.go:11)   TESTB   AL, (AX)0x01ac 00428 (main.go:11)   PCDATA  $0, $20x01ac 00428 (main.go:11)   PCDATA  $1, $30x01ac 00428 (main.go:11)   MOVQ    ""..autotmp_10+200(SP), CX0x01b4 00436 (main.go:11)   PCDATA  $0, $30x01b4 00436 (main.go:11)   LEAQ    type.map[string]string(SB), DX0x01bb 00443 (main.go:11)   PCDATA  $0, $20x01bb 00443 (main.go:11)   MOVQ    DX, ""..autotmp_9+272(SP)0x01c3 00451 (main.go:11)   PCDATA  $0, $10x01c3 00451 (main.go:11)   MOVQ    CX, ""..autotmp_9+280(SP)0x01cb 00459 (main.go:11)   TESTB   AL, (AX)0x01cd 00461 (main.go:11)   JMP 4630x01cf 00463 (main.go:11)   MOVQ    AX, ""..autotmp_18+472(SP)0x01d7 00471 (main.go:11)   MOVQ    $1, ""..autotmp_18+480(SP)0x01e3 00483 (main.go:11)   MOVQ    $1, ""..autotmp_18+488(SP)0x01ef 00495 (main.go:11)   PCDATA  $0, $00x01ef 00495 (main.go:11)   MOVQ    AX, (SP)0x01f3 00499 (main.go:11)   MOVQ    $1, 8(SP)0x01fc 00508 (main.go:11)   MOVQ    $1, 16(SP)0x0205 00517 (main.go:11)   CALL    fmt.Println(SB)0x020a 00522 (main.go:12)   CALL    runtime.makemap_small(SB)0x020f 00527 (main.go:12)   PCDATA  $0, $10x020f 00527 (main.go:12)   MOVQ    (SP), AX0x0213 00531 (main.go:12)   PCDATA  $0, $00x0213 00531 (main.go:12)   PCDATA  $1, $60x0213 00531 (main.go:12)   MOVQ    AX, "".m4+56(SP)0x0218 00536 (main.go:13)   PCDATA  $0, $10x0218 00536 (main.go:13)   PCDATA  $1, $30x0218 00536 (main.go:13)   MOVQ    "".m4+56(SP), AX0x021d 00541 (main.go:13)   PCDATA  $0, $00x021d 00541 (main.go:13)   PCDATA  $1, $40x021d 00541 (main.go:13)   MOVQ    AX, ""..autotmp_10+200(SP)0x0225 00549 (main.go:13)   PCDATA  $1, $50x0225 00549 (main.go:13)   XORPS   X0, X00x0228 00552 (main.go:13)   MOVUPS  X0, ""..autotmp_9+272(SP)0x0230 00560 (main.go:13)   PCDATA  $0, $10x0230 00560 (main.go:13)   PCDATA  $1, $40x0230 00560 (main.go:13)   LEAQ    ""..autotmp_9+272(SP), AX0x0238 00568 (main.go:13)   MOVQ    AX, ""..autotmp_23+168(SP)0x0240 00576 (main.go:13)   TESTB   AL, (AX)0x0242 00578 (main.go:13)   PCDATA  $0, $20x0242 00578 (main.go:13)   PCDATA  $1, $30x0242 00578 (main.go:13)   MOVQ    ""..autotmp_10+200(SP), CX0x024a 00586 (main.go:13)   PCDATA  $0, $30x024a 00586 (main.go:13)   LEAQ    type.map[string]string(SB), DX0x0251 00593 (main.go:13)   PCDATA  $0, $20x0251 00593 (main.go:13)   MOVQ    DX, ""..autotmp_9+272(SP)0x0259 00601 (main.go:13)   PCDATA  $0, $10x0259 00601 (main.go:13)   MOVQ    CX, ""..autotmp_9+280(SP)0x0261 00609 (main.go:13)   TESTB   AL, (AX)0x0263 00611 (main.go:13)   JMP 6130x0265 00613 (main.go:13)   MOVQ    AX, ""..autotmp_22+448(SP)0x026d 00621 (main.go:13)   MOVQ    $1, ""..autotmp_22+456(SP)0x0279 00633 (main.go:13)   MOVQ    $1, ""..autotmp_22+464(SP)0x0285 00645 (main.go:13)   PCDATA  $0, $00x0285 00645 (main.go:13)   MOVQ    AX, (SP)0x0289 00649 (main.go:13)   MOVQ    $1, 8(SP)0x0292 00658 (main.go:13)   MOVQ    $1, 16(SP)0x029b 00667 (main.go:13)   CALL    fmt.Println(SB)0x02a0 00672 (main.go:14)   PCDATA  $0, $10x02a0 00672 (main.go:14)   LEAQ    type.map[string]string(SB), AX0x02a7 00679 (main.go:14)   PCDATA  $0, $00x02a7 00679 (main.go:14)   MOVQ    AX, (SP)0x02ab 00683 (main.go:14)   PCDATA  $0, $10x02ab 00683 (main.go:14)   MOVQ    "".m3+64(SP), AX0x02b0 00688 (main.go:14)   PCDATA  $0, $00x02b0 00688 (main.go:14)   MOVQ    AX, 8(SP)0x02b5 00693 (main.go:14)   PCDATA  $0, $10x02b5 00693 (main.go:14)   LEAQ    go.string."1"(SB), AX0x02bc 00700 (main.go:14)   PCDATA  $0, $00x02bc 00700 (main.go:14)   MOVQ    AX, 16(SP)0x02c1 00705 (main.go:14)   MOVQ    $1, 24(SP)0x02ca 00714 (main.go:14)   CALL    runtime.mapassign_faststr(SB)0x02cf 00719 (main.go:14)   PCDATA  $0, $40x02cf 00719 (main.go:14)   MOVQ    32(SP), DI0x02d4 00724 (main.go:14)   MOVQ    DI, ""..autotmp_24+160(SP)0x02dc 00732 (main.go:14)   TESTB   AL, (DI)0x02de 00734 (main.go:14)   MOVQ    $1, 8(DI)0x02e6 00742 (main.go:14)   PCDATA  $0, $-20x02e6 00742 (main.go:14)   PCDATA  $1, $-20x02e6 00742 (main.go:14)   CMPL    runtime.writeBarrier(SB), $00x02ed 00749 (main.go:14)   JEQ 7560x02ef 00751 (main.go:14)   JMP 18640x02f4 00756 (main.go:14)   LEAQ    go.string."2"(SB), AX0x02fb 00763 (main.go:14)   MOVQ    AX, (DI)0x02fe 00766 (main.go:14)   JMP 7680x0300 00768 (main.go:15)   PCDATA  $0, $10x0300 00768 (main.go:15)   PCDATA  $1, $30x0300 00768 (main.go:15)   MOVQ    "".m3+64(SP), AX0x0305 00773 (main.go:15)   PCDATA  $0, $00x0305 00773 (main.go:15)   PCDATA  $1, $40x0305 00773 (main.go:15)   MOVQ    AX, ""..autotmp_10+200(SP)0x030d 00781 (main.go:15)   PCDATA  $0, $40x030d 00781 (main.go:15)   PCDATA  $1, $70x030d 00781 (main.go:15)   LEAQ    ""..autotmp_11+544(SP), DI0x0315 00789 (main.go:15)   XORPS   X0, X00x0318 00792 (main.go:15)   PCDATA  $0, $00x0318 00792 (main.go:15)   LEAQ    -32(DI), DI0x031c 00796 (main.go:15)   DUFFZERO    $2730x032f 00815 (main.go:15)   PCDATA  $0, $10x032f 00815 (main.go:15)   LEAQ    type.map[string]string(SB), AX0x0336 00822 (main.go:15)   PCDATA  $0, $00x0336 00822 (main.go:15)   MOVQ    AX, (SP)0x033a 00826 (main.go:15)   PCDATA  $0, $10x033a 00826 (main.go:15)   PCDATA  $1, $80x033a 00826 (main.go:15)   MOVQ    ""..autotmp_10+200(SP), AX0x0342 00834 (main.go:15)   PCDATA  $0, $00x0342 00834 (main.go:15)   MOVQ    AX, 8(SP)0x0347 00839 (main.go:15)   PCDATA  $0, $10x0347 00839 (main.go:15)   LEAQ    ""..autotmp_11+544(SP), AX0x034f 00847 (main.go:15)   PCDATA  $0, $00x034f 00847 (main.go:15)   MOVQ    AX, 16(SP)0x0354 00852 (main.go:15)   CALL    runtime.mapiterinit(SB)0x0359 00857 (main.go:15)   JMP 8590x035b 00859 (main.go:15)   CMPQ    ""..autotmp_11+544(SP), $00x0364 00868 (main.go:15)   JNE 8750x0366 00870 (main.go:15)   JMP 13290x036b 00875 (main.go:15)   PCDATA  $0, $10x036b 00875 (main.go:15)   MOVQ    ""..autotmp_11+552(SP), AX0x0373 00883 (main.go:15)   TESTB   AL, (AX)0x0375 00885 (main.go:15)   MOVQ    8(AX), CX0x0379 00889 (main.go:15)   MOVQ    (AX), AX0x037c 00892 (main.go:15)   PCDATA  $0, $00x037c 00892 (main.go:15)   PCDATA  $1, $90x037c 00892 (main.go:15)   MOVQ    AX, ""..autotmp_25+288(SP)0x0384 00900 (main.go:15)   MOVQ    CX, ""..autotmp_25+296(SP)0x038c 00908 (main.go:15)   PCDATA  $0, $10x038c 00908 (main.go:15)   MOVQ    ""..autotmp_11+544(SP), AX0x0394 00916 (main.go:15)   TESTB   AL, (AX)0x0396 00918 (main.go:15)   MOVQ    8(AX), CX0x039a 00922 (main.go:15)   MOVQ    (AX), AX0x039d 00925 (main.go:15)   PCDATA  $0, $00x039d 00925 (main.go:15)   PCDATA  $1, $100x039d 00925 (main.go:15)   MOVQ    AX, "".k+256(SP)0x03a5 00933 (main.go:15)   MOVQ    CX, "".k+264(SP)0x03ad 00941 (main.go:15)   MOVQ    ""..autotmp_25+296(SP), AX0x03b5 00949 (main.go:15)   PCDATA  $0, $50x03b5 00949 (main.go:15)   PCDATA  $1, $110x03b5 00949 (main.go:15)   MOVQ    ""..autotmp_25+288(SP), CX0x03bd 00957 (main.go:15)   PCDATA  $0, $00x03bd 00957 (main.go:15)   PCDATA  $1, $120x03bd 00957 (main.go:15)   MOVQ    CX, "".v+240(SP)0x03c5 00965 (main.go:15)   MOVQ    AX, "".v+248(SP)0x03cd 00973 (main.go:16)   MOVQ    "".k+264(SP), AX0x03d5 00981 (main.go:16)   PCDATA  $0, $50x03d5 00981 (main.go:16)   PCDATA  $1, $130x03d5 00981 (main.go:16)   MOVQ    "".k+256(SP), CX0x03dd 00989 (main.go:16)   PCDATA  $0, $00x03dd 00989 (main.go:16)   MOVQ    CX, (SP)0x03e1 00993 (main.go:16)   MOVQ    AX, 8(SP)0x03e6 00998 (main.go:16)   CALL    runtime.convTstring(SB)0x03eb 01003 (main.go:16)   PCDATA  $0, $10x03eb 01003 (main.go:16)   MOVQ    16(SP), AX0x03f0 01008 (main.go:16)   PCDATA  $0, $00x03f0 01008 (main.go:16)   PCDATA  $1, $140x03f0 01008 (main.go:16)   MOVQ    AX, ""..autotmp_26+152(SP)0x03f8 01016 (main.go:16)   PCDATA  $1, $150x03f8 01016 (main.go:16)   XORPS   X0, X00x03fb 01019 (main.go:16)   MOVUPS  X0, ""..autotmp_9+272(SP)0x0403 01027 (main.go:16)   PCDATA  $0, $10x0403 01027 (main.go:16)   PCDATA  $1, $140x0403 01027 (main.go:16)   LEAQ    ""..autotmp_9+272(SP), AX0x040b 01035 (main.go:16)   MOVQ    AX, ""..autotmp_28+144(SP)0x0413 01043 (main.go:16)   TESTB   AL, (AX)0x0415 01045 (main.go:16)   PCDATA  $0, $20x0415 01045 (main.go:16)   PCDATA  $1, $130x0415 01045 (main.go:16)   MOVQ    ""..autotmp_26+152(SP), CX0x041d 01053 (main.go:16)   PCDATA  $0, $30x041d 01053 (main.go:16)   LEAQ    type.string(SB), DX0x0424 01060 (main.go:16)   PCDATA  $0, $20x0424 01060 (main.go:16)   MOVQ    DX, ""..autotmp_9+272(SP)0x042c 01068 (main.go:16)   PCDATA  $0, $10x042c 01068 (main.go:16)   MOVQ    CX, ""..autotmp_9+280(SP)0x0434 01076 (main.go:16)   TESTB   AL, (AX)0x0436 01078 (main.go:16)   JMP 10800x0438 01080 (main.go:16)   MOVQ    AX, ""..autotmp_27+424(SP)0x0440 01088 (main.go:16)   MOVQ    $1, ""..autotmp_27+432(SP)0x044c 01100 (main.go:16)   MOVQ    $1, ""..autotmp_27+440(SP)0x0458 01112 (main.go:16)   PCDATA  $0, $00x0458 01112 (main.go:16)   MOVQ    AX, (SP)0x045c 01116 (main.go:16)   MOVQ    $1, 8(SP)0x0465 01125 (main.go:16)   MOVQ    $1, 16(SP)0x046e 01134 (main.go:16)   CALL    fmt.Println(SB)0x0473 01139 (main.go:17)   MOVQ    "".v+248(SP), AX0x047b 01147 (main.go:17)   PCDATA  $0, $50x047b 01147 (main.go:17)   PCDATA  $1, $80x047b 01147 (main.go:17)   MOVQ    "".v+240(SP), CX0x0483 01155 (main.go:17)   PCDATA  $0, $00x0483 01155 (main.go:17)   MOVQ    CX, (SP)0x0487 01159 (main.go:17)   MOVQ    AX, 8(SP)0x048c 01164 (main.go:17)   CALL    runtime.convTstring(SB)0x0491 01169 (main.go:17)   PCDATA  $0, $10x0491 01169 (main.go:17)   MOVQ    16(SP), AX0x0496 01174 (main.go:17)   PCDATA  $0, $00x0496 01174 (main.go:17)   PCDATA  $1, $160x0496 01174 (main.go:17)   MOVQ    AX, ""..autotmp_29+136(SP)0x049e 01182 (main.go:17)   PCDATA  $1, $170x049e 01182 (main.go:17)   XORPS   X0, X00x04a1 01185 (main.go:17)   MOVUPS  X0, ""..autotmp_9+272(SP)0x04a9 01193 (main.go:17)   PCDATA  $0, $10x04a9 01193 (main.go:17)   PCDATA  $1, $160x04a9 01193 (main.go:17)   LEAQ    ""..autotmp_9+272(SP), AX0x04b1 01201 (main.go:17)   MOVQ    AX, ""..autotmp_31+128(SP)0x04b9 01209 (main.go:17)   TESTB   AL, (AX)0x04bb 01211 (main.go:17)   PCDATA  $0, $20x04bb 01211 (main.go:17)   PCDATA  $1, $80x04bb 01211 (main.go:17)   MOVQ    ""..autotmp_29+136(SP), CX0x04c3 01219 (main.go:17)   PCDATA  $0, $30x04c3 01219 (main.go:17)   LEAQ    type.string(SB), DX0x04ca 01226 (main.go:17)   PCDATA  $0, $20x04ca 01226 (main.go:17)   MOVQ    DX, ""..autotmp_9+272(SP)0x04d2 01234 (main.go:17)   PCDATA  $0, $10x04d2 01234 (main.go:17)   MOVQ    CX, ""..autotmp_9+280(SP)0x04da 01242 (main.go:17)   TESTB   AL, (AX)0x04dc 01244 (main.go:17)   JMP 12460x04de 01246 (main.go:17)   MOVQ    AX, ""..autotmp_30+400(SP)0x04e6 01254 (main.go:17)   MOVQ    $1, ""..autotmp_30+408(SP)0x04f2 01266 (main.go:17)   MOVQ    $1, ""..autotmp_30+416(SP)0x04fe 01278 (main.go:17)   PCDATA  $0, $00x04fe 01278 (main.go:17)   MOVQ    AX, (SP)0x0502 01282 (main.go:17)   MOVQ    $1, 8(SP)0x050b 01291 (main.go:17)   MOVQ    $1, 16(SP)0x0514 01300 (main.go:17)   CALL    fmt.Println(SB)0x0519 01305 (main.go:17)   JMP 13070x051b 01307 (main.go:15)   PCDATA  $0, $10x051b 01307 (main.go:15)   LEAQ    ""..autotmp_11+544(SP), AX0x0523 01315 (main.go:15)   PCDATA  $0, $00x0523 01315 (main.go:15)   MOVQ    AX, (SP)0x0527 01319 (main.go:15)   CALL    runtime.mapiternext(SB)0x052c 01324 (main.go:15)   JMP 8590x0531 01329 (main.go:19)   PCDATA  $0, $10x0531 01329 (main.go:19)   PCDATA  $1, $30x0531 01329 (main.go:19)   LEAQ    type.map[string]string(SB), AX0x0538 01336 (main.go:19)   PCDATA  $0, $00x0538 01336 (main.go:19)   MOVQ    AX, (SP)0x053c 01340 (main.go:19)   PCDATA  $0, $10x053c 01340 (main.go:19)   MOVQ    "".m3+64(SP), AX0x0541 01345 (main.go:19)   PCDATA  $0, $00x0541 01345 (main.go:19)   MOVQ    AX, 8(SP)0x0546 01350 (main.go:19)   PCDATA  $0, $10x0546 01350 (main.go:19)   LEAQ    go.string."1"(SB), AX0x054d 01357 (main.go:19)   PCDATA  $0, $00x054d 01357 (main.go:19)   MOVQ    AX, 16(SP)0x0552 01362 (main.go:19)   MOVQ    $1, 24(SP)0x055b 01371 (main.go:19)   CALL    runtime.mapaccess1_faststr(SB)0x0560 01376 (main.go:19)   PCDATA  $0, $10x0560 01376 (main.go:19)   MOVQ    32(SP), AX0x0565 01381 (main.go:19)   PCDATA  $0, $20x0565 01381 (main.go:19)   MOVQ    (AX), CX0x0568 01384 (main.go:19)   PCDATA  $0, $50x0568 01384 (main.go:19)   MOVQ    8(AX), AX0x056c 01388 (main.go:19)   MOVQ    CX, "".v1+224(SP)0x0574 01396 (main.go:19)   MOVQ    AX, "".v1+232(SP)0x057c 01404 (main.go:20)   PCDATA  $0, $00x057c 01404 (main.go:20)   MOVQ    CX, (SP)0x0580 01408 (main.go:20)   MOVQ    AX, 8(SP)0x0585 01413 (main.go:20)   CALL    runtime.convTstring(SB)0x058a 01418 (main.go:20)   PCDATA  $0, $10x058a 01418 (main.go:20)   MOVQ    16(SP), AX0x058f 01423 (main.go:20)   PCDATA  $0, $00x058f 01423 (main.go:20)   PCDATA  $1, $180x058f 01423 (main.go:20)   MOVQ    AX, ""..autotmp_32+120(SP)0x0594 01428 (main.go:20)   PCDATA  $1, $190x0594 01428 (main.go:20)   XORPS   X0, X00x0597 01431 (main.go:20)   MOVUPS  X0, ""..autotmp_9+272(SP)0x059f 01439 (main.go:20)   PCDATA  $0, $10x059f 01439 (main.go:20)   PCDATA  $1, $180x059f 01439 (main.go:20)   LEAQ    ""..autotmp_9+272(SP), AX0x05a7 01447 (main.go:20)   MOVQ    AX, ""..autotmp_34+112(SP)0x05ac 01452 (main.go:20)   TESTB   AL, (AX)0x05ae 01454 (main.go:20)   PCDATA  $0, $20x05ae 01454 (main.go:20)   PCDATA  $1, $30x05ae 01454 (main.go:20)   MOVQ    ""..autotmp_32+120(SP), CX0x05b3 01459 (main.go:20)   PCDATA  $0, $30x05b3 01459 (main.go:20)   LEAQ    type.string(SB), DX0x05ba 01466 (main.go:20)   PCDATA  $0, $20x05ba 01466 (main.go:20)   MOVQ    DX, ""..autotmp_9+272(SP)0x05c2 01474 (main.go:20)   PCDATA  $0, $10x05c2 01474 (main.go:20)   MOVQ    CX, ""..autotmp_9+280(SP)0x05ca 01482 (main.go:20)   TESTB   AL, (AX)0x05cc 01484 (main.go:20)   JMP 14860x05ce 01486 (main.go:20)   MOVQ    AX, ""..autotmp_33+376(SP)0x05d6 01494 (main.go:20)   MOVQ    $1, ""..autotmp_33+384(SP)0x05e2 01506 (main.go:20)   MOVQ    $1, ""..autotmp_33+392(SP)0x05ee 01518 (main.go:20)   PCDATA  $0, $00x05ee 01518 (main.go:20)   MOVQ    AX, (SP)0x05f2 01522 (main.go:20)   MOVQ    $1, 8(SP)0x05fb 01531 (main.go:20)   MOVQ    $1, 16(SP)0x0604 01540 (main.go:20)   CALL    fmt.Println(SB)0x0609 01545 (main.go:21)   XORPS   X0, X00x060c 01548 (main.go:21)   MOVUPS  X0, ""..autotmp_12+336(SP)0x0614 01556 (main.go:21)   PCDATA  $0, $10x0614 01556 (main.go:21)   LEAQ    type.map[string]string(SB), AX0x061b 01563 (main.go:21)   PCDATA  $0, $00x061b 01563 (main.go:21)   MOVQ    AX, (SP)0x061f 01567 (main.go:21)   PCDATA  $0, $10x061f 01567 (main.go:21)   PCDATA  $1, $00x061f 01567 (main.go:21)   MOVQ    "".m3+64(SP), AX0x0624 01572 (main.go:21)   PCDATA  $0, $00x0624 01572 (main.go:21)   MOVQ    AX, 8(SP)0x0629 01577 (main.go:21)   PCDATA  $0, $10x0629 01577 (main.go:21)   LEAQ    go.string."1"(SB), AX0x0630 01584 (main.go:21)   PCDATA  $0, $00x0630 01584 (main.go:21)   MOVQ    AX, 16(SP)0x0635 01589 (main.go:21)   MOVQ    $1, 24(SP)0x063e 01598 (main.go:21)   CALL    runtime.mapaccess2_faststr(SB)0x0643 01603 (main.go:21)   PCDATA  $0, $10x0643 01603 (main.go:21)   MOVQ    32(SP), AX0x0648 01608 (main.go:21)   PCDATA  $0, $00x0648 01608 (main.go:21)   PCDATA  $1, $200x0648 01608 (main.go:21)   MOVQ    AX, ""..autotmp_35+104(SP)0x064d 01613 (main.go:21)   MOVBLZX 40(SP), AX0x0652 01618 (main.go:21)   MOVB    AL, ""..autotmp_13+55(SP)0x0656 01622 (main.go:21)   PCDATA  $0, $10x0656 01622 (main.go:21)   PCDATA  $1, $00x0656 01622 (main.go:21)   MOVQ    ""..autotmp_35+104(SP), AX0x065b 01627 (main.go:21)   MOVQ    8(AX), CX0x065f 01631 (main.go:21)   MOVQ    (AX), AX0x0662 01634 (main.go:21)   MOVQ    AX, ""..autotmp_12+336(SP)0x066a 01642 (main.go:21)   MOVQ    CX, ""..autotmp_12+344(SP)0x0672 01650 (main.go:21)   PCDATA  $0, $00x0672 01650 (main.go:21)   PCDATA  $1, $210x0672 01650 (main.go:21)   MOVQ    AX, "".v2+208(SP)0x067a 01658 (main.go:21)   MOVQ    CX, "".v2+216(SP)0x0682 01666 (main.go:21)   MOVBLZX ""..autotmp_13+55(SP), AX0x0687 01671 (main.go:21)   MOVB    AL, "".ok+54(SP)0x068b 01675 (main.go:21)   CMPB    "".ok+54(SP), $00x0690 01680 (main.go:21)   JNE 16870x0692 01682 (main.go:21)   JMP 18620x0697 01687 (main.go:22)   MOVQ    "".v2+216(SP), AX0x069f 01695 (main.go:22)   PCDATA  $0, $50x069f 01695 (main.go:22)   PCDATA  $1, $00x069f 01695 (main.go:22)   MOVQ    "".v2+208(SP), CX0x06a7 01703 (main.go:22)   PCDATA  $0, $00x06a7 01703 (main.go:22)   MOVQ    CX, (SP)0x06ab 01707 (main.go:22)   MOVQ    AX, 8(SP)0x06b0 01712 (main.go:22)   CALL    runtime.convTstring(SB)0x06b5 01717 (main.go:22)   PCDATA  $0, $10x06b5 01717 (main.go:22)   MOVQ    16(SP), AX0x06ba 01722 (main.go:22)   PCDATA  $0, $00x06ba 01722 (main.go:22)   PCDATA  $1, $220x06ba 01722 (main.go:22)   MOVQ    AX, ""..autotmp_36+96(SP)0x06bf 01727 (main.go:22)   PCDATA  $1, $230x06bf 01727 (main.go:22)   XORPS   X0, X00x06c2 01730 (main.go:22)   MOVUPS  X0, ""..autotmp_9+272(SP)0x06ca 01738 (main.go:22)   PCDATA  $0, $10x06ca 01738 (main.go:22)   PCDATA  $1, $220x06ca 01738 (main.go:22)   LEAQ    ""..autotmp_9+272(SP), AX0x06d2 01746 (main.go:22)   MOVQ    AX, ""..autotmp_38+88(SP)0x06d7 01751 (main.go:22)   TESTB   AL, (AX)0x06d9 01753 (main.go:22)   PCDATA  $0, $20x06d9 01753 (main.go:22)   PCDATA  $1, $00x06d9 01753 (main.go:22)   MOVQ    ""..autotmp_36+96(SP), CX0x06de 01758 (main.go:22)   PCDATA  $0, $30x06de 01758 (main.go:22)   LEAQ    type.string(SB), DX0x06e5 01765 (main.go:22)   PCDATA  $0, $20x06e5 01765 (main.go:22)   MOVQ    DX, ""..autotmp_9+272(SP)0x06ed 01773 (main.go:22)   PCDATA  $0, $10x06ed 01773 (main.go:22)   MOVQ    CX, ""..autotmp_9+280(SP)0x06f5 01781 (main.go:22)   TESTB   AL, (AX)0x06f7 01783 (main.go:22)   JMP 17850x06f9 01785 (main.go:22)   MOVQ    AX, ""..autotmp_37+352(SP)0x0701 01793 (main.go:22)   MOVQ    $1, ""..autotmp_37+360(SP)0x070d 01805 (main.go:22)   MOVQ    $1, ""..autotmp_37+368(SP)0x0719 01817 (main.go:22)   PCDATA  $0, $00x0719 01817 (main.go:22)   MOVQ    AX, (SP)0x071d 01821 (main.go:22)   MOVQ    $1, 8(SP)0x0726 01830 (main.go:22)   MOVQ    $1, 16(SP)0x072f 01839 (main.go:22)   CALL    fmt.Println(SB)0x0734 01844 (main.go:22)   JMP 18460x0736 01846 (<unknown line number>)    PCDATA  $0, $-10x0736 01846 (<unknown line number>)    PCDATA  $1, $-10x0736 01846 (<unknown line number>)    MOVQ    640(SP), BP0x073e 01854 (<unknown line number>)    ADDQ    $648, SP0x0745 01861 (<unknown line number>)    RET0x0746 01862 (main.go:21)   JMP 18460x0748 01864 (main.go:14)   PCDATA  $0, $-20x0748 01864 (main.go:14)   PCDATA  $1, $-20x0748 01864 (main.go:14)   LEAQ    go.string."2"(SB), AX0x074f 01871 (main.go:14)   CALL    runtime.gcWriteBarrier(SB)0x0754 01876 (main.go:14)   JMP 7680x0759 01881 (main.go:14)   NOP0x0759 01881 (main.go:5)    PCDATA  $1, $-10x0759 01881 (main.go:5)    PCDATA  $0, $-20x0759 01881 (main.go:5)    CALL    runtime.morestack_noctxt(SB)0x075e 01886 (main.go:5)    PCDATA  $0, $-10x075e 01886 (main.go:5)    JMP 0

东西有点多,但是我们只分析几个重点 - main.go的第6行、第8行和第12行的map申明分别对应着main.txt23行、57行和132行,都是调用的runtime.makemap_small方法 - main.go的第10行对应着main.txt的97行runtime.makemap方法 - main.go的第14行的赋值对应着main.txt的184行runtime.mapassign_faststr方法 - main.go的第15行的循环对应着main.txt第224行的runtime.mapiterinit方法初始化得到迭代器 - main.go的第19行和第21行分别对着main.txt2个不同的方法runtime.mapaccess1_faststr和runtime.mapaccess2_faststr

runtime/map.go的方法包括上面列举的方法:runtime.makemap_small、runtime.makemap和runtime.mapiterinit方法

3b9a24e17f95e9e14eb4762c06bd864d.png

由于我的示例代码的map的key是string类型,故runtime.mapassign_faststr、runtime.mapaccess1_faststr和runtime.mapaccess2_faststr方法在runtime/map_faststr.go代码里面,该文件优化了string类型的key的操作:

2dedd5b6840803bd66027c4a607cecb4.png

go的map对应的结构体hmap

go的map的基础结构体是hmap,在runtime/map.go中,

// A header for a Go map.
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.// map存储的键值对个数count     int // # live cells == size of map.  Must be first (used by len() builtin)// 表示map的一些标志位flags     uint8// map的桶的2的对数就是B值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// hash种子hash0     uint32 // hash seed// 桶,真正存数据的地方,2^B个桶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// 从oldbuckets迁移到新的buckets的进度nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)// 当key不是指针类型的数据的时候,里面会存溢出桶,这样会避免go的扫描extra *mapextra // optional fields
}

既然是map结构体,为何注释说是一个header呢?这是因为buckets和oldbuckets这2个字段并没有真正存取数据,只是存了一个指针,指向存取buckets的地址,故我们在使用过程中拷贝hmap的时候,并没有真正拷贝map的数据,只是拷贝了hmap这个结构体的一些数据。 在看看hmap的字段mapextra:

// mapextra holds fields that are not present on all maps.
type mapextra struct {// If both key and elem do not contain pointers and are inline, then we mark bucket// 如果key和value都不包括指针并且内敛,然后我们就标记bucket没有指针// type as containing no pointers. This avoids scanning such maps.// 这样会避免gc扫描// However, bmap.overflow is a pointer. In order to keep overflow buckets// 但是,虽然key和value不包括指针,但是逸出桶却是个指针,为了让逸出桶一直// alive, we store pointers to all overflow buckets in hmap.extra.overflow and hmap.extra.oldoverflow.// 存在,所以就把逸出桶和需要迁移的逸出桶的指针存到hamp的extra字段里面// overflow and oldoverflow are only used if key and elem do not contain pointers.// 如果key和elme包含指针,overflow和oldoverflow就不会被使用了// overflow contains overflow buckets for hmap.buckets.// oldoverflow contains overflow buckets for hmap.oldbuckets.// The indirection allows to store a pointer to the slice in hiter.overflow    *[]*bmapoldoverflow *[]*bmap// nextOverflow holds a pointer to a free overflow bucket.nextOverflow *bmap
}

如mapextra结构体为啥说有些字段并不会在所有map里面全部都有呢?mapextra是一个为了优化bucket而设计的,当key或value是指针的时候,此时overflow和oldoverflow就不会被使用,只有nextOverflow会被使用,该字段保存了预先申请的逸出桶,在没有发生扩容的时候,而一个桶或者说bmap的8个tophash都被使用完了,那么就要考虑使用逸出桶。 当key和value都没有指针的时候bucket的bmap的_type的ptrdata就是0,意味着该结构体是没有指针的,申请bmap内存的时候,会申请一个没有指针的span,这样会避免gc扫描该内存,会提高效率,但是bmap的最后一个内存块是确确实实存放指针的,所以用uintptr存储着该map的逸出桶的地址,但是由于没有指向下一个逸出桶,可能会被gc回收掉,所以就需要overflow存取指向该逸出桶的指针避免被gc回收掉。 overflow和oldoverflow的用处差不多,只是oldoverflow为了迁移使用,后面的系列会详说。

bucket的结构体bmap

bmap就是真正存数据的结构体了,bmap在源码中定义十分简单:

// A bucket for a Go map.
type bmap struct {// tophash generally contains the top byte of the hash value// for each key in this bucket. If tophash[0] < minTopHash,// tophash[0] is a bucket evacuation state instead.tophash [bucketCnt]uint8// Followed by bucketCnt keys and then bucketCnt elems.// NOTE: packing all the keys together and then all the elems together makes the// code a bit more complicated than alternating key/elem/key/elem/... but it allows// us to eliminate padding which would be needed for, e.g., map[int64]int8.// Followed by an overflow pointer.
}

但其实真正的在内存中分配的结构体是这样的:

// A bucket for a Go map.
type bmap struct {// tophash generally contains the top byte of the hash value// for each key in this bucket. If tophash[0] < minTopHash,// tophash[0] is a bucket evacuation state instead.tophash [bucketCnt]uint8keys [bucketCnt]string // 由于我举例的key是string,故我这里写stringvalues [bucketCnt]string // 由于上面我的例子的value的类型是string,故这里也是stringpointer unsafe.pointer  // 由于key和value都是指针,所以这里是一个指针// Followed by bucketCnt keys and then bucketCnt elems.// NOTE: packing all the keys together and then all the elems together makes the// code a bit more complicated than alternating key/elem/key/elem/... but it allows// us to eliminate padding which would be needed for, e.g., map[int64]int8.// Followed by an overflow pointer.
}

隐藏的字段在map源码中都是靠地址偏移来得到,tophash我们能轻易找到位置,但是如何找到keys、values和pointer呢? 在map中是这么做的:

dataOffset = unsafe.Offsetof(struct {b bmapv int64}{}.v)

在64位机器上,需要对齐8个字节,这里int64正好也是8个字节,所以恰好解决内存对齐的问题,找到v的起始地址也就是values的起始地址:

dataOffset+bucketCnt*2*sys.PtrSize // string16个字节,相当于2个指针,bucketCnt等于8

pointer的起始地址

dataOffset+bucketCnt*2*sys.PtrSize+sys.PtrSize

tophash存的是key的hash高8位,为了方便查找key,为什么keys和values分别存在一堆呢?不是k|v|k|v这种呢?由于key和value的变量类型可能不一样,对齐系数不一致,可能导致内存不紧凑而浪费内存,所以把8个keys存到一堆,8个values存到一堆,然后最后在pointer之前对齐就可以了。所以此时也能算出来整个bmap的大小:

bucketCnt*(uint8的字节为1)+bucketCnt*(string的字节16)+bucketCnt*(string的字节16)+指针大小8字节 = 272

在真正调试的时候如查看bucket里面的具体的key和value呢?这里给大家展示一个小技巧,如果大家有其他方法,可以留言讨论:

type dmap struct {tophash        [bucketCnt]uint8debugKeys      [bucketCnt]stringdebugElems     [bucketCnt]string//debugOverflows unsafe.PointerdebugOverflows uintptr
}

这是我定义的调试结构体,将该代码和bmap的结构体放到一堆,当你获取到bmap桶的地址的时候,就可以如下转换,就可以查看bmap的具体值了:

b0 := (*dmap)(add(buckets, uintptr(0)*uintptr(t.bucketsize)))println(b0.debugOverflows)

buckets假设是桶数组的起始地址,加上bucketsize就会得到第二个桶的起始地址,然后直接转型为*dmap,最后你可以可以打印出来你想查看的真实的值了。

map的整体结构

c04fe0552f6e526973673711b868fa68.png

如果申请内存桶的时候又多余的溢出桶,那么mapextra的nextOverflow就会指向[]bmap其中的某块桶的地址,地址后之后的桶都是溢出桶。在一个桶装不下的时候,会去溢出桶拿桶然后bmap的overflow指向溢出桶。

总结

上面大概介绍了map的数据结构,后面系列map的具体代码分析,包括增、删、改、查、扩容等都会分篇细解,如有不足之处,请共同讨论学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/529619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大学数学建模大赛是用计算机,北京大学第十届“江泽涵杯”数学建模与计算机应用竞赛试题...

消息来源&#xff1a;http://www.math.pku.edu.cn:8000/news/read.php?newsid8014A题&#xff1a;投篮问题投篮是篮球运动中一项关键性技术&#xff0c;是一项重要的得分手段。在篮球赛中有三种特殊的投篮方式&#xff0c;“三分球”、“两分球”和“一分球(罚篮)”。其中&…

dynamo方程怎么写_【简明自控】为什么特征方程如此重要

简明自动控制——为什么特征方程如此重要。热场视频&#xff1a;自平衡杆-双轴反作用轮倒立摆_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com顶个棍子&#xff01;具有主动脚轮的全向移动机器人_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com我自行车怎么少…

和佳股份有没有纳米机器人_新高赛复赛入围项目(49)一种纳米硅质绝热材料及其制备方法...

点击上方“蓝字”关注我们“2020中国山东新旧动能转换高价值专利培育大赛”(简称“新高赛”)是由山东省市场监督管理局(知识产权局)主办&#xff0c;由山东省知识产权事业发展中心、知识产权出版社有限责任公司共同承办的以新旧动能转换高价值专利培育为主题的创新大赛。新高赛…

mastercam加工报表生成_2020北京加工中心编程培训工厂教学行业

2020北京加工中心编程培训工厂教学行业河北德玛数控培训自办工厂 全程四轴五轴实践 学生直接面对客户 承揽加工各种异形件复杂件 终身技术支持 可勤工俭学 解决企业各种技术问题&#xff0c;每个校区都有实训车间&#xff0c;实训图档不限、不限、时间不限、并且不另收费&#…

背景调查 跳槽_分享 | 录用背景调查,查的到底是什么?

招聘对于HR而言&#xff0c;是一项常规工作&#xff0c;同时也是一项非常重要的工作&#xff0c;招聘有一系列的步骤和程序&#xff0c;每一道步骤和程序都必不可少&#xff0c;显得那么的重要&#xff0c;这其中包括我们常说的笔试、面试、体检&#xff0c;还包括不常说的正式…

.class文件转换.java_Java中的动态链接VS操作系统动态链接

在操作系统OS中为了优化内存的使用会采用一种动态链接方式&#xff0c;一个文件想要在操作系统中运行必须经过编译、汇编译、链接、装载等步骤。可以参考Java程序是怎么跑起来的。本篇主要讲解Java栈帧中动态链接部分与操作系统的的动态链接的区别与联系操纵系统为什么需要动态…

宏观经济学gdp计算方法_宏观经济学考研的重要考点

宏观经济学考研重要考点西方国民收入核算宏观经济学的特点;国内生产总值;核算国民收入的两种算法(支出法和收入法);国内生产总值;个人可支配收入;国民收入的基本公式;名义GDP和实际GDP。要求&#xff1a;重点掌握本章基本概念及计算。简单国民收入决定理论均衡产出;凯恩斯的消费…

json符号解释大全_牛年汪姓男孩高端大气的名字大全

牛年汪姓男孩高端大气的名字大全 张桉宁起名分享牛年汪姓男孩高端大气的名字大全&#xff1a;给男孩起名有很多的讲究&#xff0c;需要从多个方面考虑。牛年汪姓男孩如何起一个高端大气的好名字&#xff0c;是家长朋友们都十分重视的。给牛年的汪姓男孩起一个高端的名字&#x…

变电站计算机在线监控系统,变电站环境在线监测系统

原标题&#xff1a;变电站环境在线监测系统概述随着计算机技术、网络通讯技术以及电力系统保护技术的发展&#xff0c;配电室的自动化运行水平不断提高&#xff0c;大大减少了人为操作&#xff0c;使配电室的无人值守逐步变成了可能。配电的可靠和安全是整个电能管理系统中的一…

什么意思是谁_舔狗是什么意思?如果不是真的喜欢谁又愿意做舔狗呢出处?

[海峡网]网络上面经常会出现一些新的词句&#xff0c;比如最近舔狗这个词就经常出现在大家的视线中。相信很多小伙伴都知道&#xff0c;最近关于虎牙的包子的事情也是挺多的&#xff0c;不过关于包桑的梗也是很多&#xff0c;那么关于包桑的这句“如果不是真的喜欢&#xff0c;…

计算机控制面板图标显示,Win8桌面如何有计算机/控制面板图标

Win8桌面如何有计算机/控制面板图标2013年06月04日 00:44作者&#xff1a;马承平编辑&#xff1a;马承平文章出处&#xff1a;泡泡网原创分享泡泡网系统工具频道6月4日 全新Windows8系统给我们带来不仅是超炫的动态磁贴展示&#xff0c;更有新增超级按钮项&#xff0c;它大大集…

计算机专业好还是铁道运输管理好,铁道运输管理专业主要是干什么的?

铁道运输管理专业主要是干什么的?铁道运输管理专业主要学什么&#xff1f;学铁道运营管理好就业吗&#xff1f;1、铁道交通运营管理专业主要培养德、智、体、美各方面全面发展&#xff0c;掌握所必需的基本理论和专业知识&#xff0c;有较高的综合素质和较强的铁道交通运营管理…

51单片机基本刷屏测试实验_51单片机开发基础8——实时时钟实验

8.1 实时时钟简介RTC(Real Time Clock)&#xff0c;是实时时钟的缩写&#xff0c;实时时钟是日常生活中应用最为广泛的功能。它为人们提供精确的实时时间&#xff0c;或者为电子系统提供精确的时间基准&#xff0c;目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。有…

tensorflow超参数优化_机器学习模型的超参数优化

引言模型优化是机器学习算法实现中最困难的挑战之一。机器学习和深度学习理论的所有分支都致力于模型的优化。机器学习中的超参数优化旨在寻找使得机器学习算法在验证数据集上表现性能最佳的超参数。超参数与一般模型参数不同&#xff0c;超参数是在训练前提前设置的。举例来说…

南充一中计算机机房被盗,四川省CCF CSP-JS第一轮认证考试在南充一中成功举行...

10月11日&#xff0c;参加四川省青少年信息技术非专业级软件能力认证(CSP-JS)第一轮认证考试的来自遂宁市、南充市、达州市的220名参与认证的选手齐聚南充一中。软件能力认证(Certified Software Professional&#xff0c;简称CSP)&#xff0c;是由中国计算机学会举办&#xff…

软件测试浏览器的上传功能,关于浏览器上传控件的识别 - asoqa的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

1&#xff1a;基本的上传控件(图1、图2)图1&#xff1a;MSN上传照片图2&#xff1a;ogame论坛上传图片这种基本的上传控件QTP脚本在处理时有两种方式&#xff1a;1.1 识别Windows选择框对象Dialog和WinListView&#xff0c;有点繁琐&#xff0c;但是能精确的定位用户操作。Brow…

串灯控制盒去掉怎么接_单双向可控硅好坏怎么判断

大功率可控硅好坏判断单向可控硅的工作原理&#xff1a; 可控硅导通条件&#xff1a;一是可控硅阳极与阴极间必须加正向电压&#xff0c;二是控制极也要加正向电压。以上两个条件 单向可控硅的工作原理图&#xff3b;1&#xff3d;必须同时具备&#xff0c;可控硅才会处于导通状…

江西小学计算机说课稿,2019江西教师招聘面试-小学数学-说课稿

教师招聘面试-小学数学-说课稿——《分数的基本性质》尊敬的各位考官大家好&#xff0c;我是今天的X号考生&#xff0c;今天我说课的题目是《分数的基本性质》新课标指出&#xff1a;数学课程要面向全体学生&#xff0c;适应学生个性发展的需要&#xff0c;使得人人都能获得良好…

无光驱如何修复W7计算机,Win7电脑没有光驱怎么装系统?

现在很多人买台式电脑不会再配置光驱了&#xff0c;可是这就让人有疑问了&#xff0c;如果没有光驱怎么装系统呢&#xff1f;其实方法很简单&#xff0c;我们可以用U盘&#xff0c;但是要想使用U盘必须先制作启动盘&#xff0c;如果你不懂怎么制作启动盘的话&#xff0c;那就赶…

云函数查询_速览 | 京东云5月重要产品与功能更新

新增产品高可用组 正式发布产品概述&#xff1a;高可用组是京东云提供的云主机逻辑集合&#xff0c;高可用组内的云主机分散部署在相互隔离的物理资源上&#xff0c;当出现硬件故障或定时维护时只会影响部分云主机&#xff0c;客户业务仍为可用状态&#xff0c;本服务免费。流水…