[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-detail-ssr-56753032716618764":3},{"id":4,"title":5,"tag":6,"createTime":7,"updateTime":8,"renderedHtml":9,"description":10,"ogImageUrl":11},"56753032716618764","Go语言中的闭包详解","Go语言","2024-01-27","2024-04-02","\u003Ch2 id=\"h2-0-\">基本概念\u003C\u002Fh2>\n\u003Cp>Go 语言中闭包是引用了自由变量的函数，被引用的自由变量和函数一同存在，即使已经离开了自由变量的环境也不会被释放或者删除，在闭包中可以继续使用这个自由变量。闭包也可以说是一个函数和与其相关的引用环境组合而成的实体。简单来说，\u003Ccode>闭包=函数+引用环境\u003C\u002Fcode>。如下所示就是闭包的示意图：\u003C\u002Fp>\n\u003Cp>\u003Cimg class=\"article-img article-img-zoomable\" src=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202401272021155.png\" alt=\"image-20240125161017458\" loading=\"lazy\" decoding=\"async\" style=\"width: 100%; height: auto; max-width: 100%; display: block;\" srcset=\"https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202401272021155.png?imageMogr2\u002Fthumbnail\u002F400x\u002Fformat\u002Fwebp\u002Fquality\u002F85 400w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202401272021155.png?imageMogr2\u002Fthumbnail\u002F800x\u002Fformat\u002Fwebp\u002Fquality\u002F85 800w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202401272021155.png?imageMogr2\u002Fthumbnail\u002F1200x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1200w, https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202401272021155.png?imageMogr2\u002Fthumbnail\u002F1920x\u002Fformat\u002Fwebp\u002Fquality\u002F85 1920w\" sizes=\"(max-width: 576px) 100vw, (max-width: 992px) 90vw, 720px\">\u003C\u002Fp>\n\u003Cp>前面的概念可能还是不太好理解，下面是关于闭包的汇编分析。\u003C\u002Fp>\n\u003Ch2 id=\"h2-1-\">汇编分析\u003C\u002Fh2>\n\u003Ch3 id=\"h3-2--1\">例子 1\u003C\u002Fh3>\n\u003Cp>使用闭包写一个非常简单的测试代码：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"go\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">go\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-go\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    a \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">1\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">int\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        a \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">3\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> a\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>使用\u003Ccode>go tool compile -S -N -l main.go\u003C\u002Fcode>命令生成的核心汇编代码如下：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"text\" data-collapsible=\"true\" data-collapsed=\"true\" data-line-count=\"62\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">text\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-toggle ssr-code-toggle--head ssr-code-iconbtn\" type=\"button\" aria-expanded=\"true\" aria-label=\"收起代码\" title=\"收起\">\u003Csvg viewBox=\"0 0 24 24\" width=\"19\" height=\"19\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M12 8.59l-6.3 6.3 1.4 1.42L12 11.4l4.9 4.9 1.4-1.4z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-toggle ssr-code-toggle--head-expand ssr-code-iconbtn\" type=\"button\" aria-expanded=\"false\" aria-label=\"展开代码\" title=\"展开\">\u003Csvg viewBox=\"0 0 24 24\" width=\"19\" height=\"19\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M12 15.41l6.3-6.3-1.4-1.42L12 12.59 7.1 7.7l-1.4 1.4z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">16\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">17\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">18\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">19\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">20\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">21\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">22\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">23\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">24\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">25\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">26\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">27\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">28\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">29\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">30\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">31\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">32\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">33\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">34\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">35\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">36\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">37\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">38\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">39\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">40\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">41\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">42\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">43\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">44\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">45\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">46\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">47\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">48\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">49\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">50\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">51\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">52\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">53\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">54\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">55\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">56\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">57\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">58\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">59\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">60\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">61\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">62\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-text\">\u003Cspan class=\"ssr-code-line\">main.main STEXT size=56 args=0x0 locals=0x28 funcid=0x0 align=0x0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:3)        TEXT    main.main(SB), ABIInternal, $40-0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 栈溢出检查\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:3)        CMPQ    SP, 16(R14)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0004 00004 (main.go:3)        PCDATA  $0, $-2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0004 00004 (main.go:3)        JLS     49\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0006 00006 (main.go:3)        PCDATA  $0, $-1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 栈内存分配、保存旧栈的基地址和建立新栈帧\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0006 00006 (main.go:3)        SUBQ    $40, SP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000a 00010 (main.go:3)        MOVQ    BP, 32(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000f 00015 (main.go:3)        LEAQ    32(SP), BP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F gc垃圾处理\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0014 00020 (main.go:3)        FUNCDATA        $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0014 00020 (main.go:3)        FUNCDATA        $1, gclocals·EaPwxsZ75yY1hHMVZLmk6g==(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F a=1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0014 00020 (main.go:4)        MOVQ    $1, main.a+8(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把变量a的地址存储到AX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x001d 00029 (main.go:8)        LEAQ    main.a+8(SP), AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0022 00034 (main.go:8)        PCDATA  $1, $0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 调用匿名函数\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0022 00034 (main.go:8)        CALL    main.main.func1(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F BP地址恢复和栈空间回收\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0027 00039 (main.go:9)        MOVQ    32(SP), BP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x002c 00044 (main.go:9)        ADDQ    $40, SP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 函数返回\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0030 00048 (main.go:9)        RET\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0031 00049 (main.go:9)        NOP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0031 00049 (main.go:3)        PCDATA  $1, $-1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0031 00049 (main.go:3)        PCDATA  $0, $-2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0031 00049 (main.go:3)        CALL    runtime.morestack_noctxt(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0036 00054 (main.go:3)        PCDATA  $0, $-1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0036 00054 (main.go:3)        JMP     0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">main.main.func1 STEXT nosplit size=61 args=0x8 locals=0x10 funcid=0x0 align=0x0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:5)        TEXT    main.main.func1(SB), NOSPLIT|ABIInternal, $16-8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 栈内存分配、保存旧栈的基地址和建立新栈帧\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:5)        SUBQ    $16, SP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0004 00004 (main.go:5)        MOVQ    BP, 8(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0009 00009 (main.go:5)        LEAQ    8(SP), BP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F gc垃圾处理\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000e 00014 (main.go:5)        FUNCDATA        $0, gclocals·wgcWObbY2HYnK2SU\u002FU22lA==(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000e 00014 (main.go:5)        FUNCDATA        $1, gclocals·J5F+7Qw7O7ve2QcWC7DpeQ==(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000e 00014 (main.go:5)        FUNCDATA        $5, main.main.func1.arginfo1(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把AX寄存器的值(main函数a变量的地址)存储到栈上的某个位置---24(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000e 00014 (main.go:5)        MOVQ    AX, main.&amp;a+24(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 初始化匿名函数的返回值\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0013 00019 (main.go:5)        MOVQ    $0, main.~r0(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把a变量的地址存储到CX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x001b 00027 (main.go:6)        MOVQ    main.&amp;a+24(SP), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将立即数3拷贝到CX寄存器指向的内存地址(a变量的内存地址)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0020 00032 (main.go:6)        MOVQ    $3, (CX)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把a变量的地址存储到CX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0027 00039 (main.go:7)        MOVQ    main.&amp;a+24(SP), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把CX寄存器指向的内存地址中存储的值(变量a的内存地址)拷贝到AX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x002c 00044 (main.go:7)        MOVQ    (CX), AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将AX寄存器中的值存储到函数返回值的位置\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x002f 00047 (main.go:7)        MOVQ    AX, main.~r0(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F BP地址恢复和栈空间回收\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0033 00051 (main.go:7)        MOVQ    8(SP), BP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0038 00056 (main.go:7)        ADDQ    $16, SP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 函数返回\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x003c 00060 (main.go:7)        RET\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-mask\" aria-hidden=\"true\">\u003C\u002Fdiv>\u003Cbutton class=\"ssr-code-toggle ssr-code-toggle--floating\" type=\"button\" aria-expanded=\"false\">展开全部 (62 行)\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>从汇编中可以看出，匿名函数可以实现对变量 a 的获取和修改是因为在调用匿名函数之前，main 函数将变量 a 的地址保存到了 AX 寄存器中。也就是说，现在 main 函数的栈中除了保存了变量 a 的值，还有对于寄存器 AX 的引用。那么对于匿名函数，只需要获取寄存器 AX 的值就能知道变量 a 的地址，进而可以对变量 a 进行修改。\u003C\u002Fp>\n\u003Cp>所以，匿名函数本质上是通过寄存器 AX 来捕捉到 main 函数栈中的变量 a，那么这种引用（通过 AX 寄存器来获得变量 a）和匿名函数的堆栈内存空间就构成了一个闭包。\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>在这个例子 1 之前，我尝试过在匿名函数内部只是获取变量 a，但不修改变量 a，结果就是 AX 寄存器会直接存储变量 a 的值，而不是地址。\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Ch3 id=\"h3-3--2\">例子 2\u003C\u002Fh3>\n\u003Cp>测试代码如下：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"go\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">go\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-go\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#FFAB70\">x\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">int\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">int\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">int\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        x \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> x\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    f \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">1\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">f\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>使用\u003Ccode>go tool compile -S -N -l main.go\u003C\u002Fcode>命令生成的核心汇编代码如下（由于篇幅限制，在此省略掉部分汇编代码，比如栈空间操作、gc 垃圾处理和函数返回）：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"text\" data-collapsible=\"true\" data-collapsed=\"true\" data-line-count=\"101\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">text\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-toggle ssr-code-toggle--head ssr-code-iconbtn\" type=\"button\" aria-expanded=\"true\" aria-label=\"收起代码\" title=\"收起\">\u003Csvg viewBox=\"0 0 24 24\" width=\"19\" height=\"19\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M12 8.59l-6.3 6.3 1.4 1.42L12 11.4l4.9 4.9 1.4-1.4z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-toggle ssr-code-toggle--head-expand ssr-code-iconbtn\" type=\"button\" aria-expanded=\"false\" aria-label=\"展开代码\" title=\"展开\">\u003Csvg viewBox=\"0 0 24 24\" width=\"19\" height=\"19\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M12 15.41l6.3-6.3-1.4-1.42L12 12.59 7.1 7.7l-1.4 1.4z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">16\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">17\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">18\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">19\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">20\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">21\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">22\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">23\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">24\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">25\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">26\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">27\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">28\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">29\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">30\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">31\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">32\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">33\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">34\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">35\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">36\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">37\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">38\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">39\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">40\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">41\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">42\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">43\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">44\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">45\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">46\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">47\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">48\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">49\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">50\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">51\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">52\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">53\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">54\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">55\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">56\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">57\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">58\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">59\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">60\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">61\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">62\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">63\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">64\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">65\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">66\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">67\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">68\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">69\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">70\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">71\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">72\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">73\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">74\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">75\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">76\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">77\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">78\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">79\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">80\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">81\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">82\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">83\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">84\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">85\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">86\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">87\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">88\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">89\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">90\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">91\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">92\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">93\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">94\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">95\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">96\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">97\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">98\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">99\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">100\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">101\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-text\">\u003Cspan class=\"ssr-code-line\">main.main STEXT size=60 args=0x0 locals=0x18 funcid=0x0 align=0x0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:10)       TEXT    main.main(SB), ABIInternal, $24-0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        ······\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 传入参数1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0014 00020 (main.go:11)       MOVL    $1, AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0019 00025 (main.go:11)       PCDATA  $1, $0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 调用test()函数,该函数返回的是闭包对象的地址并保存到AX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0019 00025 (main.go:11)       CALL    main.test(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将闭包对象的地址保存到栈上\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x001e 00030 (main.go:11)       MOVQ    AX, main.f+8(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将闭包对象的地址中里面的数据加载到CX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 这个数据是一个函数指针,该指针指向与闭包关联的函数\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0023 00035 (main.go:12)       MOVQ    (AX), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将闭包对象的地址保存到DX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0026 00038 (main.go:12)       MOVQ    AX, DX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 调用与闭包关联的函数\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0029 00041 (main.go:12)       CALL    CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        ······\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">main.test STEXT size=175 args=0x8 locals=0x30 funcid=0x0 align=0x0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:3)        TEXT    main.test(SB), ABIInternal, $48-8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        ······\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 参数传递,得到x为1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0018 00024 (main.go:3)        MOVQ    AX, main.x+56(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 返回值初始化\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x001d 00029 (main.go:3)        MOVQ    $0, main.~r0+16(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 获取type.int的地址,作为runtime.newobject()的参数\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0026 00038 (main.go:3)        LEAQ    type.int(SB), AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x002d 00045 (main.go:3)        PCDATA  $1, $0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 调用runtime.newobject()表示要在堆上分配内存,分配一个int类型的对象\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 调用完成后返回这块内存的地址保存在AX寄存器中\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x002d 00045 (main.go:3)        CALL    runtime.newobject(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将AX寄存器中的值复制到栈指针SP加32字节的位置\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 前面的main.&amp;x表示这个内存位置的值(AX寄存器中的值)将作为变量x的地址\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0032 00050 (main.go:3)        MOVQ    AX, main.&amp;x+32(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把变量x的值(相对于栈指针SP加56字节的位置)加载到寄存器CX中\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0037 00055 (main.go:3)        MOVQ    main.x+56(SP), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把CX寄存器中的值(变量x的值)复制到AX寄存器指向的内存地址\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 通过上面的CALL指令和这三条MOVQ指令实现了:将x变量从栈区拷贝到了堆区(内存逃逸)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x003c 00060 (main.go:3)        MOVQ    CX, (AX)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 获取闭包结构体的地址\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x003f 00063 (main.go:4)        LEAQ    type.noalg.struct { F uintptr; main.x *int }(SB), AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0046 00070 (main.go:4)        PCDATA  $1, $1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 调用runtime.newobject为闭包本身分配内存,分配的内存地址保存到AX寄存器中\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0046 00070 (main.go:4)        CALL    runtime.newobject(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将AX寄存器中闭包对象的地址复制到栈上SP+24字节的内存位置\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x004b 00075 (main.go:4)        MOVQ    AX, main..autotmp_2+24(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将匿名函数的地址复制到CX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0050 00080 (main.go:4)        LEAQ    main.test.func1(SB), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将匿名函数地址存入AX寄存器指向的堆地址(设置了闭包中的函数指针)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0057 00087 (main.go:4)        MOVQ    CX, (AX)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F .autotmp_2通常表示一个自动分配的临时变量,这个变量其实是用来存储闭包对象的地址\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将这个变量的值(在SP栈指针向上偏移24字节的位置)复制到DI寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x005a 00090 (main.go:4)        MOVQ    main..autotmp_2+24(SP), DI\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 应该是设置某个条件码寄存器的标志位(暂时不用管)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x005f 00095 (main.go:4)        TESTB   AL, (DI)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将变量x的地址(在SP栈指针向上偏移32字节的位置)复制给CX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0061 00097 (main.go:4)        MOVQ    main.&amp;x+32(SP), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F DX寄存器用来存储闭包的环境指针\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0066 00102 (main.go:4)        LEAQ    8(DI), DX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x006a 00106 (main.go:4)        PCDATA  $0, $-2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 这段是内存写屏障相关的汇编,有点看不懂\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x006a 00106 (main.go:4)        CMPL    runtime.writeBarrier(SB), $0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0071 00113 (main.go:4)        JEQ     117\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0073 00115 (main.go:4)        JMP     123\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 设置闭包的环境指针(CX寄存器存储的是x的地址)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0075 00117 (main.go:4)        MOVQ    CX, 8(DI)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0079 00121 (main.go:4)        JMP     135\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x007b 00123 (main.go:4)        MOVQ    DX, DI\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x007e 00126 (main.go:4)        NOP\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0080 00128 (main.go:4)        CALL    runtime.gcWriteBarrierCX(SB)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0085 00133 (main.go:4)        JMP     135\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0087 00135 (main.go:4)        PCDATA  $0, $-1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F test()最终返回的是闭包对象的地址\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0087 00135 (main.go:4)        MOVQ    main..autotmp_2+24(SP), AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x008c 00140 (main.go:4)        MOVQ    AX, main.~r0+16(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        ······\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">main.test.func1 STEXT size=214 args=0x0 locals=0x68 funcid=0x0 align=0x0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0000 00000 (main.go:6)        TEXT    main.test.func1(SB), NEEDCTXT|ABIInternal, $104-0\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        ······\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F DX寄存器存储的是闭包对象的起始地址\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 从闭包内存空间的第8个字节的位置读取变量x的地址到CX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x000e 00014 (main.go:4)        MOVQ    8(DX), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将变量x的地址拷贝到栈内存中(SP指针向上偏移8字节的位置)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0012 00018 (main.go:4)        MOVQ    CX, main.&amp;x+8(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 返回值初始化\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0017 00023 (main.go:4)        MOVQ    $0, main.~r0(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把变量x的地址放到CX寄存器中(获取变量x的地址,为写入x做准备)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x001f 00031 (main.go:5)        MOVQ    main.&amp;x+8(SP), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 将立即数2写入到变量x所在的内存地址(该位置在堆内存中)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0024 00036 (main.go:5)        MOVQ    $2, (CX)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 再次获取变量x的地址,准备读取x的值\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x002b 00043 (main.go:6)        MOVQ    main.&amp;x+8(SP), CX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F CX寄存器指向的内存地址(变量x的地址)中的值(立即数2)复制给AX寄存器\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0030 00048 (main.go:6)        MOVQ    (CX), AX\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        \u002F\u002F 把AX寄存器的值(变量x)复制到函数返回寄存器(r0)中\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        0x0033 00051 (main.go:6)        MOVQ    AX, main.~r0(SP)\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">        ······\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-mask\" aria-hidden=\"true\">\u003C\u002Fdiv>\u003Cbutton class=\"ssr-code-toggle ssr-code-toggle--floating\" type=\"button\" aria-expanded=\"false\">展开全部 (101 行)\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>上面分析完了大部分的汇编代码。汇编代码晦涩难懂，既要懂得相关语法，又要把握好程序执行基本脉络。\u003C\u002Fp>\n\u003Cp>从汇编中可以看出，闭包其实就是一个函数指针和一个环境指针。环境指针指向变量 x 的地址，由于变量 x 最初分配在栈上，当 test()调用完成后变量 x 就会被销毁。于是编译器为了能让环境指针一直指向变量 x，就将变量 x 从栈内存拷贝到了堆内存，以此来延长变量 x 的生命周期。除此之外，一个指向匿名函数的指针也被赋值给了闭包的函数指针，这样只要调用闭包，相对应的函数就能执行。\u003C\u002Fp>\n\u003Cp>整体逻辑虽然并不算复杂，但是其中的细节确实非常多，想要完全弄明白也不容易（堆栈内存分配和写屏障问题）。\u003C\u002Fp>\n\u003Ch2 id=\"h2-4-\">闭包中的“延迟求值”特性\u003C\u002Fh2>\n\u003Cp>只要从汇编角度理解了闭包，其实闭包的“延迟求值”特性也不难理解。主要是以前我不太理解这个延迟求值的本质是什么。下面看测试代码：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"go\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">go\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-go\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() []\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">var\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> s []\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F定义一个切片s,s的类型为func()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> i \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">0\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">; i \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">&lt;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">; i\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">++\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        s \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">append\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(s, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">            fmt.\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">Println\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(i)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        })\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> s\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> _, value \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">range\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F遍历test()的返回值\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">value\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>这段代码的执行结果我最初以为是 0 和 1，但是实际的执行结果是输出了两个 2。\u003C\u002Fp>\n\u003Cp>现在结合闭包的底层原理很快就能知道为什么是两个 2。切片 s 为 func()类型的切片，使用 append 将匿名函数放在切片 s 中。由于匿名函数引用了外部变量 i，因此这个匿名函数和变量 i 构成了一个闭包。所以这个匿名函数并不会立即执行，只有在调用闭包的时候，匿名函数才会执行。\u003C\u002Fp>\n\u003Cp>现在看 main 函数中的执行逻辑：首先执行 test()函数，得到一个 func()类型的切片，该切片中包含两个匿名函数，接下来就是遍历切片。在第一次迭代中执行闭包的时候，需要打印变量 i 的值，尽管 test()函数已经执行完毕（test 函数的栈帧已经被销毁），但是由于变量 i 和匿名函数构成了闭包，所以编译器将变量 i 从栈内存拷贝到了堆内存，那现在 i 的值是多少呢？就是 test 函数栈在销毁前最终的 i 值，也就是 2。因此两个匿名函数都使用了堆内存中的同一个 i，并将其打印出来。\u003C\u002Fp>\n\u003Cp>那么如果我想让执行结果为 0 和 1，该如何修改代码呢？其实也很简单，问题的根源在于 test()函数执行完成后变量 i 从栈内存拷贝到了堆内存，所以堆中只是记录了 i 的最终状态，那么如果我们能够把 test()函数中 for 循环中的每个变量 i 都记录下来，那么问题也就解决了。所以解决办法是在匿名函数外部，for 循环内部定义一个变量，将 i 值记录到这个变量中。这样每次 for 循环都会创建一个新的变量，每个变量记录当前的 i 值，最终这些变量都会逃逸到堆区，最后被匿名函数引用。代码如下：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"go\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">go\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">16\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">17\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">18\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-go\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() []\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">var\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> s []\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> i \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">0\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">; i \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">&lt;\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">2\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">; i\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">++\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        \u003C\u002Fspan>\u003Cspan style=\"color:#6A737D\">\u002F\u002F虽然都是x,但是每个x的地址都不同,最后所有的x都会逃逸到堆区\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        x \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> i\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        s \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">append\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(s, \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">            \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">println\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(x)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">        })\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> s\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">​\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#F97583\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    result \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> _, value \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">:=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">range\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> result {\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">      \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">value\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">()\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>下面是使用命令\u003Ccode>go tool compile -N -l -m=2 main.go\u003C\u002Fcode>进行逃逸分析：\u003C\u002Fp>\n\u003Cdiv class=\"ssr-code-block\" data-lang=\"bash\">\u003Cdiv class=\"ssr-code-head\">\u003Cspan class=\"ssr-code-lang\">bash\u003C\u002Fspan>\u003Cdiv class=\"ssr-code-actions\">\u003Cbutton class=\"ssr-code-fullscreen ssr-code-iconbtn\" type=\"button\" aria-label=\"全屏查看代码\" title=\"全屏\">\u003Csvg viewBox=\"0 0 24 24\" width=\"17\" height=\"17\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M5 5h6v2H7v4H5V5zm14 0v6h-2V7h-4V5h6zM5 19v-6h2v4h4v2H5zm14 0h-6v-2h4v-4h2v6z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003Cbutton class=\"ssr-code-copy ssr-code-iconbtn\" type=\"button\" aria-label=\"复制代码\" title=\"复制\">\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--default\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--success\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"\u002F>\u003C\u002Fsvg>\u003Csvg class=\"ssr-code-copy-icon ssr-code-copy-icon--error\" viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" aria-hidden=\"true\">\u003Cpath fill=\"currentColor\" d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"\u002F>\u003C\u002Fsvg>\u003C\u002Fbutton>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"ssr-code-body\">\u003Cdiv class=\"ssr-code-pane\">\u003Cdiv class=\"ssr-code-gutter\" aria-hidden=\"true\">\u003Cspan class=\"ssr-code-num\">1\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">2\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">3\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">4\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">5\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">6\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">7\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">8\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">9\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">10\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">11\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">12\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">13\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">14\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">15\u003C\u002Fspan>\u003Cspan class=\"ssr-code-num\">16\u003C\u002Fspan>\u003C\u002Fdiv>\u003Cpre class=\"ssr-code-pre\">\u003Ccode class=\"hljs language-bash\">\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#E1E4E8\">[deep@binary test]$ go tool compile -N -l -m\u003C\u002Fspan>\u003Cspan style=\"color:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">2\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">main.go\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:9:17:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">literal\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">escapes\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">to\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">heap:\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:9:17:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">   \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">flow:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">{heap}\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> &amp;{storage for func literal}:\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:9:17:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">     \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">literal\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> (spill) at main.go:9:17\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:9:17:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">     \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">append\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#B392F0\">s,\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">literal\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) (call \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">parameter\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) at main.go:9:13\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:8:3:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">test\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">capturing\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">by\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">value:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">x\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> (addr=false \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">assign=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">false\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">width=\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">8\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">x\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">escapes\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">to\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">heap:\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">   \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">flow:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">{storage\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">argument}\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> &amp;{storage for x}:\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">     \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">x\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> (spill) at main.go:10:15\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">     \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">argument\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> (slice-literal-element) at main.go:10:15\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">   \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">flow:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">{heap}\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">{storage\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">argument}:\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">     \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">argument\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> (spill) at main.go:10:15\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">     \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">fmt.Println\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"color:#79B8FF\">...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">argument...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) (call \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">parameter\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\">) at main.go:10:15\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:9:17:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">func\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">literal\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">escapes\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">to\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">heap\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">...\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">argument\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">does\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">not\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">escape\u003C\u002Fspan>\u003C\u002Fspan>\u003Cspan class=\"ssr-code-line\">\u003Cspan style=\"color:#B392F0\">main.go:10:15:\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">x\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">escapes\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">to\u003C\u002Fspan>\u003Cspan style=\"color:#E1E4E8\"> \u003C\u002Fspan>\u003Cspan style=\"color:#9ECBFF\">heap\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>\n\u003Cp>可以看到变量 x 和闭包函数（func literal）逃逸到了堆上（\u003Ccode>x escapes to heap\u003C\u002Fcode>和\u003Ccode>func literal escapes to heap\u003C\u002Fcode>），gc 会负责管理这些在堆上分配的内存。\u003C\u002Fp>\n","基本概念 Go 语言中闭包是引用了自由变量的函数，被引用的自由变量和函数一同存在，即使已经离开了自由变量的环境也不会被释放或者删除，在闭包中可以继续使用这个自由变量。闭包也可以说是一个函数和与其相关的引用环境组合而成的实体。简单来说， 。如下所示就是闭包的示意图： 前面的概念可能还是不太好理解，下面是关于闭包的汇编分析","https:\u002F\u002Fliubing-1314895948.cos.ap-chengdu.myqcloud.com\u002Fimg\u002F202401272021155.png"]