From 548bfb032cd9e628cde0356518ad3d163ca3b738 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 12:35:09 +0000 Subject: [PATCH] Deploy to GitHub pages --- 404.html | 20 + CHANGELOG.html | 50 + assets/css/0.styles.93ee3edc.css | 1 + assets/img/a.732405d8.png | Bin 0 -> 66181 bytes assets/img/gofunc.32e2f0aa.svg | 4 + assets/img/hash.b54950a0.svg | 149 +++ assets/img/ringwaiter.c4e44723.png | Bin 0 -> 38556 bytes assets/img/search.83621669.svg | 1 + assets/img/wechat.4a3030a4.png | Bin 0 -> 41224 bytes assets/js/10.993cf521.js | 1 + assets/js/100.049dca94.js | 1 + assets/js/101.9e4a3cce.js | 1 + assets/js/102.60455322.js | 1 + assets/js/103.4ebce8b3.js | 1 + assets/js/104.dcbef6d1.js | 1 + assets/js/105.76803baf.js | 1 + assets/js/106.26567b10.js | 1 + assets/js/107.c757198e.js | 1 + assets/js/108.90ae536a.js | 1 + assets/js/109.55b5f850.js | 1 + assets/js/11.25dd6abf.js | 1 + assets/js/110.9afae874.js | 1 + assets/js/111.fcb96ca2.js | 1 + assets/js/112.9e9125b6.js | 1 + assets/js/12.521ef871.js | 1 + assets/js/13.6a579e8b.js | 1 + assets/js/14.fa863532.js | 1 + assets/js/15.ccbbdb7a.js | 1 + assets/js/16.d5f6c328.js | 1 + assets/js/17.1312d121.js | 1 + assets/js/18.4b8a1599.js | 1 + assets/js/19.5ed73af4.js | 1 + assets/js/2.5c331e53.js | 1 + assets/js/20.fea9a837.js | 1 + assets/js/21.321b1448.js | 1 + assets/js/22.e3bbafa7.js | 1 + assets/js/23.6633ca8a.js | 1 + assets/js/24.edf743ad.js | 1 + assets/js/25.831fd7ee.js | 1 + assets/js/26.83ccb127.js | 1 + assets/js/27.d1524f5d.js | 1 + assets/js/28.69e5608b.js | 1 + assets/js/29.742dd6e8.js | 1 + assets/js/3.a22689ce.js | 1 + assets/js/30.4aafb94a.js | 1 + assets/js/31.87baab0b.js | 1 + assets/js/32.1ea926c5.js | 1 + assets/js/33.4d31d0db.js | 1 + assets/js/34.7610889f.js | 1 + assets/js/35.32a9ec30.js | 1 + assets/js/36.8d562ec5.js | 1 + assets/js/37.18cb13d8.js | 1 + assets/js/38.53670642.js | 1 + assets/js/39.9c8315fb.js | 1 + assets/js/4.a73c4d70.js | 1 + assets/js/40.3bf1fd84.js | 1 + assets/js/41.73deb46e.js | 1 + assets/js/42.85cfacd9.js | 1 + assets/js/43.1b441a63.js | 1 + assets/js/44.5dc33e34.js | 1 + assets/js/45.b2f02d30.js | 1 + assets/js/46.7fef4e9d.js | 1 + assets/js/47.6dd9b6a9.js | 1 + assets/js/48.e525f69a.js | 1 + assets/js/49.565c30a8.js | 1 + assets/js/5.864fc44c.js | 1 + assets/js/50.249734db.js | 1 + assets/js/51.9dd5ff4a.js | 1 + assets/js/52.9dfffd13.js | 1 + assets/js/53.c98436b4.js | 1 + assets/js/54.ee26f0f5.js | 1 + assets/js/55.7b5dc58d.js | 1 + assets/js/56.e3024720.js | 1 + assets/js/57.ba1b4c58.js | 1 + assets/js/58.d6c32d73.js | 1 + assets/js/59.a733d97b.js | 1 + assets/js/6.5f593451.js | 1 + assets/js/60.f162e276.js | 1 + assets/js/61.155a3987.js | 1 + assets/js/62.ad6d715b.js | 1 + assets/js/63.088bb315.js | 1 + assets/js/64.58e4a79c.js | 1 + assets/js/65.9e82002d.js | 1 + assets/js/66.949483d3.js | 1 + assets/js/67.613f77e3.js | 1 + assets/js/68.f73d44cf.js | 1 + assets/js/69.a717baf8.js | 1 + assets/js/7.5280db48.js | 1 + assets/js/70.b3476fa3.js | 1 + assets/js/71.57746954.js | 1 + assets/js/72.4cc3186e.js | 1 + assets/js/73.03d8974c.js | 1 + assets/js/74.4f1eeb3c.js | 1 + assets/js/75.d44fc2e7.js | 1 + assets/js/76.f53bf284.js | 1 + assets/js/77.bad2588a.js | 1 + assets/js/78.2ee31447.js | 1 + assets/js/79.f5c3f20d.js | 1 + assets/js/8.ff976029.js | 1 + assets/js/80.5aa44af4.js | 1 + assets/js/81.33455a03.js | 1 + assets/js/82.9f2284bd.js | 1 + assets/js/83.5e222179.js | 1 + assets/js/84.b93653e7.js | 1 + assets/js/85.aff346f9.js | 1 + assets/js/86.ca707802.js | 1 + assets/js/87.d9bc2332.js | 1 + assets/js/88.87973a44.js | 1 + assets/js/89.37b7fea9.js | 1 + assets/js/9.e2b0263e.js | 1 + assets/js/90.dedfc540.js | 1 + assets/js/91.dbd4ca9b.js | 1 + assets/js/92.61c0947f.js | 1 + assets/js/93.eaa3fe92.js | 1 + assets/js/94.c3c51d69.js | 1 + assets/js/95.d1eac759.js | 1 + assets/js/96.add14987.js | 1 + assets/js/97.357d16bb.js | 1 + assets/js/98.fe5446fa.js | 1 + assets/js/99.c9fd11f7.js | 1 + assets/js/app.dbd5dba2.js | 17 + css/index.css | 3 + favicon.ico | Bin 0 -> 277379 bytes index.html | 52 + runtime/gmp/index.html | 50 + runtime/index.html | 50 + runtime/netpool/index.html | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../helloWorld/index.html" | 64 + "\345\237\272\347\241\200/index.html" | 50 + .../interface/index.html" | 714 +++++++++++ "\345\237\272\347\241\200/map/index.html" | 149 +++ "\345\237\272\347\241\200/slice/index.html" | 298 +++++ "\345\237\272\347\241\200/string/index.html" | 256 ++++ .../index.html" | 145 +++ .../index.html" | 155 +++ .../0.html" | 112 ++ .../1.html" | 92 ++ .../2.html" | 50 + .../3.html" | 98 ++ .../4.html" | 120 ++ .../5.html" | 84 ++ .../6.html" | 50 + .../7.html" | 176 +++ .../index.html" | 1050 +++++++++++++++++ .../index.html" | 145 +++ .../index.html" | 94 ++ .../index.html" | 146 +++ .../index.html" | 119 ++ .../index.html" | 74 ++ .../\346\263\233\345\236\213/index.html" | 453 +++++++ .../index.html" | 319 +++++ .../index.html" | 199 ++++ .../index.html" | 562 +++++++++ .../\351\233\266\345\200\274/index.html" | 117 ++ "\345\267\245\347\250\213/cgo/index.html" | 50 + "\345\267\245\347\250\213/copilot/index.html" | 50 + .../goweb\347\274\226\347\250\213/index.html" | 50 + .../index.html" | 121 ++ .../encoding-hex.html" | 50 + .../fmt.html" | 50 + .../index.html" | 158 +++ .../sync.html" | 64 + .../index.html" | 50 + .../k8s_visitor/index.html" | 50 + .../pipeline/index.html" | 50 + .../\344\273\243\347\220\206/index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../\345\215\225\344\276\213/index.html" | 50 + .../\345\216\237\345\236\213/index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../\345\271\266\350\241\214/index.html" | 50 + .../\346\211\207\345\205\245/index.html" | 50 + .../\346\211\207\345\207\272/index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../\347\255\226\347\225\245/index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../architect.html" | 50 + .../index.html" | 50 + .../intermediate.html" | 50 + .../primary.html" | 50 + .../senior.html" | 50 + ...\350\257\225\351\242\230\344\270\200.html" | 50 + "\345\267\245\347\250\213/index.html" | 50 + "\345\267\245\347\250\213/ioc/index.html" | 50 + "\345\267\245\347\250\213/log/index.html" | 50 + "\345\267\245\347\250\213/wasm/index.html" | 50 + .../index.html" | 133 +++ .../gin/index.html" | 50 + .../index.html" | 50 + .../sonic/index.html" | 50 + .../index.html" | 50 + .../index.html" | 275 +++++ .../\345\217\215\345\260\204/index.html" | 50 + .../\345\221\275\344\273\244/index.html" | 61 + .../\345\235\221/index.html" | 50 + .../index.html" | 50 + .../\346\265\213\350\257\225/index.html" | 50 + ...\345\207\206\346\265\213\350\257\225.html" | 50 + ...\347\241\200\346\265\213\350\257\225.html" | 50 + ...\347\263\212\346\265\213\350\257\225.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + .../index.html" | 50 + "\345\271\266\345\217\221/atomic/index.html" | 61 + "\345\271\266\345\217\221/channel/index.html" | 922 +++++++++++++++ "\345\271\266\345\217\221/context/index.html" | 208 ++++ "\345\271\266\345\217\221/index.html" | 50 + .../index.html" | 201 ++++ .../index.html" | 791 +++++++++++++ .../index.html" | 95 ++ .../gc/index.html" | 50 + .../gccgo/index.html" | 53 + .../index.html" | 65 + .../llvm/index.html" | 54 + 228 files changed, 12661 insertions(+) create mode 100644 404.html create mode 100644 CHANGELOG.html create mode 100644 assets/css/0.styles.93ee3edc.css create mode 100644 assets/img/a.732405d8.png create mode 100644 assets/img/gofunc.32e2f0aa.svg create mode 100644 assets/img/hash.b54950a0.svg create mode 100644 assets/img/ringwaiter.c4e44723.png create mode 100644 assets/img/search.83621669.svg create mode 100644 assets/img/wechat.4a3030a4.png create mode 100644 assets/js/10.993cf521.js create mode 100644 assets/js/100.049dca94.js create mode 100644 assets/js/101.9e4a3cce.js create mode 100644 assets/js/102.60455322.js create mode 100644 assets/js/103.4ebce8b3.js create mode 100644 assets/js/104.dcbef6d1.js create mode 100644 assets/js/105.76803baf.js create mode 100644 assets/js/106.26567b10.js create mode 100644 assets/js/107.c757198e.js create mode 100644 assets/js/108.90ae536a.js create mode 100644 assets/js/109.55b5f850.js create mode 100644 assets/js/11.25dd6abf.js create mode 100644 assets/js/110.9afae874.js create mode 100644 assets/js/111.fcb96ca2.js create mode 100644 assets/js/112.9e9125b6.js create mode 100644 assets/js/12.521ef871.js create mode 100644 assets/js/13.6a579e8b.js create mode 100644 assets/js/14.fa863532.js create mode 100644 assets/js/15.ccbbdb7a.js create mode 100644 assets/js/16.d5f6c328.js create mode 100644 assets/js/17.1312d121.js create mode 100644 assets/js/18.4b8a1599.js create mode 100644 assets/js/19.5ed73af4.js create mode 100644 assets/js/2.5c331e53.js create mode 100644 assets/js/20.fea9a837.js create mode 100644 assets/js/21.321b1448.js create mode 100644 assets/js/22.e3bbafa7.js create mode 100644 assets/js/23.6633ca8a.js create mode 100644 assets/js/24.edf743ad.js create mode 100644 assets/js/25.831fd7ee.js create mode 100644 assets/js/26.83ccb127.js create mode 100644 assets/js/27.d1524f5d.js create mode 100644 assets/js/28.69e5608b.js create mode 100644 assets/js/29.742dd6e8.js create mode 100644 assets/js/3.a22689ce.js create mode 100644 assets/js/30.4aafb94a.js create mode 100644 assets/js/31.87baab0b.js create mode 100644 assets/js/32.1ea926c5.js create mode 100644 assets/js/33.4d31d0db.js create mode 100644 assets/js/34.7610889f.js create mode 100644 assets/js/35.32a9ec30.js create mode 100644 assets/js/36.8d562ec5.js create mode 100644 assets/js/37.18cb13d8.js create mode 100644 assets/js/38.53670642.js create mode 100644 assets/js/39.9c8315fb.js create mode 100644 assets/js/4.a73c4d70.js create mode 100644 assets/js/40.3bf1fd84.js create mode 100644 assets/js/41.73deb46e.js create mode 100644 assets/js/42.85cfacd9.js create mode 100644 assets/js/43.1b441a63.js create mode 100644 assets/js/44.5dc33e34.js create mode 100644 assets/js/45.b2f02d30.js create mode 100644 assets/js/46.7fef4e9d.js create mode 100644 assets/js/47.6dd9b6a9.js create mode 100644 assets/js/48.e525f69a.js create mode 100644 assets/js/49.565c30a8.js create mode 100644 assets/js/5.864fc44c.js create mode 100644 assets/js/50.249734db.js create mode 100644 assets/js/51.9dd5ff4a.js create mode 100644 assets/js/52.9dfffd13.js create mode 100644 assets/js/53.c98436b4.js create mode 100644 assets/js/54.ee26f0f5.js create mode 100644 assets/js/55.7b5dc58d.js create mode 100644 assets/js/56.e3024720.js create mode 100644 assets/js/57.ba1b4c58.js create mode 100644 assets/js/58.d6c32d73.js create mode 100644 assets/js/59.a733d97b.js create mode 100644 assets/js/6.5f593451.js create mode 100644 assets/js/60.f162e276.js create mode 100644 assets/js/61.155a3987.js create mode 100644 assets/js/62.ad6d715b.js create mode 100644 assets/js/63.088bb315.js create mode 100644 assets/js/64.58e4a79c.js create mode 100644 assets/js/65.9e82002d.js create mode 100644 assets/js/66.949483d3.js create mode 100644 assets/js/67.613f77e3.js create mode 100644 assets/js/68.f73d44cf.js create mode 100644 assets/js/69.a717baf8.js create mode 100644 assets/js/7.5280db48.js create mode 100644 assets/js/70.b3476fa3.js create mode 100644 assets/js/71.57746954.js create mode 100644 assets/js/72.4cc3186e.js create mode 100644 assets/js/73.03d8974c.js create mode 100644 assets/js/74.4f1eeb3c.js create mode 100644 assets/js/75.d44fc2e7.js create mode 100644 assets/js/76.f53bf284.js create mode 100644 assets/js/77.bad2588a.js create mode 100644 assets/js/78.2ee31447.js create mode 100644 assets/js/79.f5c3f20d.js create mode 100644 assets/js/8.ff976029.js create mode 100644 assets/js/80.5aa44af4.js create mode 100644 assets/js/81.33455a03.js create mode 100644 assets/js/82.9f2284bd.js create mode 100644 assets/js/83.5e222179.js create mode 100644 assets/js/84.b93653e7.js create mode 100644 assets/js/85.aff346f9.js create mode 100644 assets/js/86.ca707802.js create mode 100644 assets/js/87.d9bc2332.js create mode 100644 assets/js/88.87973a44.js create mode 100644 assets/js/89.37b7fea9.js create mode 100644 assets/js/9.e2b0263e.js create mode 100644 assets/js/90.dedfc540.js create mode 100644 assets/js/91.dbd4ca9b.js create mode 100644 assets/js/92.61c0947f.js create mode 100644 assets/js/93.eaa3fe92.js create mode 100644 assets/js/94.c3c51d69.js create mode 100644 assets/js/95.d1eac759.js create mode 100644 assets/js/96.add14987.js create mode 100644 assets/js/97.357d16bb.js create mode 100644 assets/js/98.fe5446fa.js create mode 100644 assets/js/99.c9fd11f7.js create mode 100644 assets/js/app.dbd5dba2.js create mode 100644 css/index.css create mode 100644 favicon.ico create mode 100644 index.html create mode 100644 runtime/gmp/index.html create mode 100644 runtime/index.html create mode 100644 runtime/netpool/index.html create mode 100644 "runtime/\344\270\211\350\211\262gc\347\256\227\346\263\225/index.html" create mode 100644 "runtime/\345\240\206\345\206\205\345\255\230\345\210\206\351\205\215/index.html" create mode 100644 "runtime/\345\256\232\346\227\266\345\231\250/index.html" create mode 100644 "runtime/\346\240\210\345\206\205\345\255\230\347\256\241\347\220\206/index.html" create mode 100644 "runtime/\347\263\273\347\273\237\347\233\221\346\216\247/index.html" create mode 100644 "\345\237\272\347\241\200/helloWorld/index.html" create mode 100644 "\345\237\272\347\241\200/index.html" create mode 100644 "\345\237\272\347\241\200/interface/index.html" create mode 100644 "\345\237\272\347\241\200/map/index.html" create mode 100644 "\345\237\272\347\241\200/slice/index.html" create mode 100644 "\345\237\272\347\241\200/string/index.html" create mode 100644 "\345\237\272\347\241\200/\344\275\234\347\224\250\345\237\237/index.html" create mode 100644 "\345\237\272\347\241\200/\345\205\266\344\273\226\345\206\205\345\256\271/index.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/0.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/1.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/2.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/3.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/4.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/5.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/6.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/7.html" create mode 100644 "\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/index.html" create mode 100644 "\345\237\272\347\241\200/\345\217\230\351\207\217\345\243\260\346\230\216/index.html" create mode 100644 "\345\237\272\347\241\200/\345\244\215\345\220\210\345\255\227\351\235\242\351\207\217/index.html" create mode 100644 "\345\237\272\347\241\200/\345\270\270\351\207\217\345\243\260\346\230\216/index.html" create mode 100644 "\345\237\272\347\241\200/\346\225\260\345\255\227\347\261\273\345\236\213/index.html" create mode 100644 "\345\237\272\347\241\200/\346\261\202\345\200\274\351\241\272\345\272\217/index.html" create mode 100644 "\345\237\272\347\241\200/\346\263\233\345\236\213/index.html" create mode 100644 "\345\237\272\347\241\200/\347\273\223\346\236\204\344\275\223/index.html" create mode 100644 "\345\237\272\347\241\200/\351\200\273\350\276\221\345\222\214\345\210\244\346\226\255\350\257\255\345\217\245/index.html" create mode 100644 "\345\237\272\347\241\200/\351\224\231\350\257\257\345\244\204\347\220\206/index.html" create mode 100644 "\345\237\272\347\241\200/\351\233\266\345\200\274/index.html" create mode 100644 "\345\267\245\347\250\213/cgo/index.html" create mode 100644 "\345\267\245\347\250\213/copilot/index.html" create mode 100644 "\345\267\245\347\250\213/goweb\347\274\226\347\250\213/index.html" create mode 100644 "\345\267\245\347\250\213/go\345\221\275\345\220\215\346\203\257\344\276\213/index.html" create mode 100644 "\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/encoding-hex.html" create mode 100644 "\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/fmt.html" create mode 100644 "\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/index.html" create mode 100644 "\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/sync.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/k8s_visitor/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/pipeline/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\273\243\347\220\206/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\277\241\345\217\267\351\207\217/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\210\233\345\273\272\350\200\205/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\212\237\350\203\275\351\200\211\351\241\271/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\215\225\344\276\213/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\216\237\345\236\213/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\217\221\345\270\203\350\200\205\350\256\242\351\230\205\350\200\205/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\256\232\346\227\266\345\207\275\346\225\260/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\257\271\350\261\241\346\261\240/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\267\245\345\216\202\346\226\271\346\263\225/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\271\266\350\241\214/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\205\245/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\207\272/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\226\255\350\267\257\345\231\250/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\234\211\347\225\214\345\271\266\350\241\214/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\224\237\346\210\220\345\231\250/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\255\226\347\225\245/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\243\205\351\245\260\345\231\250/index.html" create mode 100644 "\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\247\202\345\257\237\350\200\205/index.html" create mode 100644 "\345\267\245\347\250\213/go\350\257\255\350\250\200\350\247\204\350\214\203/index.html" create mode 100644 "\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/architect.html" create mode 100644 "\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/index.html" create mode 100644 "\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/intermediate.html" create mode 100644 "\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/primary.html" create mode 100644 "\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/senior.html" create mode 100644 "\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/\344\270\255\351\253\230\347\272\247go\351\235\242\350\257\225\351\242\230\344\270\200.html" create mode 100644 "\345\267\245\347\250\213/index.html" create mode 100644 "\345\267\245\347\250\213/ioc/index.html" create mode 100644 "\345\267\245\347\250\213/log/index.html" create mode 100644 "\345\267\245\347\250\213/wasm/index.html" create mode 100644 "\345\267\245\347\250\213/\344\273\243\347\240\201\346\243\200\346\237\245/index.html" create mode 100644 "\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/gin/index.html" create mode 100644 "\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/index.html" create mode 100644 "\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/sonic/index.html" create mode 100644 "\345\267\245\347\250\213/\345\212\250\346\200\201\350\260\203\350\257\225/index.html" create mode 100644 "\345\267\245\347\250\213/\345\214\205\345\217\212\345\205\266\346\236\204\345\273\272\345\267\245\345\205\267/index.html" create mode 100644 "\345\267\245\347\250\213/\345\217\215\345\260\204/index.html" create mode 100644 "\345\267\245\347\250\213/\345\221\275\344\273\244/index.html" create mode 100644 "\345\267\245\347\250\213/\345\235\221/index.html" create mode 100644 "\345\267\245\347\250\213/\345\255\227\347\254\246\347\274\226\347\240\201/index.html" create mode 100644 "\345\267\245\347\250\213/\346\265\213\350\257\225/index.html" create mode 100644 "\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\345\207\206\346\265\213\350\257\225.html" create mode 100644 "\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\347\241\200\346\265\213\350\257\225.html" create mode 100644 "\345\267\245\347\250\213/\346\265\213\350\257\225/\346\250\241\347\263\212\346\265\213\350\257\225.html" create mode 100644 "\345\267\245\347\250\213/\347\263\273\347\273\237\344\277\241\345\217\267\347\232\204\345\244\204\347\220\206/index.html" create mode 100644 "\345\267\245\347\250\213/\350\257\273\345\206\231\346\250\241\345\236\213/index.html" create mode 100644 "\345\267\245\347\250\213/\351\241\271\347\233\256\347\273\204\347\273\207\345\275\242\345\274\217/index.html" create mode 100644 "\345\271\266\345\217\221/atomic/index.html" create mode 100644 "\345\271\266\345\217\221/channel/index.html" create mode 100644 "\345\271\266\345\217\221/context/index.html" create mode 100644 "\345\271\266\345\217\221/index.html" create mode 100644 "\345\271\266\345\217\221/\345\206\205\345\255\230\346\250\241\345\236\213/index.html" create mode 100644 "\345\271\266\345\217\221/\345\220\214\346\255\245\345\216\237\350\257\255/index.html" create mode 100644 "\345\271\266\345\217\221/\345\271\266\345\217\221\346\250\241\345\236\213/index.html" create mode 100644 "\347\274\226\350\257\221\345\231\250/gc/index.html" create mode 100644 "\347\274\226\350\257\221\345\231\250/gccgo/index.html" create mode 100644 "\347\274\226\350\257\221\345\231\250/index.html" create mode 100644 "\347\274\226\350\257\221\345\231\250/llvm/index.html" diff --git a/404.html b/404.html new file mode 100644 index 000000000..90dd8a389 --- /dev/null +++ b/404.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/12.521ef871.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/2.5c331e53.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><div class="theme-default-content"><h1>404</h1> <blockquote>How did we get here?</blockquote> <a href="/GOFamily/" class="router-link-active"> + Take me home. + </a></div></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/12.521ef871.js" defer></script> + </body> +</html> diff --git a/CHANGELOG.html b/CHANGELOG.html new file mode 100644 index 000000000..5f9e5b3fd --- /dev/null +++ b/CHANGELOG.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/13.6a579e8b.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/CHANGELOG.html#v0-3-0-2022-03-02" class="sidebar-link">v0.3.0 (2022-03-02)</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/CHANGELOG.html#features" class="sidebar-link">Features</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p><a name="v0.3.0"></a></p> <h2 id="v0-3-0-2022-03-02">v0.3.0 (2022-03-02)</h2> <h2 id="features">Features</h2> <p>引入 ci</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/CHANGELOG.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/13.6a579e8b.js" defer></script> + </body> +</html> diff --git a/assets/css/0.styles.93ee3edc.css b/assets/css/0.styles.93ee3edc.css new file mode 100644 index 000000000..be8cbe390 --- /dev/null +++ b/assets/css/0.styles.93ee3edc.css @@ -0,0 +1 @@ +code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.theme-default-content code{color:#476582;padding:.25rem .5rem;margin:0;font-size:.85em;background-color:rgba(27,31,35,.05);border-radius:3px}.theme-default-content code .token.deleted{color:#ec5975}.theme-default-content code .token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}.theme-default-content pre[class*=language-] code,.theme-default-content pre code{color:#fff;padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:#282c34;border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.66)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:hsla(0,0%,100%,.4)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:3.5rem;height:100%;background-color:rgba(0,0,0,.66)}div[class*=language-].line-numbers-mode pre{padding-left:4.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:3.5rem;text-align:center;color:hsla(0,0%,100%,.3);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:3.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid rgba(0,0,0,.66);background-color:#282c34}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-docker]:before{content:"docker"}div[class~=language-dockerfile]:before{content:"dockerfile"}div[class~=language-makefile]:before{content:"makefile"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}div[class~=language-php]:before{content:"php"}.custom-block .custom-block-title{font-weight:600;margin-bottom:-.4rem}.custom-block.danger,.custom-block.tip,.custom-block.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983}.custom-block.warning{background-color:rgba(255,229,100,.3);border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:#2c3e50}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:#2c3e50}.custom-block.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:#eee}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.theme-default-content:not(.custom){max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.table-of-contents .badge{vertical-align:middle}body,html{padding:0;margin:0;background-color:#fff}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:#2c3e50}.page{padding-left:20rem}.navbar{z-index:20;right:0;height:3.6rem;background-color:#fff;box-sizing:border-box;border-bottom:1px solid #eaecef}.navbar,.sidebar-mask{position:fixed;top:0;left:0}.sidebar-mask{z-index:9;width:100vw;height:100vh;display:none}.sidebar{font-size:16px;background-color:#fff;width:20rem;position:fixed;z-index:10;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid #eaecef;overflow-y:auto}.theme-default-content:not(.custom)>:first-child{margin-top:3.6rem}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#3eaf7c}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1rem;color:#999;border-left:.2rem solid #dfe2e5;margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-top:-1.5rem;margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-block,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-block,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-block,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-block,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-block,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-block,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:focus .header-anchor,h1:hover .header-anchor,h2:focus .header-anchor,h2:hover .header-anchor,h3:focus .header-anchor,h3:hover .header-anchor,h4:focus .header-anchor,h4:hover .header-anchor,h5:focus .header-anchor,h5:hover .header-anchor,h6:focus .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid #eaecef}h3{font-size:1.35rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0}a.header-anchor:focus,a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid #eaecef}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}td,th{border:1px solid #dfe2e5;padding:.6em 1em}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px;width:16.4rem}.page{padding-left:16.4rem}}@media (max-width:719px){.sidebar{top:0;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.gt-container{width:80%;margin-left:auto;margin-right:auto}html{scroll-behavior:smooth}.go-to-top[data-v-5fd4ef0c]{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;color:#3eaf7c;z-index:1}.go-to-top[data-v-5fd4ef0c]:hover{color:#72cda4}@media (max-width:959px){.go-to-top[data-v-5fd4ef0c]{display:none}}.fade-enter-active[data-v-5fd4ef0c],.fade-leave-active[data-v-5fd4ef0c]{transition:opacity .3s}.fade-enter[data-v-5fd4ef0c],.fade-leave-to[data-v-5fd4ef0c]{opacity:0}#nprogress{pointer-events:none}#nprogress .bar{background:#3eaf7c;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #3eaf7c,0 0 5px #3eaf7c;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border-color:#3eaf7c transparent transparent #3eaf7c;border-style:solid;border-width:2px;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.icon.outbound{color:#aaa;display:inline-block;vertical-align:middle;position:relative;top:-1px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.home{padding:3.6rem 2rem 0;max-width:960px;margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:#6a8bad}.home .hero .action-button{display:inline-block;font-size:1.2rem;color:#fff;background-color:#3eaf7c;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #389d70}.home .hero .action-button:hover{background-color:#4abf8a}.home .features{border-top:1px solid #eaecef;padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:#3a5169}.home .feature p{color:#4e6e8e}.home .footer{padding:2.5rem;border-top:1px solid #eaecef;text-align:center;color:#4e6e8e}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;height:2rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/GOFamily/assets/img/search.83621669.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#3eaf7c}.search-box .suggestions{background:#fff;width:20rem;position:absolute;top:2rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion a{white-space:normal;color:#5d82a6}.search-box .suggestion a .page-title{font-weight:600}.search-box .suggestion a .header{font-size:.9em;margin-left:.25em}.search-box .suggestion.focused{background-color:#f3f4f5}.search-box .suggestion.focused a{color:#3eaf7c}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (-ms-high-contrast:none){.search-box input{height:2rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.sidebar-button{cursor:pointer;display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (max-width:719px){.sidebar-button{display:block}}.dropdown-enter,.dropdown-leave-to{height:0!important}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title,.dropdown-wrapper .mobile-dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:#2c3e50}.dropdown-wrapper .dropdown-title:hover,.dropdown-wrapper .mobile-dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow,.dropdown-wrapper .mobile-dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .mobile-dropdown-title{display:none;font-weight:600}.dropdown-wrapper .mobile-dropdown-title font-size inherit:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid #eee;padding:1rem 1.5rem .45rem 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #3eaf7c;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{display:none}.dropdown-wrapper .mobile-dropdown-title{display:block}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper.open:blur{display:none}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:#fff;padding:.6rem 0;border:1px solid;border-color:#ddd #ddd #ccc;text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#3eaf7c}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:#2c3e50}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #46bd87}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:#2c3e50;position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;background-color:#fff;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.page-edit{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-edit{padding:2rem}}@media (max-width:419px){.page-edit{padding:1.5rem}}.page-edit{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block}.page-edit .edit-link a{color:#4e6e8e;margin-right:.25rem}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:#4e6e8e}.page-edit .last-updated .time{font-weight:400;color:#767676}@media (max-width:719px){.page-edit .edit-link{margin-bottom:.5rem}.page-edit .last-updated{font-size:.8em;float:none;text-align:left}}.page-nav{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-nav{padding:2rem}}@media (max-width:419px){.page-nav{padding:1.5rem}}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid #eaecef;padding-top:1rem;overflow:auto}.page-nav .next{float:right}.page{padding-bottom:2rem;display:block}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading:not(.clickable){cursor:auto;color:inherit}.sidebar-group.is-sub-group{padding-left:0}.sidebar-group.is-sub-group>.sidebar-heading{font-size:.95em;line-height:1.4;font-weight:400;padding-left:2rem}.sidebar-group.is-sub-group>.sidebar-heading:not(.clickable){opacity:.5}.sidebar-group.is-sub-group>.sidebar-group-items{padding-left:1rem}.sidebar-group.is-sub-group>.sidebar-group-items>li>.sidebar-link{font-size:.95em;border-left:none}.sidebar-group.depth-2>.sidebar-heading{border-left:none}.sidebar-heading{color:#2c3e50;transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading.clickable.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-heading.clickable:hover{color:#3eaf7c}.sidebar-group-items{transition:height .1s ease-out;font-size:.95em;overflow:hidden}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}a.sidebar-link{font-size:1em;font-weight:400;display:inline-block;color:#2c3e50;border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#3eaf7c}a.sidebar-link.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid #eaecef;padding:.5rem 0 .75rem}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar>.sidebar-links{padding:1.5rem 0}.sidebar>.sidebar-links>li>a.sidebar-link{font-size:1.1em;line-height:1.7;font-weight:700}.sidebar>.sidebar-links>li:not(:first-child){margin-top:.75rem}@media (max-width:719px){.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar>.sidebar-links{padding:1rem 0}}.badge[data-v-15b7b770]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff}.badge.green[data-v-15b7b770],.badge.tip[data-v-15b7b770],.badge[data-v-15b7b770]{background-color:#42b983}.badge.error[data-v-15b7b770]{background-color:#da5961}.badge.warn[data-v-15b7b770],.badge.warning[data-v-15b7b770],.badge.yellow[data-v-15b7b770]{background-color:#e7c000}.badge+.badge[data-v-15b7b770]{margin-left:5px}.theme-code-block[data-v-759a7d02]{display:none}.theme-code-block__active[data-v-759a7d02]{display:block}.theme-code-block>pre[data-v-759a7d02]{background-color:orange}.theme-code-group__nav[data-v-deefee04]{margin-bottom:-35px;background-color:#282c34;padding-bottom:22px;border-top-left-radius:6px;border-top-right-radius:6px;padding-left:10px;padding-top:10px}.theme-code-group__ul[data-v-deefee04]{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.theme-code-group__nav-tab[data-v-deefee04]{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:hsla(0,0%,100%,.9);font-weight:600}.theme-code-group__nav-tab-active[data-v-deefee04]{border-bottom:1px solid #42b983}.pre-blank[data-v-deefee04]{color:#42b983} \ No newline at end of file diff --git a/assets/img/a.732405d8.png b/assets/img/a.732405d8.png new file mode 100644 index 0000000000000000000000000000000000000000..dd56ade1607c72201543127b7321b375d70cceb4 GIT binary patch literal 66181 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 M1x@)%S?hQIAKJ(-YybcN literal 0 HcmV?d00001 diff --git a/assets/img/gofunc.32e2f0aa.svg b/assets/img/gofunc.32e2f0aa.svg new file mode 100644 index 000000000..fe40dba20 --- /dev/null +++ b/assets/img/gofunc.32e2f0aa.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Do not edit this file with editors other than diagrams.net --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="742px" height="587px" viewBox="-0.5 -0.5 742 587" content="<mxfile host="Electron" modified="2023-03-24T19:26:43.709Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="5VgzJKjX12y5I334UJwm" version="20.3.0" type="device"><diagram id="VpiX2cICzOayVwReV_gE" name="第 1 页">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</diagram></mxfile>" style="background-color: rgb(255, 255, 255);"><defs/><g><rect x="120" y="140" width="170" height="350" rx="7" ry="7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="2" pointer-events="all"/><rect x="404" y="30" width="130" height="210" rx="7" ry="7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="2" pointer-events="all"/><rect x="610" y="30" width="130" height="170" rx="7" ry="7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="2" pointer-events="all"/><path d="M 675 230 L 590 230 L 590 110 L 526.37 110" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 521.12 110 L 528.12 106.5 L 526.37 110 L 528.12 113.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 675 230 L 675 200" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><rect x="404" y="280" width="126" height="160" rx="7" ry="7" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="2" pointer-events="all"/><path d="M 470 460 L 305 460 L 305 320 L 256.37 320" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 251.12 320 L 258.12 316.5 L 256.37 320 L 258.12 323.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 249 240 L 319 240 L 319 300 L 423.63 300" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 428.88 300 L 421.88 303.5 L 423.63 300 L 421.88 296.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 469 460 L 468.91 440" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 204.41 490 L 204.41 508.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 204.41 513.88 L 200.91 506.88 L 204.41 508.63 L 207.91 506.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 204.41 390 L 204.41 408.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 204.41 413.88 L 200.91 406.88 L 204.41 408.63 L 207.91 406.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 204.41 440 L 204.41 458.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 204.41 463.88 L 200.91 456.88 L 204.41 458.63 L 207.91 456.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 204.41 340 L 204.41 358.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 204.41 363.88 L 200.91 356.88 L 204.41 358.63 L 207.91 356.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="160" y="110" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 125px; margin-left: 161px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><b><font style="font-size: 16px;">main 包</font></b></div></div></div></foreignObject><text x="190" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">main 包</text></switch></g><rect x="439" y="0" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 15px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><b><font style="font-size: 16px;">pkg 1</font></b></div></div></div></foreignObject><text x="469" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">pkg 1</text></switch></g><rect x="645" y="0" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 15px; margin-left: 646px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><b><font style="font-size: 16px;">pkg 2</font></b></div></div></div></foreignObject><text x="675" y="19" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">pkg 2</text></switch></g><rect x="439" y="250" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 265px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><b><font style="font-size: 16px;">pkg 3</font></b></div></div></div></foreignObject><text x="469" y="269" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="12px" text-anchor="middle">pkg 3</text></switch></g><rect x="175" y="300" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 315px; margin-left: 176px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">const...</div></div></div></foreignObject><text x="205" y="320" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">const...</text></switch></g><rect x="175" y="360" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 375px; margin-left: 176px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">var...</div></div></div></foreignObject><text x="205" y="380" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">var...</text></switch></g><rect x="175" y="410" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 425px; margin-left: 176px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">init()</div></div></div></foreignObject><text x="205" y="430" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">init()</text></switch></g><rect x="175" y="460" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 475px; margin-left: 176px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">main()</div></div></div></foreignObject><text x="205" y="480" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">main()</text></switch></g><rect x="160" y="160" width="90" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 170px; margin-left: 161px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">import pkg1</div></div></div></foreignObject><text x="205" y="175" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">import pkg1</text></switch></g><rect x="155" y="220" width="100" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 230px; margin-left: 156px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">import pkg 3</div></div></div></foreignObject><text x="205" y="235" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">import pkg 3</text></switch></g><path d="M 250 180 L 350 180 L 350 70 L 417.63 70" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 422.88 70 L 415.88 73.5 L 417.63 70 L 415.88 66.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 60 170 L 143.63 170" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 148.88 170 L 141.88 173.5 L 143.63 170 L 141.88 166.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="0" y="150" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 165px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><h3>程序开始执行</h3></div></div></div></foreignObject><text x="30" y="170" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">程序开始执行</text></switch></g><path d="M 468.41 320 L 468.41 338.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 468.41 343.88 L 464.91 336.88 L 468.41 338.63 L 471.91 336.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="439" y="290" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 305px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">const...</div></div></div></foreignObject><text x="469" y="310" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">const...</text></switch></g><rect x="439" y="340" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 355px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">var...</div></div></div></foreignObject><text x="469" y="360" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">var...</text></switch></g><rect x="439" y="400" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 415px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">init()</div></div></div></foreignObject><text x="469" y="420" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">init()</text></switch></g><path d="M 468.82 370 L 468.86 380 L 468.83 393.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 468.82 398.88 L 465.33 391.88 L 468.83 393.63 L 472.33 391.89 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 468.41 125 L 468.41 143.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 468.41 148.88 L 464.91 141.88 L 468.41 143.63 L 471.91 141.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="439" y="95" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 110px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">const...</div></div></div></foreignObject><text x="469" y="115" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">const...</text></switch></g><rect x="439" y="145" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 160px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">var...</div></div></div></foreignObject><text x="469" y="165" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">var...</text></switch></g><rect x="439" y="205" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 220px; margin-left: 440px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">init()</div></div></div></foreignObject><text x="469" y="225" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">init()</text></switch></g><path d="M 468.82 175 L 468.86 185 L 468.83 198.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 468.82 203.88 L 465.33 196.88 L 468.83 198.63 L 472.33 196.89 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="424" y="60" width="90" height="20" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 70px; margin-left: 425px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">import pkg2</div></div></div></foreignObject><text x="469" y="75" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">import pkg2</text></switch></g><path d="M 520 70 L 600 70 L 621.52 69.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 626.77 69.54 L 619.83 73.16 L 621.52 69.63 L 619.71 66.16 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 674.41 85 L 674.41 103.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 674.41 108.88 L 670.91 101.88 L 674.41 103.63 L 677.91 101.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="645" y="55" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 70px; margin-left: 646px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">const...</div></div></div></foreignObject><text x="675" y="75" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">const...</text></switch></g><rect x="645" y="105" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 120px; margin-left: 646px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">var...</div></div></div></foreignObject><text x="675" y="125" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">var...</text></switch></g><rect x="645" y="165" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 180px; margin-left: 646px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">init()</div></div></div></foreignObject><text x="675" y="185" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">init()</text></switch></g><path d="M 674.82 135 L 674.86 145 L 674.83 158.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 674.82 163.88 L 671.33 156.88 L 674.83 158.63 L 678.33 156.89 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="175" y="530" width="60" height="30" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 545px; margin-left: 176px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 16px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><h3>程序执行完毕</h3></div></div></div></foreignObject><text x="205" y="550" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="16px" text-anchor="middle">程序执行完毕</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/assets/img/hash.b54950a0.svg b/assets/img/hash.b54950a0.svg new file mode 100644 index 000000000..857539bec --- /dev/null +++ b/assets/img/hash.b54950a0.svg @@ -0,0 +1,149 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="545px" height="556px" viewBox="0 0 545 556" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>未命名</title> + <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <rect id="矩形" stroke="#0A0101" fill="#D8D8D8" x="0.5" y="0.5" width="530" height="555"></rect> + <path id="直线-31" d="M442.995074,121.995122 L442.999976,122.495098 L443.916,215.995 L447.916454,215.956293 L443.504902,224.999976 L438.916887,216.044524 L442.916,216.005 L442.000024,122.504902 L441.995122,122.004926 L442.995074,121.995122 Z" fill="#979797" fill-rule="nonzero"></path> + <path id="直线-30" d="M443,77 L443,107 L447,107 L442.5,116 L438,107 L442,107 L442,77 L443,77 Z" fill="#979797" fill-rule="nonzero"></path> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="371.5" y="116.5" width="148" height="42"></rect> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="390.5" y="44.5" width="104" height="32"></rect> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="129.5" y="443.5" width="40" height="91"></rect> + <line x1="130.5" y1="459.5" x2="169.5" y2="459.5" id="直线-24" stroke="#979797" stroke-linecap="square"></line> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="41.5" y="443.5" width="42" height="91"></rect> + <line x1="41.5" y1="459.5" x2="82.5" y2="459.5" id="直线-21" stroke="#979797" stroke-linecap="square"></line> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="41.5" y="443.5" width="42" height="91"></rect> + <line x1="41.5" y1="459.5" x2="82.5" y2="459.5" id="直线-21" stroke="#979797" stroke-linecap="square"></line> + <line x1="84.5" y1="528.5" x2="106.5" y2="528.5" id="直线-18" stroke="#979797" stroke-linecap="square"></line> + <line x1="106.5" y1="528.5" x2="106.5" y2="452.5" id="直线-19" stroke="#979797" stroke-linecap="square"></line> + <path id="直线-16" d="M56,375 L56,434 L60,434 L55.5,443 L51,434 L55,434 L55,375 L56,375 Z" fill="#979797" fill-rule="nonzero"></path> + <line x1="55.5" y1="375.5" x2="71.5" y2="375.5" id="直线-17" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="77.5" x2="198.5" y2="77.5" id="直线-6" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="77.5" x2="198.5" y2="77.5" id="直线-5" stroke="#979797" stroke-linecap="square"></line> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="71.5" y="59.5" width="254" height="325"></rect> + <line x1="71.5" y1="328.5" x2="198.5" y2="328.5" id="直线-15" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="238.5" x2="198.5" y2="238.5" id="直线-13" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="253.5" x2="198.5" y2="253.5" id="直线-14" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="142.5" x2="198.5" y2="142.5" id="直线-10" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="158.5" x2="198.5" y2="158.5" id="直线-11" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="207.5" x2="198.5" y2="207.5" id="直线-12" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="91.5" x2="198.5" y2="91.5" id="直线-9" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="77.5" x2="198.5" y2="77.5" id="直线-7" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="77.5" x2="198.5" y2="77.5" id="直线-7" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="114.5" x2="198.5" y2="114.5" id="直线-8" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="127.5" x2="198.5" y2="127.5" id="直线-2" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="222.5" x2="198.5" y2="222.5" id="直线-3" stroke="#979797" stroke-linecap="square"></line> + <line x1="71.5" y1="347.5" x2="198.5" y2="347.5" id="直线-4" stroke="#979797" stroke-linecap="square"></line> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="71.5" y="24.5" width="254" height="35"></rect> + <text id="buckets[0]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="107.74" y="53">buckets[0]</tspan> + </text> + <text id="tophash[0]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000102" fill-opacity="0.5"> + <tspan x="111.68" y="74">tophash[0]</tspan> + </text> + <text id="key[0]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="120.192" y="138">key[0]</tspan> + </text> + <text id="key[1]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="120.192" y="155">key[1]</tspan> + </text> + <text id="key[7]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="120.192" y="217">key[7]</tspan> + </text> + <text id="value[0]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="116.852" y="234">value[0]</tspan> + </text> + <text id="value[1]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="116.852" y="250">value[1]</tspan> + </text> + <text id="value[7]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="120.852" y="343">value[7]</tspan> + </text> + <text id="overflow" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="119.732" y="373">overflow</tspan> + </text> + <text id="tophashs" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="43.616" y="453">tophashs</tspan> + </text> + <text id="overflow-buckets" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="76.768" y="427">overflow buckets</tspan> + </text> + <text id="keys" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="52.152" y="481">keys</tspan> + </text> + <text id="values" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="48.748" y="509">values</tspan> + </text> + <text id="overflow" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="44.732" y="531">overflow</tspan> + </text> + <text id="tophashs" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="133.616" y="455">tophashs</tspan> + </text> + <text id="链表" font-family="HarmonyOS_Sans_SC_Medium, HarmonyOS Sans SC" font-size="14" font-weight="400" fill="#000000" fill-opacity="0.5"> + <tspan x="282" y="460">链表</tspan> + </text> + <text id="keys" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="142.152" y="481">keys</tspan> + </text> + <text id="values" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="137.748" y="509">values</tspan> + </text> + <text id="overflow" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="133.732" y="531">overflow</tspan> + </text> + <text id="tophash[7]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="111.68" y="124">tophash[7]</tspan> + </text> + <text id="tophash[1]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="8" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="111.68" y="86">tophash[1]</tspan> + </text> + <text id=".-.-." font-family="HarmonyOS_Sans_SC_Black, HarmonyOS Sans SC" font-size="6" font-weight="800" fill="#000000"> + <tspan x="130.166" y="96">.</tspan> + <tspan x="130.166" y="104">.</tspan> + <tspan x="130.166" y="112">.</tspan> + </text> + <text id=".-.-." font-family="HarmonyOS_Sans_SC_Black, HarmonyOS Sans SC" font-size="6" font-weight="800" fill="#000000"> + <tspan x="130.166" y="177">.</tspan> + <tspan x="130.166" y="185">.</tspan> + <tspan x="130.166" y="193">.</tspan> + </text> + <text id=".-.-." font-family="HarmonyOS_Sans_SC_Black, HarmonyOS Sans SC" font-size="6" font-weight="800" fill="#000000"> + <tspan x="133.166" y="289">.</tspan> + <tspan x="133.166" y="297">.</tspan> + <tspan x="133.166" y="305">.</tspan> + </text> + <text id="buckets[1]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="239.74" y="52">buckets[1]</tspan> + </text> + <text id="v,ok-:=-m[key]" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="412.86" y="64">v,ok := m[key]</tspan> + </text> + <text id="hashcode-=-hash(key)" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="398.35" y="142">hashcode = hash(key)</tspan> + </text> + <line x1="198.5" y1="385.5" x2="198.5" y2="59.5" id="直线" stroke="#979797" stroke-linecap="square"></line> + <path id="直线-20" d="M120,448 L129,452.5 L120,457 L120,453 L106,453 L106,452 L120,452 L120,448 Z" fill="#979797" fill-rule="nonzero"></path> + <line x1="41.5" y1="489.5" x2="82.5" y2="489.5" id="直线-22" stroke="#979797" stroke-linecap="square"></line> + <line x1="130.5" y1="489.5" x2="169.5" y2="489.5" id="直线-25" stroke="#979797" stroke-linecap="square"></line> + <line x1="41.5" y1="521.5" x2="82.5" y2="521.5" id="直线-23" stroke="#979797" stroke-linecap="square"></line> + <line x1="130.5" y1="521.5" x2="169.5" y2="521.5" id="直线-23" stroke="#979797" stroke-linecap="square"></line> + <path d="M224,409 L224,552 L7,552 L7,409 L224,409 Z" id="直线-27" stroke="#830D0D" stroke-linecap="square"></path> + <path id="直线-28" d="M278.703934,463.822939 L279.177061,464.703934 L278.736563,464.940497 L232.225,489.918 L234.117523,493.442899 L224.059503,493.736563 L229.859383,485.513949 L231.751,489.037 L278.263437,464.059503 L278.703934,463.822939 Z" fill="#979797" fill-rule="nonzero"></path> + <path id="直线-29" d="M363,62 L372,66.5 L363,71 L363,62 Z M205,66 L205,67 L198,67 L198,66 L205,66 Z M217,66 L217,67 L210,67 L210,66 L217,66 Z M229,66 L229,67 L222,67 L222,66 L229,66 Z M241,66 L241,67 L234,67 L234,66 L241,66 Z M253,66 L253,67 L246,67 L246,66 L253,66 Z M265,66 L265,67 L258,67 L258,66 L265,66 Z M277,66 L277,67 L270,67 L270,66 L277,66 Z M289,66 L289,67 L282,67 L282,66 L289,66 Z M301,66 L301,67 L294,67 L294,66 L301,66 Z M313,66 L313,67 L306,67 L306,66 L313,66 Z M325,66 L325,67 L318,67 L318,66 L325,66 Z M337,66 L337,67 L330,67 L330,66 L337,66 Z M349,66 L349,67 L342,67 L342,66 L349,66 Z M361,66 L361,67 L354,67 L354,66 L361,66 Z" fill="#2621C7" fill-rule="nonzero" opacity="0.49781436"></path> + <rect id="矩形" stroke="#979797" fill="#D8D8D8" x="360.5" y="222.5" width="166" height="54"></rect> + <text id="hashcode高位区" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="366.32" y="256">hashcode高位区 </tspan> + </text> + <text id="hashcode的高位区域组成topha" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="356.575" y="319">hashcode的高位区域组成tophash,</tspan> + <tspan x="373.255" y="332">用来确定在tophash中的位置</tspan> + <tspan x="436.5" y="345"></tspan> + <tspan x="353.17" y="358">hashcode的低位区域经过mask最终来</tspan> + <tspan x="401.5" y="371">确定是哪一个桶 </tspan> + </text> + <text id="hashcode低位区" font-family="HarmonyOS_Sans_SC_Light, HarmonyOS Sans SC" font-size="10" font-weight="300" fill="#000000" fill-opacity="0.5"> + <tspan x="451.32" y="257">hashcode低位区</tspan> + </text> + <line x1="445.5" y1="221.5" x2="445.5" y2="276.5" id="直线-32" stroke="#979797" stroke-linecap="square"></line> + </g> +</svg> \ No newline at end of file diff --git a/assets/img/ringwaiter.c4e44723.png b/assets/img/ringwaiter.c4e44723.png new file mode 100644 index 0000000000000000000000000000000000000000..23d275975afb40248677c6b2c8ee5f4713d8a8b5 GIT binary patch literal 38556 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 literal 0 HcmV?d00001 diff --git a/assets/img/search.83621669.svg b/assets/img/search.83621669.svg new file mode 100644 index 000000000..03d83913e --- /dev/null +++ b/assets/img/search.83621669.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg> diff --git a/assets/img/wechat.4a3030a4.png b/assets/img/wechat.4a3030a4.png new file mode 100644 index 0000000000000000000000000000000000000000..81b494bee6a243f17e187f5ed353243575c4951a GIT binary patch literal 41224 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%0AruYyeMbQY39cN>XtA&jpJ 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 literal 0 HcmV?d00001 diff --git a/assets/js/10.993cf521.js b/assets/js/10.993cf521.js new file mode 100644 index 000000000..cdfb85d7c --- /dev/null +++ b/assets/js/10.993cf521.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{430:function(t,s,n){t.exports=n.p+"assets/img/a.732405d8.png"},533:function(t,s,n){"use strict";n.r(s);var e=n(36),i=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"go-项目组织形式"}},[this._v("go 项目组织形式")]),this._v(" "),s("p",[s("img",{attrs:{src:n(430),alt:""}})])])}),[],!1,null,null,null);s.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/100.049dca94.js b/assets/js/100.049dca94.js new file mode 100644 index 000000000..59334cf7a --- /dev/null +++ b/assets/js/100.049dca94.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[100],{530:function(t,e,s){"use strict";s.r(e);var n=s(36),l=Object(n.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"模糊测试"}},[t._v("模糊测试")]),t._v(" "),s("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),s("ul",[s("li",[t._v("https://go.dev/doc/tutorial/fuzz")]),t._v(" "),s("li",[t._v("https://mp.weixin.qq.com/s/kR8pCyjpYz_9ax6P7LyB2w")])])])}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/101.9e4a3cce.js b/assets/js/101.9e4a3cce.js new file mode 100644 index 000000000..ec0e2c707 --- /dev/null +++ b/assets/js/101.9e4a3cce.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[101],{531:function(t,s,e){"use strict";e.r(s);var n=e(36),r=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"系统信号的处理"}},[this._v("系统信号的处理")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/102.60455322.js b/assets/js/102.60455322.js new file mode 100644 index 000000000..17a70cd67 --- /dev/null +++ b/assets/js/102.60455322.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[102],{532:function(t,s,e){"use strict";e.r(s);var n=e(36),o=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"go-语言的读写模型"}},[this._v("go 语言的读写模型")])])}),[],!1,null,null,null);s.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/103.4ebce8b3.js b/assets/js/103.4ebce8b3.js new file mode 100644 index 000000000..00f252fcd --- /dev/null +++ b/assets/js/103.4ebce8b3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[103],{535:function(t,a,e){"use strict";e.r(a);var r=e(36),n=Object(r.a)({},(function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"并发"}},[t._v("并发")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"./%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B"}},[t._v("内存模型")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B"}},[t._v("并发模型")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91%E5%8E%9F%E8%AF%AD"}},[t._v("并发原语")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./channel"}},[t._v("channel")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./atomic"}},[t._v("atomic")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./context"}},[t._v("context")])])])])}),[],!1,null,null,null);a.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/104.dcbef6d1.js b/assets/js/104.dcbef6d1.js new file mode 100644 index 000000000..d40bbe1ab --- /dev/null +++ b/assets/js/104.dcbef6d1.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[104],{534:function(t,a,n){"use strict";n.r(a);var v=n(36),_=Object(v.a)({},(function(){var t=this,a=t.$createElement,n=t._self._c||a;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"atomic"}},[t._v("atomic")]),t._v(" "),n("p",[t._v("原子包是比互斥锁更底层的包,如果在简单的场景下,使用 sync.Mutex 可能会比较复杂,并且耗费资源,那么使用更加底层的 atomic 就更加划算了")]),t._v(" "),n("p",[t._v("所谓原子操作,就是当某 goroutine 去执行原子操作时,其它 goroutine 只能看着,这个操作要么成功,要么失败,不会有第三个状态")]),t._v(" "),n("p",[t._v("原子包操作对象的时候,都是操作的地址,所以谨记不要使用值操作而是要指针操作")]),t._v(" "),n("h2",{attrs:{id:"介绍一下-atomic-的内容"}},[t._v("介绍一下 atomic 的内容")]),t._v(" "),n("ul",[n("li",[t._v("Add:例如 "),n("code",[t._v("func AddInt32(addr *int32,delta int32)(new int32)")]),t._v(" 给第一个参数地址指向的数据值增加一个 delta 并返回新的数据")]),t._v(" "),n("li",[t._v("CompareAndSwap:例如 "),n("code",[t._v("func CompareAndSwapInt32(addr *int32,old,new int32)(swapped bool)")]),t._v(" 比较 addr 指向的数据是否等于 old,如果不等于返回 false,如果等于就将此地址的值切换为 new 值,并且返回 true")]),t._v(" "),n("li",[t._v("Load:例如 "),n("code",[t._v("func LoadInt32(addr *int32)(val int32)")]),t._v(" 读取 addr 指向的值并返回")]),t._v(" "),n("li",[t._v("Store:例如 "),n("code",[t._v("func StoreInt32(addr *int32,val int32)")]),t._v(" 将 val 值写入到 addr 指向的内存空间中")]),t._v(" "),n("li",[t._v("Swap:例如 "),n("code",[t._v("func SwapInt32(addr *int32,new int32)(old int32)")]),t._v(" 将 addr 指向的值切换为 new 值,并返回旧值")]),t._v(" "),n("li",[t._v("Value:"),n("code",[t._v("type Value")]),t._v(" "),n("code",[t._v("func(*Value) Load")]),t._v(" "),n("code",[t._v("func(*Value) Store")]),t._v(" 原子的存取数据")])]),t._v(" "),n("p",[t._v("目前 atomic 还没有部署泛型,所以里面到处充斥者 "),n("code",[t._v("LoadInt32")]),t._v(" "),n("code",[t._v("LoadInt64")]),t._v(" 这种类型的函数,以后等泛型部署到原子包后就不会这么繁琐了")]),t._v(" "),n("h2",{attrs:{id:"基于原子库的第三方扩展"}},[t._v("基于原子库的第三方扩展")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("uber-go/atomic 定义扩展了几种常见类型的原子操作,例如 bool error string 等")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" atom atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Uint32\natom"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Store")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\natom"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sub")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\natom"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("CompareAndSwap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("40")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("11")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("看起来的确比官方提供的原子包更加简洁一些")])])]),t._v(" "),n("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),n("h3",{attrs:{id:"对一个地址的赋值是原子操作吗"}},[t._v("对一个地址的赋值是原子操作吗?")]),t._v(" "),n("p",[t._v("如果对于单核处理器的机器来说,地址的赋值是原子操作")]),t._v(" "),n("p",[t._v("在现在的系统中,write 的地址基本上都是对齐的")]),t._v(" "),n("p",[t._v("对齐地址的写,不会导致其他人看到只写了一半的数据,因为它通过一个指令就可以实现对地址的操作,如果地址不是对齐的话,那么,处理器就需要分成两个指令去处理,如果执行了一个指令,其它人就会看到更新了一半的错误的数据,这被称做撕裂写")]),t._v(" "),n("p",[t._v("所以,你可以认为赋值操作是一个原子操作")]),t._v(" "),n("p",[t._v("但是,对于现代的多处理多核的系统来说,由于 cache、指令重排,可见性等问题,我们\n对原子操作的意义有了更多的追求。")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("在多核系统中,一个核对地址的值的更改,在更新到主内存中之前,是在多级缓存中存放的。这时,多个核看到的数据可能是不一样的")])])]),t._v(" "),n("p",[t._v("多处理器多核心系统为了处理这类问题,使用了一种叫做内存屏障 (memory fence 或\nmemory barrier) 的方式。一个写内存屏障会告诉处理器,必须要等到它管道中的未完成\n的操作 (特别是写操作) 都被刷新到内存中,再进行操作。")]),t._v(" "),n("p",[t._v("atomic 包提供的方法会提供了一些的功能,不仅仅可以保证赋值的数据完整性,还能保证数据的可见性,一旦一个核更新了该地址的值,其它处理器总是能读取到它的最新值。")]),t._v(" "),n("p",[t._v("atomic 包主要利用了以下几点技术:")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("编译器插入内存屏障 (Memory Barrier) 指令\n编译器会在 atomic 操作前后插入内存屏障指令,来限制 CPU 的乱序执行,保证在该操作前的读写操作都完成,之后的读写都待其完成后再执行。")])]),t._v(" "),n("li",[n("p",[t._v("硬件支持的原子 CPU 指令\n如 X86 的 LOCK 指令可以将某些指令变为原子指令。atomic 会利用 CPU 提供的这些原子指令实现加锁。")])]),t._v(" "),n("li",[n("p",[t._v("缓存一致性硬件协议\n如 Intel 的 MESI 协议可以在多核间保证缓存的一致性。atomic 利用缓存一致性,使得多个核心缓存中的数据版本是一致的。")])]),t._v(" "),n("li",[n("p",[t._v("核心间互斥\natomic 中的原子操作会在多核间加锁,保证同时只有一个核心可以操作共享变量。")])])]),t._v(" "),n("p",[t._v("需要注意的是,因为需要处理器之间保证数据的一致性,atomic 的操作是会降低性能的。")]),t._v(" "),n("p",[t._v("综上所述,"),n("em",[n("strong",[t._v("对于单核机器来说,普通的地址赋值就是原子操作,但是对于多核机器来说,不属于原子操作,原子包去进行的赋值一定是原子操作")])])]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("go.dev")]),t._v(" "),n("li",[t._v("https://time.geekbang.org/column/intro/100061801")]),t._v(" "),n("li",[t._v("《go 进阶训练营》")]),t._v(" "),n("li",[t._v("《go 语言精进之路》")])])])}),[],!1,null,null,null);a.default=_.exports}}]); \ No newline at end of file diff --git a/assets/js/105.76803baf.js b/assets/js/105.76803baf.js new file mode 100644 index 000000000..9f00d4a25 --- /dev/null +++ b/assets/js/105.76803baf.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[105],{536:function(t,s,n){"use strict";n.r(s);var a=n(36),e=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"channel"}},[t._v("channel")]),t._v(" "),n("p",[t._v("channel 是 csp 并发模型中的重要组成部分,它完成的使命是 goroutine 之间的通信。也就是 csp 中的 c。")]),t._v(" "),n("p",[t._v("channel 是 go 语言语言级的线程安全的通信组件,它是 go 语言的一个内置类型,也因此 go 语言才被称之为在设计之初就考虑了并发的语言。")]),t._v(" "),n("p",[t._v("go 语言之父 rob pike 曾说到 “不要使用共享内存的方式去通信,而是通过通信的方式去共享内存” 这句话就是形容的 channel,这句话的意思是说,我们正在执行的程序不应该通过共享内存的方式去完成这个并发操作,各个线程应该各自运行,互不干涉,使用通信的方式去交流去分享内存信息即可。")]),t._v(" "),n("h2",{attrs:{id:"基础用法"}},[t._v("基础用法")]),t._v(" "),n("h3",{attrs:{id:"创建-channel"}},[t._v("创建 channel")]),t._v(" "),n("p",[t._v("channel 是一个引用类型,所以创建一个 channel 必须划定底层内存给 channel,所以需要使用 make,不使用 make 只用来声明的 channel,其初始值就是 nil,这一点跟其它引用类型,例如接口,切片,map 是一致的。")]),t._v(" "),n("p",[t._v("对于 nil 的 channel,发送和接收数据总是会阻塞的,对于 nil 的 channel,关闭它直接会 panic "),n("code",[t._v("panic: close of nil channel")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建一个无缓存channel")]),t._v("\nch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建一个有缓存的channel")]),t._v("\nch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("一个无缓存的 channel,只有接收了数据,才能发送下一个数据往通道中,一个有缓存的数据,比如这里是 10,那么可以往这个 channel 中发送 10 个数据,并且不需要接收,只有发送第十一个数据的时候才会发送阻塞。")]),t._v(" "),n("blockquote",[n("p",[t._v("关于 channel 的多线程规则,请参考"),n("a",{attrs:{href:"../%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B"}},[t._v("内存模型")]),t._v("这一章节")])]),t._v(" "),n("h3",{attrs:{id:"channel-分为三种类型"}},[t._v("channel 分为三种类型")]),t._v(" "),n("ul",[n("li",[t._v("只能发送的 channel "),n("code",[t._v("chan<-")])]),t._v(" "),n("li",[t._v("只能接收的 channel "),n("code",[t._v("<-chan")])]),t._v(" "),n("li",[t._v("可发可收的 channel "),n("code",[t._v("chan")])])]),t._v(" "),n("p",[t._v("channel 里面理论上可以存在任意的类型数据,当然也包括 channel 自己,那么当 channel 中出现了很多符号时该如何区分呢?")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" \n")])])]),n("p",[t._v("这里有个规则,符号总是跟左侧的 chan 在一起表示含义,比如这里,就是一个只能发送的 channel,里面保存的是一个 int 类型的 channel")]),t._v(" "),n("p",[t._v("我们知道,channel 可以拥有三种不同的类型,能发能收的 channel 是满足前两者的,也就是说,当你声明的是一个只能接收的 channel,你可以传入一个能收能发的 channel,但当你声明的是一个能收也能发的 channel 时,就不能传递进去一个只能发或者只能收的 channel")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌ ")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// cannot use c (variable of type <-chan int) as chan int value in argument to age")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("所以,通常我们实际使用当中都是这样的场景,某个函数中的参数是一个只读或者只发的一个 channel 类型,我们传递进去的是一个能收能发的 channel。")]),t._v(" "),n("p",[t._v("因为我们在函数的参数中这么设置是为了避免使用中出现 bug,比如某个函数它就只能收数据,所以给定它的是一个只能收的 channel 非常合理,但是为什么我们创建时要创建一个能收也能发的 channel 呢?因为这个 channel 必定要在其它的 goroutine 中被发送数据,这个其它 goroutine 参数可能被设置为只能发送。")]),t._v(" "),n("p",[t._v("总结一下,设置只能发或者只能收的 channel 本质上只是为了限制函数的能力是为了避免不必要的 bug,但是 channel 的本质我们还是要清楚的:在不同的 goroutine 之间传递信息")]),t._v(" "),n("p",[t._v("同时,除了上面这个禁忌之外,"),n("strong",[t._v("只能收")]),t._v("的 channel 不能 close,一旦 close 就会 panic,不过只能发的 channel 倒是可以 close 这个操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//❌")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// invalid operation: cannot close receive-only channel c (variable of type <-chan int)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//❌ ")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//invalid operation: cannot close receive-only channel c (variable of type <-chan int)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ✅")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//✅")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"发送数据"}},[t._v("发送数据")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n")])])]),n("h3",{attrs:{id:"接收数据"}},[t._v("接收数据")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接收但舍弃数值")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// <- ch")]),t._v("\n \n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接收并赋值")]),t._v("\n c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" ch\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"关闭-channel"}},[t._v("关闭 channel")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("h3",{attrs:{id:"判断从-channel-中取出的值是否有效"}},[t._v("判断从 channel 中取出的值是否有效")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 是有效值")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//是零值")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("ok 的值表示的是 “接收是否会成功”,而不是 channel 是否已关闭")]),t._v(" "),n("p",[t._v("当 channel 已关闭且数据已取完,再接收时 ok 会为 false,表示 “接收不会成功”")]),t._v(" "),n("p",[t._v("不过值得注意的是,即使 channel 已经关闭,如果之前 channel 中还有数据未被消费,那么数据也能被正常的读取:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 向channel发送3个数据")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"已经关闭了channel,并且没有取值"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// channel中还有未消费的数据,可以正常读取")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// channel数据已取完,此时会立即得到零值")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 0")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 再次关闭channel会panic")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"range-channel"}},[t._v("range channel")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" value "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("值得注意的是,一个 channel 如果没有被关闭,那么 range 操作将会一直阻塞,所以通常我们都会关闭这个 channel,好让程序继续执行")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\twg1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n")])])]),n("p",[t._v("注意看,这个关闭的操作其实是另起了一个 goroutine,因为你为了 waitgroup 的完全执行完毕,所以使用新的 goroutine 去关闭 channel 的操作是比较常见的做法,你可以参考这个"),n("a",{attrs:{href:"https://github.com/shgopher/collie",target:"_blank",rel:"noopener noreferrer"}},[t._v("项目"),n("OutboundLink")],1)]),t._v(" "),n("h3",{attrs:{id:"其它操作-len-cap"}},[t._v("其它操作:len cap")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取channel中缓存的中还未被取走的元素数量")]),t._v("\nfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取channel的容量")]),t._v("\nfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("cap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("h3",{attrs:{id:"不同状态-channel-的总结"}},[t._v("不同状态 channel 的总结")]),t._v(" "),n("table",[n("thead",[n("tr",[n("th",{staticStyle:{"text-align":"center"}},[t._v("状态")]),t._v(" "),n("th",{staticStyle:{"text-align":"center"}},[t._v("发送数据")]),t._v(" "),n("th",{staticStyle:{"text-align":"center"}},[t._v("接收数据")]),t._v(" "),n("th",{staticStyle:{"text-align":"center"}},[t._v("关闭chan")])])]),t._v(" "),n("tbody",[n("tr",[n("td",{staticStyle:{"text-align":"center"}},[t._v("正常")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("正常")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("正常")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("正常")])]),t._v(" "),n("tr",[n("td",{staticStyle:{"text-align":"center"}},[t._v("nil")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("阻塞")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("阻塞")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("panic")])]),t._v(" "),n("tr",[n("td",{staticStyle:{"text-align":"center"}},[t._v("closed")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("panic")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("正常值+零值")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("panic")])])])]),t._v(" "),n("p",[t._v("对于正常的 channel,如果它没有缓存,那么读写都会发生阻塞,除非另一方准备好,对于有 buffer 的 channel,当它还有缓存的时候,随意发送数据,这个时候收可以不准备好,当他满了,其实跟没有 buffer 的是一样的,这里就不过多讨论了,可以去查看"),n("RouterLink",{attrs:{to:"/并发/内存模型/"}},[t._v("内存模型")]),t._v("那一章")],1),t._v(" "),n("h2",{attrs:{id:"select"}},[t._v("select")]),t._v(" "),n("p",[t._v("select 是 go 语言提供的,供 channel 去操作的一个组件,它的基本使用方法如下")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" ch1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" ch2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ch被关闭了"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" ch1"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ch1 发送成功"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" ch2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ch2 接收到值"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ch没有被关闭"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("首先,select 的 case 中只能存放 channel 的收和发,以及一个 default 分支,各个分支如果在相同时间满足了条件是会随机去走分支的,不存在先后顺序,在 select 中也是可以去做判断的,判断 channel 是否存在正常值")]),t._v(" "),n("p",[t._v("select 本身不具有循环性质,所以通常被配合 for 循环使用")]),t._v(" "),n("p",[t._v("select 在没有任何 case 的时候会陷入阻塞,我们如果希望有一个阻塞存在,使用 select 是极好的:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n")])])]),n("h3",{attrs:{id:"对于-select-for-和-time-sleep-的阻塞机制的理解"}},[t._v("对于 select for 和 time.Sleep 的阻塞机制的理解")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("1。使用 for 循环不会造成 cpu 的执行吗?还是说 cpu 陷入了休眠状态,time.Sleep 呢?")])])]),t._v(" "),n("p",[t._v("使用 "),n("code",[t._v("for{}")]),t._v(" 循环会导致 CPU 高速空转。")]),t._v(" "),n("p",[t._v("for 循环本质上是一个忙等待/空转,CPU 会一直执行循环体内容,只不过这里的循环体为空,所以 CPU 会一直空转浪费资源。")]),t._v(" "),n("p",[t._v("相比而言,time.Sleep() 会"),n("strong",[t._v("让出 CPU 时间片")]),t._v(",把 goroutine 暂停一段时间,在这段时间 CPU 可以去执行其他任务。当 sleep 时间结束,goroutine 会重新得到时间片继续执行。")]),t._v(" "),n("p",[t._v("所以从资源利用效率来说,time.Sleep() 明显优于 for 循环的空转方式。")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("2。那么 select {} 呢是高速空转还是让出资源呢?")])])]),t._v(" "),n("p",[t._v("当 select 里所有的 case 都不 ready 时,它会释放 CPU 时间片,使当前 goroutine 进入阻塞状态,这就避免了空转。")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("3。select 的不同 case,在等待 case ready 的时候,select 是靠调度器去看 case 是否 ready 还是不停的轮询呢?")])])]),t._v(" "),n("p",[t._v("select 内部实现了更精密的监听逻辑:")]),t._v(" "),n("ul",[n("li",[t._v("为每个 case 的 channel 设置监听器")]),t._v(" "),n("li",[t._v("当前 goroutine 阻塞时释放 CPU 执行权")]),t._v(" "),n("li",[t._v("监听器异步监控 channel 状态")]),t._v(" "),n("li",[t._v("有 channel ready 则唤醒 goroutine")])]),t._v(" "),n("p",[t._v("所以 select 不是通过忙碌的轮询来判断 channel ready,而是通过异步监听的方式,只在必要的时刻唤醒 goroutine。")]),t._v(" "),n("p",[t._v("这种方式可以极大地减少 CPU 的占用,效率也更高。")]),t._v(" "),n("p",[t._v("综上所述,如果你想设置一个阻塞时,使用一个没有 case 的 select 是比一个空 for 循环更好的方法,如果你想设置一个有时间的阻塞时,使用 time.Sleep 无疑是更好的选择,不过这里需要注意的是 time.Sleep 的精度并不高,特别高精度的阻塞不要使用这个函数,select 设计非常精妙,在等待 case 的时候并不会大量耗费 cpu 的执行时间,而是让出 cpu 的执行片段,设置监听,异步的去获取状态,所以 select 的性能是非常不错的")]),t._v(" "),n("h2",{attrs:{id:"定时器"}},[t._v("定时器")]),t._v(" "),n("p",[t._v("在 go 语言中,go 提供了定时器给用户,基本的使用方法如下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在一秒后给case发送信息")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 心跳信号,每间隔一秒发送一次信息")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Tick")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("通常来说,这是为了超时而去设置的跳出机制")]),t._v(" "),n("h3",{attrs:{id:"cron-规则定时任务框架-robfig-cron"}},[t._v("cron 规则定时任务框架 robfig/cron")]),t._v(" "),n("p",[t._v("robfig/cron 是一个 Go 语言编写的 Cron 计划任务管理器。")]),t._v(" "),n("p",[t._v("这个项目的主要功能和特点包括:")]),t._v(" "),n("ul",[n("li",[t._v("实现了 cron 规范,可以基于 cron 表达式来调度任务")]),t._v(" "),n("li",[t._v("支持在代码中以声明式方式定义定时任务")]),t._v(" "),n("li",[t._v("支持在配置文件中定义定时任务")]),t._v(" "),n("li",[t._v("支持任务链,一个任务可以触发其他任务")]),t._v(" "),n("li",[t._v("支持任务锁,防止并发执行")]),t._v(" "),n("li",[t._v("支持失败重试")]),t._v(" "),n("li",[t._v("有默认的日志记录器,也可以自定义日志记录器")]),t._v(" "),n("li",[t._v("轻量级,没有外部依赖")])]),t._v(" "),n("p",[t._v("robfig/cron 因为其简单、轻量和高效而被许多 Go 项目用来实现定时任务。它可以用于项目中不同粒度的调度需求,如每分钟执行、每小时执行等。")]),t._v(" "),n("p",[t._v("下面解释一下 cron 机制的含义:")]),t._v(" "),n("p",[t._v("cron 表达式调度是 cron 作业调度程序的核心机制。")]),t._v(" "),n("p",[t._v("cron 表达式是一个字符串,由 5 或 6 个用空格分隔的字段组成,每个字段表示一个时间单位。Cron 会根据表达式中设置的值,在特定的时间点触发相应的任务。")]),t._v(" "),n("p",[t._v("cron 表达式的字段与意义如下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("# 文件格式說明\n# ┌──分钟("),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("59")]),t._v(")\n# │ ┌──小时("),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("23")]),t._v(")\n# │ │ ┌──日("),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("31")]),t._v(")\n# │ │ │ ┌─月("),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(")\n# │ │ │ │ ┌─星期("),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),t._v(",表示从周日到周六)\n# │ │ │ │ │ ┌─年份( "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" 表示全部年份,"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2024")]),t._v(" 表示只在"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2024")]),t._v("年)\n# │ │ │ │ │ │\n# "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n\n# 例如\n# "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("\n# 每天 "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" 点触发\n")])])]),n("p",[t._v("每个字段可以使用特殊字符表示多种时间设置:")]),t._v(" "),n("ul",[n("li",[n("code",[t._v("*")]),t._v(":表示匹配该字段的任意值")]),t._v(" "),n("li",[n("code",[t._v(",")]),t._v(":表示分隔多个值,如在分钟字段使用 “5,15,25” 就表示5分、15分、25分都触发")]),t._v(" "),n("li",[n("code",[t._v("-")]),t._v(":表示一个范围,如在小时字段使用 “9-17” 表示 9 点到 17 点之间每个整点都触发")]),t._v(" "),n("li",[n("code",[t._v("/")]),t._v(":表示一个间隔,如在分钟字段使用 “0/15” 表示每15分钟触发一次,从0分开始")]),t._v(" "),n("li",[n("code",[t._v("?")]),t._v(":表示不指定的值,会匹配该字段的任意值。")])]),t._v(" "),n("p",[t._v("一些例子:")]),t._v(" "),n("ul",[n("li",[n("code",[t._v("0 0 12 * * ?")]),t._v(":每天 12 点触发")]),t._v(" "),n("li",[n("code",[t._v("0 15 10 ? * *")]),t._v(":每天 10:15 触发")]),t._v(" "),n("li",[n("code",[t._v("0 0/5 14 * * ?")]),t._v(":每天 14:00 到 14:55 每5分钟触发一次")]),t._v(" "),n("li",[n("code",[t._v("0 0/5 14,18 * * ?")]),t._v(":每天 14:00 到 14:55 和 18:00 到 18:55 每5分钟触发一次")])]),t._v(" "),n("p",[t._v("通过这种表达式,cron 可以非常灵活地设置触发时间表,从而实现各种调度需求。")]),t._v(" "),n("p",[t._v("下面给出这个项目的 demo:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" cron"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 每小时的第30分钟执行")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"30 * * * *"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"每小时的第30分钟"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在每天早上3点到6点,晚上8点到11点的范围内,每小时执行一次 ")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"30 3-6,20-23 * * *"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"在每天早上3点到6点,晚上8点到11点的范围内,每小时执行一次"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 每天早上东京时间4点30分执行一次")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"CRON_TZ=Asia/Tokyo 30 04 * * *"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"每天早上东京时间4点30分执行一次"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从现在起每小时执行一次")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@hourly"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"从现在起每小时执行一次"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从现在起每隔1小时30分执行一次 ")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@every 1h30m"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"从现在起每隔1小时30分执行一次"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Start")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 被添加的函数会在自己的goroutine中异步执行")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 也可以向已经启动的Cron添加新的函数")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"@daily"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"每天执行"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 检查cron任务下次和上次的执行时间")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("inspect")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Entries")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 停止调度器(已经启动的任务不会被停止)")]),t._v("\nc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Stop")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("h2",{attrs:{id:"使用反射执行未知数量的-channel"}},[t._v("使用反射执行未知数量的 channel")]),t._v(" "),n("p",[t._v("当你不确定需要多少个 channel 去处理时,你只能选择在运行时去创建未知数量的 channel,这个时候就要使用反射了。")]),t._v(" "),n("p",[t._v("我们使用 "),n("code",[t._v("reflect.Select(cases []reflect.SelectCase)(chosen int,recv reflect.Value,recvok bool)")]),t._v(" 去实现 select")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"reflect"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用反射创建的select")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tch2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" cases "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("createSelectCase")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ch2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// chosen:channel 切片的索引")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// recv:收到的值")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ok:是否是通道上发送的值(而不是因为通道关闭而接收到的零值)")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Select最多支持 65536 个channel")]),t._v("\n\t\tchosen"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" recv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" recv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("IsValid")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 收")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"recv:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("chosen"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Dir"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" recv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 发")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"send:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("chosen"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Dir"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("createSelectCase")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" cases "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建 收 channel")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" chs "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tcases "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tDir"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectRecv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 发 or 收")]),t._v("\n\t\t\tChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ValueOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 具体 Channel")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建 发 channel")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" chs "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tcases "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tDir"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectSend"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 发 or 收")]),t._v("\n\t\t\tChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ValueOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 具体 channel")]),t._v("\n\t\t\tSend"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ValueOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 发送的值")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" cases\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n")])])]),n("h2",{attrs:{id:"数据交流-生产者-消费者模式"}},[t._v("数据交流---生产者/消费者模式")]),t._v(" "),n("p",[t._v("著名的 worker pool,如果使用 channel 去实现的话,就是一个标准的生产者消费者模式")]),t._v(" "),n("p",[t._v("为了组成这个结构,需要一个存储任务的数据结构,那么这里肯定是使用一个 channel")]),t._v(" "),n("p",[t._v("基本原理就是,一边往 channel 中发送数据,一边从 channel 中取数据,然后使用固定数量的 goroutine 去消费 channel 中的数据,刚好形成一个完整的生产者消费者模式,这就是复用 goroutine 的模式。")]),t._v(" "),n("p",[t._v("具体的额外操作还有控制 worker 数量,任务放入 woker 池,以及从 woker 池取出任务这个操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tctx"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cal "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithTimeout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("TODO")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("cal")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ctx"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"退出"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 往 channel 中 发送数据")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("89")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("这就是基本的生产者消费者模式,以及 channel 去数据交流的最基础的原理,下面我们来实现一个真正的可用的 worker pool")]),t._v(" "),n("p",[t._v("一个真正可用的 worker pool 不仅需要一个任务 channel,还需要存储任务 channel 的 woker pool,而这个 woker pool 是一个 chan chan 类型")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" worker "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n wokerPool "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("worker\n jobChannel "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Job\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("之所以需要一个 chan chan 原因也很简单,如果只有一个 chan,那么 10 几个固定数目的 goroutine 将会互斥的读取一个 channel 的数据,如果是 chan chan 则互不打扰各自读取自己的 channel 即可。")]),t._v(" "),n("p",[t._v("在这个项目中,我们会将读取的 channel 和处理的 channel 分开,读写分离,进行解耦,\n读取数据的 channel 只需要一个即可,处理的 channel 可以有多个")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("worker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("run")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将 单个channel(可以简单的这么认为为一个 channel) ")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 放入 wokerPool 中")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果 这个 单个woker(这里代表单个channel)不再使用的话")]),t._v("\n w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("workerPool "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" w\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" job "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jobChannel"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从单个channel中读取数据并处理")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("job")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n")])])]),n("p",[t._v("接下来我们需要一个任务分发的函数,也就是从读取的单个 channel 中读取数据,然后发送给多个处理任务的 channel")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" dispatcher "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n workerPool "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("worker\n OneChannel "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Job\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dispatcher "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("dispatcher"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("run")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" job "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" dispatcher"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("OneChannel"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从单个channel中读取数据")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从 wokerPool 中获取一个worker")]),t._v("\n work "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" disatcher"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("workerPool\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 给这个worker发送任务")]),t._v("\n work"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("jobChannel "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" job\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunDispatcher")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("workerPool "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("workerPool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 启动固定数目的goroutine去消费任务,并且每一个goroutine拥有一个独立的channel")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("cap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("workerPool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n worker "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("newWorker")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("workerPool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n worker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("run")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 启动分发器")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" dispatcher"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("run")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("大致的运行规律就是这些,其它的完整功能请查看这里:https://github.com/shgopher/grpool")]),t._v(" "),n("h2",{attrs:{id:"传递信号-通知"}},[t._v("传递信号/通知")]),t._v(" "),n("p",[t._v("当使用 channel 去传递信号的用法")]),t._v(" "),n("p",[t._v("例如使用一个 channel 去充当信号量,当 channel 没有被关闭的时候,那么就会一直阻塞,一旦 closed,那么就能读取到数据,自然就完成了信号的传递,这种用法非常常见,比如:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这里使用的 channel 就是充当了一个传递信号的功能。一旦信号传递过来,整个函数就可以继续运行下去了。")]),t._v(" "),n("p",[t._v("或者我们也可以传递一个空的结构体而不是直接 close(ch):")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"收发同时进行的信号"}},[t._v("收发同时进行的信号")]),t._v(" "),n("p",[t._v("你也可能见过这种表现方式,当 channel 充当信号的时候,发和收同时进行,看一个例子:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stop"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// B")]),t._v("\n\t\t\t\tw"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stop "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// C")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 另一段代码")]),t._v("\n\tw"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stop "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// A")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("stop "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// D")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("先说结论,这种用法提供了两个意思,提供信号+判断是否运行完毕")]),t._v(" "),n("p",[t._v("A 代码等 B 准备好之后,发送了信号;\nB 代码接受到了信号,这算完成了第一个含义,提供信号")]),t._v(" "),n("p",[t._v("C 代码等 D 代码准备完毕,发送了信号,D 接受完毕,这个表示 A 通知 B 干的事儿,圆满完成,这里是表示判断是否执行完毕")]),t._v(" "),n("h3",{attrs:{id:"使用计时器去解决长等待问题"}},[t._v("使用计时器去解决长等待问题")]),t._v(" "),n("p",[t._v("一般来说,我们都是希望程序执行完毕之后自己主动退出,比如:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("很合理,一般执行完毕之后,就会通知主 goroutine 优雅退出,但是如果执行的时间过长,用户很有可能就会失去信息,这个时候就需要我们再设置一个超时时间更加优雅的退出")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"处理超时"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"信号传递之-or-do-模式"}},[t._v("信号传递之 or-do 模式")]),t._v(" "),n("p",[t._v("channel 信号传递之 or-do 模式跟 go 并发原语的 "),n("RouterLink",{attrs:{to:"/并发/同步原语/#singleflight"}},[t._v("singleflight")]),t._v(" 比较类似")],1),t._v(" "),n("p",[t._v("区别是,channel 的 or-do 是多个信号传递,只有一个 channel 获取信号之后就可以停止其它 channel 了,并不需要将这个信号传递给其它的 channel,singleflight 是需要分享情报的。")]),t._v(" "),n("p",[t._v("下面有两种实现的方式,递归和反射,递归比较适合递归树较低的场景,反射就适合了递归树更高的场景,因为如果递归过深的话很容易出现内存溢出的情况,如果你认为你项目中的 goroutine 也就几十那么递归就可以了,毕竟反射可是很浪费执行时间的,如果 goroutine 成千上万,选用反射即可。")]),t._v(" "),n("p",[t._v("使用递归的方法:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Ordo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 递归退出条件")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tor "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("or"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tmi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Ordo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("mi"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Ordo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("mi"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" or\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("使用反射的方式:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Ordo1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 递归退出条件")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tor "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("or"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" cases "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" chs "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tcases "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tDir"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectRecv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t\tChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ValueOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t\t\treflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" or\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("开始测试:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// output: 7")]),t._v("\n start "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Now")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Ordo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("sig")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("sig")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("sig")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Since")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("start"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("sig")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Duration"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("测试证明这两种方法均可实现 or-do 信号通知模式,不过就我看来,反射的这种方法,完全无脑,也不用考虑递归,也不必去考虑递归导致的内存溢出,从实现逻辑上,非常的清晰,只需要组成一个 select 随便 case 即可,非常清晰,我首推这种实现方法")]),t._v(" "),n("h2",{attrs:{id:"锁"}},[t._v("锁")]),t._v(" "),n("p",[t._v("我们不仅可以使用 sync.Mutext 去实现互斥锁,也可以使用 channel 去做锁,锁本质上来说,其实就是一种信号量,标准的 pv 操作,p 减少数据,获取到锁,v 增加数据释放掉锁,锁是一种二进制信号量")]),t._v(" "),n("p",[t._v("刚好,channel 的收发就符合信号量的指征")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" lock "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("tryLock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("tryLockeTimeout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("timeout time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Duration"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("timeout"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n\t\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewLock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n l"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" l\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("在初始阶段,给予一个拥有一个缓存的 channel 一个数据,获取锁就是将这个数据取出来,释放锁就是将这个数据放回 channel,这样就实现了信号量以及互斥锁")]),t._v(" "),n("p",[t._v("那么让我们试一下我们自己实现的互斥锁:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tl "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewLock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tvalue "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("120")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tl"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tvalue"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\t\tl"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 120")]),t._v("\n")])])]),n("h2",{attrs:{id:"任务编排"}},[t._v("任务编排")]),t._v(" "),n("h3",{attrs:{id:"fan-in"}},[t._v("fan-in")]),t._v(" "),n("p",[t._v("核心思想就是 “多个进,单个出”,这是数字电路的一个概念,场景是,多个 channel 发送数据给一个处理函数,此函数返回一个 channel 去承载众多信息,我们只需要监听最后输出的 channel 就可以达到监听众多信息的目的。")]),t._v(" "),n("p",[t._v("基本样貌如下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("从这个基本构型也能看出来,我们要在函数中处理多个 channel,这跟上文 channel 传递信号的 or-do 模式类似,所以免不了我们要使用反射或者递归的方式去处理函数,首先我们使用递归的方式去实现这个功能")]),t._v(" "),n("p",[t._v("递归版 "),n("code",[t._v("fan-in")]),t._v(":")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" c\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("merge")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tm "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("merge")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("merge")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ch2 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" ch1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" ch2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" v1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tch1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("continue")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v1\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" v2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tch2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("continue")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v2\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" c\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("反射版 "),n("code",[t._v("fan-int")]),t._v(":")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanintflect")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tout "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" cases "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vl "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" chs "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tcases "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectCase"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tDir"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SelectRecv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t\tChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ValueOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("vl"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\ti"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 从 cases 取数据,一旦取完,cases 会取消已经取完的 case")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tcases "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cases"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("continue")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// out 发送数据")]),t._v("\n\t\t\tout "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("反射版本这里有个小问题,从 cases 中取出数据,往 out 中添加,这个操作只能一个 case 一个 case 的取,但是你如果观察上文的递归实现模式,你会发现它开启了很多 goroutine 所以是并发的去取数据往 out 中送。")]),t._v(" "),n("h3",{attrs:{id:"fan-out"}},[t._v("fan-out")]),t._v(" "),n("p",[t._v("fan out 跟 fan in 模式是相反的,fan out 指的是拥有一个输入源,多个输出源,实际上这是一种广播机制,读取一个数据,广播给众多接受者。")]),t._v(" "),n("p",[t._v("下面看一下代码:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" value "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if go version is lower then 1.22")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("实际上这段代码有 goroutine 泄露的风险,如果 out 一直不被消费,value 的数据越来越多,那么这么多等待发送信息的 goroutine 就会发生泄露问题")]),t._v(" "),n("p",[t._v("解决方案有下面几种:")]),t._v(" "),n("ul",[n("li",[t._v("使用信号量去控制最多的 goroutine 数量")]),t._v(" "),n("li",[t._v("给每一个 goroutine 设置超时时间")]),t._v(" "),n("li",[t._v("控制发送的 value channel 的发送频率")]),t._v(" "),n("li",[t._v("使用 worker pool 去限制并发数量")])]),t._v(" "),n("p",[t._v("那么让我们用代码去实现这些改进的方案:")]),t._v(" "),n("p",[t._v("方案一:使用信号量控制")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n maxWorkers "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("GOMAXPROCS")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsema "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewWeighted")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("int64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maxWorkers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在 value传递结束之后,记得close value")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" value "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if go version is lower then 1.22")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ctx "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Acquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Release")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("方案二:使用超时时间")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" value "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// if go version is lower then 1.22")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\t\t\t\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("方案三:控制发送 value 的发送频率")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"关闭了吗"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" value "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"发送了吗"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("方案四:使用 worker 池复用 goroutine 去控制并发的 goroutine 数量")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// github.com/shgopher/grpool")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fanout")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tpool "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" grpool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewPool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("50")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" pool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Release")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" value "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" async "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tpool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("JobQueue "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\tvi "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("按照我的工作经验,使用工作池和信号量控制 goroutine 数量的方法最为常用,他们都是保证最多同时存在 n 个 goroutine,这样就避免了 goroutine 泄漏问题")]),t._v(" "),n("h3",{attrs:{id:"map-reduce"}},[t._v("map-reduce")]),t._v(" "),n("p",[t._v("我们在函数那个"),n("a",{attrs:{href:"https://github.com/shgopher/GOFamily/blob/aca91397692f99cd744fabcaca2055da3ec92c6f/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.md?plain=1#L11",target:"_blank",rel:"noopener noreferrer"}},[t._v("章节"),n("OutboundLink")],1),t._v("介绍过 map-reduce 模式,不过并没有牵涉到并发,这里我们介绍一下并发版的 map-reduce 模式\nmap")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("mapChan")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n out "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" in "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" in "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n out "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fn")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("reduce")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("reduceChan")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" in "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n out "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" in\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" in "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n out "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fn")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"pipeline-流水线模式"}},[t._v("pipeline-流水线模式")]),t._v(" "),n("p",[t._v("pipeline 模式的核心思想就是顺序,单线模式,数据从头到尾,顺序执行,一个阶段的输出是下一阶段的输入。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a A\na"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("then")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Download")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("这就是 pipeline 的一个简单掩饰,它的底层可能是这样实现的")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("then")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Download")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("那么在并发的场景里,如何使 goroutine 实现 pipeline 模式呢?")]),t._v(" "),n("p",[t._v("这显然跟一般的流水线实现方法不同。")]),t._v(" "),n("p",[t._v("我们将 channel 比作一个 token,所谓令牌,只要我们控制获取令牌的顺序,那么就可以控制持有这些令牌的 goroutine 顺序。")]),t._v(" "),n("p",[t._v("下面我们使用 4 个 goroutine 依次打印 “a b c d”,300 次,我们使用流水线的方式实现:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Token "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tGNumber "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tNumber "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tsign "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("world")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" id "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"b"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"c"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"d"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("worker")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" in "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" number "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" number "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttoken "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("in\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fn")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这段代码是为了保证最后一个 goroutine 执行完毕退出 ")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" id "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GNumber"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" number "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sign"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t\tout "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" token\n\t\tnumber"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunPipeline")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GNumber "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("Number "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" GNumber "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 核心代码: ")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 传入的in chan 和 out chan 刚好前后顺序")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这样 token 才能前后传递")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("worker")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v("GNumber"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Number"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tchs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("sign\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n GNumber "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n\tNumber "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),t._v("\n chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunPipeline")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GNumber"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("Number"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("world"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"stream-流模式"}},[t._v("stream-流模式")]),t._v(" "),n("h3",{attrs:{id:"pipeline-流水线模式和-stream-流模式的对比"}},[t._v("pipeline 流水线模式和 stream 流模式的对比")]),t._v(" "),n("p",[t._v("流水线模式 (Pipeline Pattern) 和流模式 (Stream Pattern) 都是将任务分解成多个阶段来处理,但两者还是有一些区别:")]),t._v(" "),n("ul",[n("li",[t._v("数据流动方向不同\n"),n("ul",[n("li",[t._v("流水线模式是一条主线,数据从头流到尾,每个阶段处理完输出给下一个阶段。")]),t._v(" "),n("li",[t._v("流模式是多条分支,数据可以从多个来源流入,经过处理流向多个去处。")])])]),t._v(" "),n("li",[t._v("执行方式不同\n"),n("ul",[n("li",[t._v("流水线模式强调阶段间"),n("strong",[t._v("串行执行")]),t._v("。"),n("strong",[t._v("一个阶段的输出是下一阶段的输入")]),t._v("。")]),t._v(" "),n("li",[t._v("流模式可以"),n("strong",[t._v("并行执行")]),t._v(","),n("strong",[t._v("不同阶段可以同时操作不同数据")]),t._v("。")])])]),t._v(" "),n("li",[t._v("连接方式不同\n"),n("ul",[n("li",[t._v("流水线模式中,每个阶段靠固定管道连接,顺序不能改变。")]),t._v(" "),n("li",[t._v("流模式中,流可以更灵活自由地连接。")])])]),t._v(" "),n("li",[t._v("扩展性不同\n"),n("ul",[n("li",[t._v("流水线模式扩展一个阶段可能影响整个流水线。")]),t._v(" "),n("li",[t._v("流模式扩展一个阶段对其他阶段影响很小。")])])])]),t._v(" "),n("p",[t._v("总结:")]),t._v(" "),n("ul",[n("li",[t._v("流水线模式注重将任务划分多个线性执行的固定阶段。")]),t._v(" "),n("li",[t._v("流模式注重构建灵活的流处理流程,流可以并行运动。")])]),t._v(" "),n("p",[t._v("所以两者侧重点不同,在使用上也有区别。")]),t._v(" "),n("h2",{attrs:{id:"channel-注意事项"}},[t._v("channel 注意事项")]),t._v(" "),n("p",[t._v("发生下面事项一定会触发 panic:")]),t._v(" "),n("ul",[n("li",[t._v("向已经关闭的 channel 中发送数据")]),t._v(" "),n("li",[t._v("关闭一个 nil channel")]),t._v(" "),n("li",[t._v("关闭一个已经被关闭的 channel")])]),t._v(" "),n("h3",{attrs:{id:"goroutine-泄露"}},[t._v("goroutine 泄露")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ch 被关闭了"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("当 time.After(time.Second) 执行完毕以后,上面那个 goroutine 因为无法接收数据,所以就会一直阻塞在发送数据那个地方,所以这个代码中,goroutine 就会泄露了。")]),t._v(" "),n("p",[t._v("解决之道就是将容量设置为 1 即可:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ch 被关闭了"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("当设置为 1 的时候,即使没有接受者了,发送这个地方的代码也能执行完毕,所以这个 goroutine 是不会泄露了。")]),t._v(" "),n("p",[t._v("这里插一句,main goroutine 只要退出,其它 goroutine 不管有没有执行完毕也会退出,所以如果这种代码在 main 函数中出现,那么是不会发生 goroutine 泄露问题的,因为 main 函数结束以后,其它 goroutine 自动结束")]),t._v(" "),n("h2",{attrs:{id:"channel-的实现原理"}},[t._v("channel 的实现原理")]),t._v(" "),n("h3",{attrs:{id:"创建"}},[t._v("创建")]),t._v(" "),n("h3",{attrs:{id:"send"}},[t._v("send")]),t._v(" "),n("h3",{attrs:{id:"recive"}},[t._v("recive")]),t._v(" "),n("h3",{attrs:{id:"close"}},[t._v("close")]),t._v(" "),n("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),n("h3",{attrs:{id:"channel-是并发银弹吗"}},[t._v("channel 是并发银弹吗?")]),t._v(" "),n("p",[t._v("在 go 语言中,绝大多数情况下都是是使用 channel 更有优势,比如上文提到的那几种场景,例如数据的传递以及任务编排,需要跟 select 或者 context 结合,那么这都是 channel 的适用场景")]),t._v(" "),n("p",[t._v("不过如果是对于共享资源的并发访问,使用传统的互斥锁更有优势一些")]),t._v(" "),n("p",[t._v("如果只是线程安全的对于某个变量的数据变更,使用原子包显然是更加合适的选择")]),t._v(" "),n("h3",{attrs:{id:"有无-buffer-的-channel-区别"}},[t._v("有无 buffer 的 channel 区别")]),t._v(" "),n("p",[t._v("go 语言中经常会出现一个 bug,就是死锁,很多都很没有设置 channel 缓存有关,有的时候给 channel 设置一个缓存往往可以规避很多的 panic 风险")]),t._v(" "),n("h3",{attrs:{id:"channel-close-后-read-write-close-的区别"}},[t._v("channel close 后,read write close 的区别")]),t._v(" "),n("ul",[n("li",[t._v("read:正常值+零值")]),t._v(" "),n("li",[t._v("close:panic")]),t._v(" "),n("li",[t._v("write:panic")])]),t._v(" "),n("h3",{attrs:{id:"channle-底层是什么"}},[t._v("channle 底层是什么")]),t._v(" "),n("p",[t._v("一个内部有锁的循环队列")]),t._v(" "),n("h3",{attrs:{id:"channle-和运行时调度如何交互"}},[t._v("channle 和运行时调度如何交互")]),t._v(" "),n("h3",{attrs:{id:"编程题-使用三个-goroutine-打印-abc-100-次"}},[t._v("编程题,使用三个 goroutine 打印 abc 100 次")]),t._v(" "),n("p",[t._v("上文提到的 channel 任务编排中的 pipeline 流水线模式完美解决这个问题。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Token "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tGNumber "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tNumber "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tsign "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("world")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" id "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"b"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"c"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("worker")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" in "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" number "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" number "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttoken "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("in\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("fn")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("id"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" id "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GNumber"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" number "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sign"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tout "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" token\n\t\tnumber"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunPipeline")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GNumber "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("Number "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" GNumber "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("worker")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v("GNumber"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Number"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("fn"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tchs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("sign\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n GNumber "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n\tNumber "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v("\n chs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Token"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RunPipeline")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("GNumber"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("Number"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("chs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("world"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("包括之前的水生成工厂那道题,也可以使用 pieline 模式来解决,替换掉之前使用的 waitgroup 和信号量,以及循环栅栏")]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee")]),t._v(" "),n("li",[t._v("https://github.com/fortytw2/leaktest")]),t._v(" "),n("li",[t._v("https://cloud.tencent.com/developer/article/1921580")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/106.26567b10.js b/assets/js/106.26567b10.js new file mode 100644 index 000000000..174c53612 --- /dev/null +++ b/assets/js/106.26567b10.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[106],{537:function(t,n,s){"use strict";s.r(n);var a=s(36),e=Object(a.a)({},(function(){var t=this,n=t.$createElement,s=t._self._c||n;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"context"}},[t._v("context")]),t._v(" "),s("p",[t._v("context 应该被翻译为上下文,但是 go 语言中的 context 更多的作用是"),s("strong",[t._v("取消子 goroutine")]),t._v(",传递信息这个上下文本来的含义,在 go 的 context 反而不是重点")]),t._v(" "),s("p",[t._v("context 本身是一个接口类型,它拥有四个方法:")]),t._v(" "),s("ul",[s("li",[t._v("Deadline()(deadline time.Time,ok bool):返回一个代表此上下文完成工作的时间,如果没有截止时间,返回 false")]),t._v(" "),s("li",[t._v("Done() <-chan struct {}:代表了完结")]),t._v(" "),s("li",[t._v("Err() error:如果 context 已经 done 了返回一个 error 错误,错误值分别为:Canceled,DeadlineExceeded,如果没有 done,error 返回 nil")]),t._v(" "),s("li",[t._v("Value(key any) any:context 中存储的键值对")])]),t._v(" "),s("p",[t._v("context 作为上下文,需要一个最顶层的 context 接口类型,你可以使用 "),s("code",[t._v("context.Background()")]),t._v(" 或者 "),s("code",[t._v("context.TODO()")]),t._v(" 去充当这个顶端,这两者是一个意思,用哪个都可以,这是 go 提供的已经实现了 context 接口类型的对象,它的底层是一个结构体")]),t._v(" "),s("p",[t._v("context 有一些编程范式:")]),t._v(" "),s("ul",[s("li",[t._v("将 cotext 设置为参数的第一个,例如 "),s("code",[t._v("func age(ctx context.Context,a string)")])]),t._v(" "),s("li",[t._v("不要使用 nil 作为上下文参数,如果想要空的顶端上下文,使用 "),s("code",[t._v("context.Background")]),t._v(",虽然 background 底层实现接口的时候,也是内容为空,但是它的确是实现了接口")]),t._v(" "),s("li",[t._v("context 只能作为函数的临时传递对象,不能持久化它,使用数据库保存,等持久化方式都是不可取的")]),t._v(" "),s("li",[t._v("使用 withValue 方法的时候,key 值不要使用 string,如果起冲突,使用自建的类型,例如 "),s("code",[t._v("type A struct{}")])]),t._v(" "),s("li",[t._v("尽量不要定义输出的 key 值")])]),t._v(" "),s("h2",{attrs:{id:"使用-context"}},[t._v("使用 context")]),t._v(" "),s("p",[t._v("标准库中提供了多个 context 接口类型实例:")]),t._v(" "),s("ul",[s("li",[t._v("WithCancel")]),t._v(" "),s("li",[t._v("WithCancelCause")]),t._v(" "),s("li",[t._v("WithDeadline")]),t._v(" "),s("li",[t._v("WithDeadlineCause")]),t._v(" "),s("li",[t._v("WithTimeout")]),t._v(" "),s("li",[t._v("WithTimeoutCause")])]),t._v(" "),s("p",[t._v("其中,带有 Cause 的函数跟不带的函数基本意思相同,但是多了一个 cause 的内容,它是指的是取消的原因")]),t._v(" "),s("h2",{attrs:{id:"withvalue"}},[t._v("withValue")]),t._v(" "),s("p",[t._v("WithValue 基于 parent Context 生成一个新的 Context,保存了一个 key-value 键值\n对。它常常用来传递上下文。")]),t._v(" "),s("p",[t._v("context 在查询 key 值的时候还支持链式查找,如果没有发现数据就往 parent context 中查询")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("ctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("TODO")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0001"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key2"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0001"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key3"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0001"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nctx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithValue")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key4"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0004"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Value")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h3",{attrs:{id:"withcancel"}},[t._v("WithCancel")]),t._v(" "),s("p",[t._v("withCancel 返回父 context 中的 ctx 实例副本,它相当于父 context 的子 context,并且在父 context 被取消时,子 context 也会被取消。")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("withCancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("cancelCtx "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" parent "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cannot create context from nil parent"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("cancelCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 向上寻找")]),t._v("\n\tc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("propagateCancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" c\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("propagateCancel 部分代码:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("cancelCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("propagateCancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" child canceler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Context "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" parent\n\n\tdone "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" done "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// parent is never canceled")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("done"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果父done了,那么子ctx一定也会出发cancel")]),t._v("\n\t\tchild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cause")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("parentCancelCtx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" ok "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// parent is a *cancelCtx, or derives from one.")]),t._v("\n\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mu"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果父发生了cancel,那么子ctx也要触发cancel")]),t._v("\n\t\t\tchild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cause"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("children "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("children "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("canceler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将子ctx添加到父ctx中")]),t._v("\n\t\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("children"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("child"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mu"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 父 done被触发,那么子ctx就会被触发cancel操作")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tchild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cause")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("child"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" canceler "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("removeFromParent "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cause "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("propagateCancel 将 c 向上传播,顺着 parent 的路径一直向上查找,直到找到 parentCancelCtx,如果不为空,就把自己加入到这个 parentCancelCtx 的 children 切片中,然后就可以在父 ctx 取消的时候,通知自己也被取消")]),t._v(" "),s("p",[t._v("当这个 cancelCtx 的 cancel 函数被调用的时候,parent 的 Done 被 close 的时候,或者父 ctx 触发了 cancel 的时候,这个子 ctx 会被触发 cancel 动作")]),t._v(" "),s("p",[t._v("cancel 是向下传递的,如果一个 WithCancel 生成的 Context 被 cancel 时,如果它的子 Context (也有可能是孙,或者更低),就会被 cancel,但是不会向上传递。parent Context 不会因为子 Context 被 cancel 而 cancel。")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cancel "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithCancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"done"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("WithCancel 返回 parent context 的一个副本,它自然就是子 context,当父 context 被 cancel 的时候,子 context 也会被 cancel")]),t._v(" "),s("h3",{attrs:{id:"withtimeout-withdeadline"}},[t._v("withTimeout withDeadline")]),t._v(" "),s("p",[t._v("这两个只是添加了到期时间,一个是超时时间,一个是截止时间,一旦超过时间后,自动 close 这个 done 这个 channel")]),t._v(" "),s("p",[t._v("综上所述,done 这个 channel 被 close 有三个原因:")]),t._v(" "),s("ul",[s("li",[t._v("截止时间到了")]),t._v(" "),s("li",[t._v("cancel 函数被调用了")]),t._v(" "),s("li",[t._v("parent context 的 done close 了,然后子 ctx 也要触发 cancel 方法")]),t._v(" "),s("li",[t._v("parent context cancel 了触发子 ctx cancel 方法")])]),t._v(" "),s("p",[t._v("关于第三条,解释一下:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建一个父context,设置deadline为3秒")]),t._v("\n\tparentCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cancel "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithTimeout")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建一个子context,deadline继承父context")]),t._v("\n\tchildCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cancel "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithCancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parentCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 注意这里需要调用cancel")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("doWork")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("childCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\ttime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("14")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("doWork")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"over"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"11"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"带有-cause-的函数"}},[t._v("带有 cause 的函数")]),t._v(" "),s("p",[t._v("我们看一个例子")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errors"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" myError "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" errors"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"myError"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cancel "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithCancelCause")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("TODO")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myError"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Err")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cause")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// returns myError")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("但我们调用 cancel 函数的时候,内部参数是一个 error 类型,调用 context.Cause(ctx) 返回的就是它的取消原因,那么这里的话就是 MyError")]),t._v(" "),s("h2",{attrs:{id:"在-withtimeout-中-cancel-函数的存在意义是什么"}},[t._v("在 WithTimeout 中 cancel() 函数的存在意义是什么?")]),t._v(" "),s("p",[t._v("cancel 函数的作用是可以手动提前取消 Context,使其 Done channel 关闭,不用等待 timeout 的时间或者 deadline 的时间")]),t._v(" "),s("p",[t._v("所以 cancel 函数相当于手动取消的意思,并不是说有了 timeout deadline 之后,cancel 函数就没有存在的意义了。")]),t._v(" "),s("p",[t._v("按照 go 的语法,即便是 timeout 触发了 <- done 操作,你仍然需要手动的去在最后调用 cancel 函数,否则就会报错")]),t._v(" "),s("p",[t._v("WithTimeout 在超时时会自动 cancel context,但是 cancel 函数还是需要调用,以释放/重置 Context 内部的 timer,如果不调用 cancel,timer 不会被释放,持续运行并重复 cancel 导致 context leak,占用更多资源。")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cancel "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithTimeout")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parentCtx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("doWork")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1秒后决定取消任务")]),t._v("\ntime"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("time"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),s("h3",{attrs:{id:"contex-contex-如何实现并发安全的"}},[t._v("contex.Contex 如何实现并发安全的?")]),t._v(" "),s("p",[t._v("Go 语言中 context 实现并发安全的主要手段是通过原子操作和 Mutex 来保证状态的原子性")]),t._v(" "),s("p",[t._v("根据底层代码可知,当不同的 goroutine 获取 ctx 的时候,每次操作都会加上互斥锁,来保证数据的非竞争性,线程的安全,例如")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("parentCancelCtx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("parent"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" ok "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// parent is a *cancelCtx, or derives from one.")]),t._v("\n\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mu"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果父发生了cancel,那么子ctx也要触发cancel")]),t._v("\n\t\t\tchild"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cancel")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cause"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" p"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("children "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("children "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("canceler"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将子ctx添加到父ctx中")]),t._v("\n\t\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("children"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("child"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mu"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/107.c757198e.js b/assets/js/107.c757198e.js new file mode 100644 index 000000000..04b07744d --- /dev/null +++ b/assets/js/107.c757198e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[107],{538:function(t,s,n){"use strict";n.r(s);var a=n(36),e=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"内存模型"}},[t._v("内存模型")]),t._v(" "),n("p",[t._v("go 官方介绍 go 内存模型的时候说:探究在什么条件下,A goroutine 在读取一个变量的值的时,能够看到其它 goroutine 对这个变量进行的写的结果。")]),t._v(" "),n("p",[t._v("我们为什么需要内存模型?")]),t._v(" "),n("p",[t._v("CPU 指令可能会被重排序,并且存在多级缓存,例如 Go 语言中的多级内存模型。不同的 CPU 架构 (比如 x86 和 ARM) 也会对指令顺序产生影响,编译器优化也可能改变指令顺序。")]),t._v(" "),n("p",[t._v("因此,编程语言需要一个内存规范,也就是内存模型,来规定程序中的内存访问和同步的语义,保证在不同的硬件和编译器下,程序的执行结果保持一致")]),t._v(" "),n("h2",{attrs:{id:"介绍一些-go-语言中的基本操作"}},[t._v("介绍一些 go 语言中的基本操作")]),t._v(" "),n("blockquote",[n("p",[t._v("除了基本的读和写之外都是同步操作,包括以下列举的,并且更多以这些基础操作衍生出的操作。")])]),t._v(" "),n("ul",[n("li",[t._v("读\n"),n("ul",[n("li",[t._v("基础的读\n"),n("ul",[n("li",[t._v("对超过机器 word 大小的值读,可以看作是拆成 word 大小的几个读的无序进行")])])]),t._v(" "),n("li",[t._v("原子包的读")]),t._v(" "),n("li",[t._v("使用 sync.Mux 的读")]),t._v(" "),n("li",[t._v("使用 channel 形式的读")])])]),t._v(" "),n("li",[t._v("写\n"),n("ul",[n("li",[t._v("基础的写\n"),n("ul",[n("li",[t._v("变量的初始化就是一个写操作")]),t._v(" "),n("li",[t._v("对超过机器 word 大小的值写,可以看作是拆成 word 大小的几个写的无序进行")])])]),t._v(" "),n("li",[t._v("原子包的写")]),t._v(" "),n("li",[t._v("sync.mux 的写")]),t._v(" "),n("li",[t._v("向 channel 发送数据")])])]),t._v(" "),n("li",[t._v("atomic 的 compare and swap 操作,兼顾了写和读")])]),t._v(" "),n("p",[t._v("我们讨论 go 内存模型的时候,主要聚焦下面四种细节的"),n("strong",[t._v("差异性")]),t._v(":")]),t._v(" "),n("ul",[n("li",[t._v("操作的种类:\n"),n("ul",[n("li",[t._v("普通的读或者写")]),t._v(" "),n("li",[n("strong",[t._v("同步操作")]),t._v(",比如利用 sync 包进行同步,利用 channel 在不同的 goroutine 中间进行同步,利用 atomic 包进行同步等。")])])]),t._v(" "),n("li",[t._v("这个操作者在程序中的位置")]),t._v(" "),n("li",[t._v("被操作者在内存位置,或者是被访问的变量的位置")]),t._v(" "),n("li",[t._v("被操作者值的类型")])]),t._v(" "),n("h2",{attrs:{id:"内存模型存存在的意义"}},[t._v("内存模型存存在的意义")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("给程序员一个最根本的法则 --- 你只要遵循这个法则,那么在进行多 goroutine 数据访问的时候,做串行控制 (使用同步操作) 一定会成功。")])]),t._v(" "),n("li",[n("p",[t._v("给编译器优化开发者一个法则,只要遵循这个法则,就能不出错的做出编译器级别的优化。")])])]),t._v(" "),n("h3",{attrs:{id:"具体表现"}},[t._v("具体表现")]),t._v(" "),n("ul",[n("li",[n("strong",[t._v("探究可见性")])]),t._v(" "),n("li",[n("strong",[t._v("happens- before")]),t._v(":x 操作一定在 y 操作之前执行完毕,这里说的并不是时间,而是 “执行完毕” 这个结论,我们可以放心的在 y 中使用 x 的执行结果。主要突出的是这个完成性。")])]),t._v(" "),n("h3",{attrs:{id:"三条定律"}},[t._v("三条定律")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("在一个 goroutine 中,程序执行的顺序一定是符合代码写的顺序的。但是不同的 goroutine 中这个定理失效。")])]),t._v(" "),n("li",[n("p",[t._v("在"),n("strong",[t._v("同步操作")]),t._v("的时候,从 a goroutine 看到 b goroutine 的执行顺序,必须符合同步操作的顺序,这里举个例子,举例:b 的同步操作是什么顺序,那么 a 读取的就是什么顺序。比如 b 中有三个 Channel,他们执行的顺序是先 a 发 b 收,b 发,c 收,那么在 a 中读取的顺序跟这个同步的操作顺序是一致的,"),n("strong",[t._v("如果不是同步操作就可能不一致。")])])]),t._v(" "),n("li",[n("p",[t._v("对于非同步操作的普通读和写,如果 b 操作了 a,那么必须成立")]),t._v(" "),n("ul",[n("li",[t._v("b 发生在 a 之前")])])])]),t._v(" "),n("p",[t._v("我们可以使用 "),n("code",[t._v("go build -race")]),t._v(" 来发现数据竞争。")]),t._v(" "),n("p",[t._v("接下来我们对于内存模型的具体表现进行更具体的介绍。")]),t._v(" "),n("h2",{attrs:{id:"重排和可见性"}},[t._v("重排和可见性")]),t._v(" "),n("p",[t._v("由于指令的重排,代码"),n("strong",[t._v("不一定")]),t._v("会按照你写的顺序执行。")]),t._v(" "),n("p",[t._v("这里给出一个案例:有两个 goroutine 分别是 g1,和 g2,g1 读某个变量的数据,g2 写这个变量的数据,当 g1 读取到 g2 写的新数据之后,你也不一定能读取到在 goroutine g2 中排列在这个写数据操作之前的操作:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\tdone "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n\t\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n\t\tdone "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("done "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 可能观察到的就是输出的 4 3,但是无法保证必须是4 3 ,能观察到 != 保证")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("下面这种情况,a goroutine 无法观察到 b goroutine 是否完成了写操作,有可能造成 a goroutine 一直被卡的现象:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Result "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tdata "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Result\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\td "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\td"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi there"')]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里无法确认一定会运行")]),t._v("\n\tr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" d "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里无法确认观察到")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("blockquote",[n("p",[t._v("there is no guarantee that the write to done will ever be observed by main,"),n("strong",[t._v("since there are no synchronization events between the two threads")]),t._v("。The loop in main is not guaranteed to finish。“")])]),t._v(" "),n("p",[t._v("这一句是 go blog 中对于这代代码的描述,重点是说,这俩线程中,没有存在同步原语,所以无法做到从 main goroutine 去观测到 r 的状态,也就是说,在 goroutine 中只要存在了同步原语,那么就可以把两个 goroutine 当作正常的语句来看。")]),t._v(" "),n("p",[t._v("这里有两点无法确认,第一:主 goroutine 无法"),n("strong",[t._v("确认")]),t._v(" r 的状态,这里指的就是"),n("strong",[t._v("可观测性")]),t._v(",因为这里是非同步操作,所以主 goroutine 的读无法观测到 "),n("code",[t._v("go set()")]),t._v(" 这里 "),n("code",[t._v("r = d")]),t._v(" 这里的写,注意是无法完全确认,通常来说这段代码是可以运行的,我说的是通常,第二无法保证 "),n("code",[t._v("d.data")]),t._v(" 一定会运行,所以有可能输出的是空字符串,这里说的就是因为编译优化导致的指令重排。")]),t._v(" "),n("h2",{attrs:{id:"同步操作的-happens-before"}},[t._v("同步操作的 happens-before")]),t._v(" "),n("p",[t._v("go 不直接提供 cpu 屏障,来保证编译器或者 cpu 保证顺序性,而是使用不同架构的内存屏障指令来实现统一的并发原语。")]),t._v(" "),n("h3",{attrs:{id:"单个-goroutine"}},[t._v("单个 goroutine")]),t._v(" "),n("p",[t._v("上文说到,"),n("strong",[t._v("在一个 goroutine 中,happens- before 其实就等于代码书写的顺序,这一点是严格成立的")]),t._v("。")]),t._v(" "),n("h3",{attrs:{id:"init-函数"}},[t._v("init 函数")]),t._v(" "),n("p",[t._v("go 语言的初始化是在单一的 goroutine 中执行的,也就是 main goroutine。")]),t._v(" "),n("p",[n("strong",[t._v("p 包导入了 q 包,那么 q 的 init 函数一定 happens before p 的任何初始化代码")]),t._v("。")]),t._v(" "),n("p",[t._v("这里有点像树,导入的过程,以及初始化的过程,会形成一个多叉树,从最底层的树开始进行初始化,逐步的忘上层走,先进后出,栈一样的感觉,并且相同的包只会导入一次,进而也只会初始化一次,比如 q 包被第三层导入了,在第五层也导入了,那么这个包在从底层往上走的过程中,只会在第五层先全局变量后 init 函数的初始化一次。这导入的包全部初始化一遍之后,才开始进行 main 包的 mian 函数,然后进而去运行接下来的逻辑。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" b\n\n b "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n d "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n d "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" d \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("初始化的顺序是这样的,首先初始化 a,因为 a = c + b,那么系统开始初始化 c 和 b,c 和 b 等于一个函数 f,那么就开始初始化这个函数,函数里面是 d 那么开始初始化 d,所以 b = 3+1 c = 3+1+1 a = 9,这个时候 d 已经++ 两次了,所以最终的初始化以后 a = 9 b = 4 c = 5 d = 5")]),t._v(" "),n("p",[t._v("包级别的变量按照代码顺序初始化,同一个包的众多文件会按照文件名的排列顺序进行初始化。")]),t._v(" "),n("h3",{attrs:{id:"goroutine"}},[t._v("goroutine")]),t._v(" "),n("p",[t._v("启动 goroutine 的 go 语言执行,一定 happens - before 此 goroutine 内的代码执行。退出可就没有任何 happens- before 的理论了,所以退出我们通常要部署同步语句。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("从单个 goroutine 的 happens- before 的关系来看,a = “hi” 一定 happens- before go f (),从新 goroutine 的开辟来说,go f () 一定 happens- before fmt.Println 所以这个代码中,hi 一定能被输出。")]),t._v(" "),n("h3",{attrs:{id:"channel"}},[t._v("channel")]),t._v(" "),n("p",[t._v("go 语言有一句经典名言,不要使用共享内存来通信 (sync.Mutex) 而应该采用通信的方式来共享内存,这个后者说的就是 channel,channel 是同步操作的首选。")]),t._v(" "),n("ul",[n("li",[t._v("往 channel 中发数据,happens - before 从这个 channel 接收数据"),n("strong",[t._v("完成")]),t._v("。注意这里说的是接收完成,"),n("strong",[t._v("没说")]),t._v("发数据 happens- before 这个 channel 接受数据开始的时候。")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//这里之所以a = hi 发生在 c <-0 之前,就是因为这个goroutine和main goroutine 存在同步原语,")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//只要存在,那么代码就会按照程序员写的顺序执行,并不会进行重排。")]),t._v("\n a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),t._v(" \n c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里因为有了同步操作,所以 a = “hi” 在main goroutine看 也是 a= “hi” happens- before c <- 0")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("c "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里只要收到数据了,那么 c <- 0 肯定已经运行了,并且发送完毕了。")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("ul",[n("li",[n("p",[t._v("close 一个 channel 一定 happens- before 从关闭的 channel 中读取一个零值。我们都知道可以从一个 closed 的一个 channel 中读取零值是可以的,这里说明的是读零值这个过程一定在关闭这个操作之后。")])]),t._v(" "),n("li",[n("p",[t._v("一个 unbuffered 的 channle,读的准备好一定 happens-before 发准备好,意思是说,只有收数据准备好了,才能发,否则就会一直卡在发那个地方。")])]),t._v(" "),n("li",[n("p",[t._v("一个容量大于 0 为 m 的 channel,第 n 个接收,一定 happens- before 第 n+m 的发送,意思是说,如果容量满了,必须先拿出来一个才能往里面再塞进去一个。比如:n=1 m=2,第一个接收一定 happens- before 第三个发送,因为容量一共是 2,要想往里面塞进去第三个,"),n("strong",[t._v("必须拿出来一个并且拿出来这个操作完毕了")]),t._v(",才能发送第三个。")])])]),t._v(" "),n("h3",{attrs:{id:"mutex-rwmutex"}},[t._v("Mutex/RWMutex")]),t._v(" "),n("ul",[n("li",[t._v("第 n 次的 unlock 一定 happends- before 第 n+1 次 lock 方法的返回\n意思是说,只有先解锁才能再次加锁。")]),t._v(" "),n("li",[t._v("读写锁虽然有两把锁,但是不能同时使用,必须等待一个锁解锁后,另一个锁才能上锁,比如读锁解锁后才能再次上读锁,或者才能上写锁。")])]),t._v(" "),n("p",[t._v("互斥锁可以由 a goroutine 上锁,b goroutine 解锁")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),t._v("\n mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里拥有了一个同步原语,所以 s = hi 一定发生在 mu.unlock() 之前。(相当于在一段锁的内部)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的lock 一定发生在 另一个goroutine 中f 的 mu.Unlock() 之后。")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"waitgroup"}},[t._v("WaitGroup")]),t._v(" "),n("ul",[n("li",[t._v("wait 方法等到计数值归零才能返回 (运行完毕)")])]),t._v(" "),n("h3",{attrs:{id:"once"}},[t._v("Once")]),t._v(" "),n("ul",[n("li",[t._v("对于 once.Do(f) f 一定会在 do 方法返回之前执行。")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" once sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Once\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n once"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Do")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里 f 的执行完毕 一定在 Do()返回之前,所以一定能输出 s = hi")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"atomic"}},[t._v("atomic")]),t._v(" "),n("p",[t._v("按照 atomic load / store 顺序来保证 happens - before 不过 go 官方并没有严格定义,直到目前为止并没有严格定义。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("StoreInt32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("StoreInt32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LoadInt32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Gosched")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LoadInt32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),n("p",[n("code",[t._v("使用channel实现一个互斥锁")])]),t._v(" "),n("p",[t._v("我们利用 channel 发送数据 happens- before 收到数据完毕这个特性来实现互斥锁。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Locker "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始状态是已经有一个")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewLocker")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Locker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Locker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// lock 从缓存是1编程0,从chan中取出来数据")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Locker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// unlock 将缓存从0变成1,向ch中放入数据。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Locker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tl"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("一个小小的经验:channel 拥有 buffer 比没有 buffer 常用很多。")]),t._v(" "),n("p",[t._v("完结。")]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://go.dev/ref/mem")]),t._v(" "),n("li",[t._v("https://time.geekbang.org/column/article/307469")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/108.90ae536a.js b/assets/js/108.90ae536a.js new file mode 100644 index 000000000..83a105755 --- /dev/null +++ b/assets/js/108.90ae536a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[108],{542:function(t,s,n){"use strict";n.r(s);var a=n(36),p=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"go-并发模型"}},[t._v("go 并发模型")]),t._v(" "),n("h2",{attrs:{id:"并发和并行的关系"}},[t._v("并发和并行的关系")]),t._v(" "),n("p",[t._v("并发是问题域的一种概念,它强调处理多个同时 (或者近似同时) 发生的事件。")]),t._v(" "),n("p",[t._v("并行是方法域的一种概念,将问题分解为多个部分,同时并行执行来加速解决问题。")]),t._v(" "),n("blockquote",[n("p",[t._v("rob pike:并发不是并行,并发关乎结构,并行关乎执行")])]),t._v(" "),n("p",[t._v("并发:一位老师,在听一个学生朗读的时候,她可以暂停学生的朗读,然后回答学生的问题,再次开始学生的朗读,虽然她一次只能干一件事,但是这也能看作处理多个近乎同时发生的事件")]),t._v(" "),n("p",[t._v("并发和并行:两位老师,一个老师提问,一个老师解决学生的问题,这就是满足了并行和并发")]),t._v(" "),n("p",[t._v("并行但不是并发:让全班同学制作贺卡,全班同学每个学生制作五枚,全班同学同时开始做,只能是并行,但不是并发,因为只有一个事件。")]),t._v(" "),n("h2",{attrs:{id:"多线程并发模型"}},[t._v("多线程并发模型")]),t._v(" "),n("p",[t._v("使用共享内存的方式去完成并发就是多线程并发模型,它的核心就是使用锁的方法,让某个线程单独拥有某块内存,其他线程只能访问该内存,从而实现了并发。")]),t._v(" "),n("p",[t._v("go 语言中的锁就是 sync.Mutex,这也是 go 语言实现多线程并发的核心,一共有:")]),t._v(" "),n("ul",[n("li",[t._v("sync.Mutex 互斥锁,可以同时对一个资源进行读写操作,但是只能有一个线程可以对该资源进行写操作。")]),t._v(" "),n("li",[t._v("sync.RWMutex 读写锁,可以同时对一个资源进行读操作,但是只能有一个写操作")]),t._v(" "),n("li",[t._v("sync.Cond 条件变量,可以让一个线程等待另一个线程满足某个条件")]),t._v(" "),n("li",[t._v("sync.Once 单例模式,保证某个资源只被初始化一次")]),t._v(" "),n("li",[t._v("sync.Pool 资源池,可以让一个资源在内存中被复用,避免了重复创建资源的开销")]),t._v(" "),n("li",[t._v("sync.Map 线程安全的 map,可以让多个线程安全的对 map 进行读写操作")]),t._v(" "),n("li",[t._v("sync.Pool 资源池,可以让一个资源在内存中被复用,避免了重复创建资源的开销")]),t._v(" "),n("li",[t._v("sync.WaitGroup 等待组,可以让多个线程等待,直到某个线程完成某个任务")]),t._v(" "),n("li",[t._v("golang.org/x/sync/errgroup 为处理公共任务的子任务的 goroutine 组提供同步、错误传播和上下文取消")]),t._v(" "),n("li",[t._v("golang.org/x/sync/semaphore 提供了一个加权信号量实现。")]),t._v(" "),n("li",[t._v("golang.org/x/sync/singleflight 提供了重复函数调用抑制机制,中文叫栅栏机制")]),t._v(" "),n("li",[t._v("golang.org/x/sync/syncmap 提供了一个并发映射实现")])]),t._v(" "),n("h2",{attrs:{id:"csp"}},[t._v("csp")]),t._v(" "),n("p",[t._v("go 语言推荐的并发模型使用的就是 csp 模型,csp 的核心思想就是讲各个任务等同于进程,进程顺序执行互不牵连,进程可以收发信息,使用通道的方式进行信息的通信。")]),t._v(" "),n("p",[t._v("所以如果使用 channel 的方式进行通信就是使用的 csp 并发模型")]),t._v(" "),n("p",[t._v("CSP 模型中的进程通信原语包括:")]),t._v(" "),n("ul",[n("li",[t._v("发送消息:一个进程可以通过发送消息到另一个进程来与之进行通信。")]),t._v(" "),n("li",[t._v("接收消息:一个进程可以通过接收消息来获取另一个进程发送的消息。")]),t._v(" "),n("li",[t._v("原子发送-接收:一个进程可以通过原子发送-接收操作来发送消息并等待接收消息,这相当于发送和接收两个操作的组合。")])]),t._v(" "),n("p",[t._v("这些进程通信的都是通过内置的 channel 对象去实现的。")]),t._v(" "),n("h2",{attrs:{id:"了解-goroutine"}},[t._v("了解 goroutine")]),t._v(" "),n("p",[t._v("这里我们现简单的了解一些基本的使用 goroutne 的方法,后面的 channel 篇和并发原语 context atomic 定时器会进行更加详细的介绍。")]),t._v(" "),n("p",[t._v("我们知道 go 使用了用户线程也就是 goroutine 去替代了传统的线程,所以在 go 语言中我们能操作的线程就是 goroutine,我们无法去触及真实的线程,线程和 goroutine 之间的关系是 go 语言运行时的调度器去调度的。")]),t._v(" "),n("h3",{attrs:{id:"创建-goroutine"}},[t._v("创建 goroutine")]),t._v(" "),n("p",[t._v("使用 go 关键字加上函数去创建一个 goroutine,当然后面跟方法也可以。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 注意后面跟的是一个函数的运行,这跟 defer 一致")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\td "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("c\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们可以看到,这里使用了 csp 的并发模型,下面我们看一下使用传统的共享内存的并发模式")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 注意后面跟的是一个函数的运行,这跟 defer 一致")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("200")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"goroutine-退出"}},[t._v("goroutine 退出")]),t._v(" "),n("p",[t._v("goroutine 使用代价很低,因为它并不是操作系统的线程,创建成本非常低,go 推荐可以多多使用 goroutine")]),t._v(" "),n("p",[t._v("goroutine 退出有两种方式:")]),t._v(" "),n("ul",[n("li",[t._v("主动退出:使用 return 或者 panic 关键字退出")]),t._v(" "),n("li",[t._v("非主动退出:使用 sync.WaitGroup,context 等方法,当所有的 goroutine 都退出后,等待组会自动退出")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wg sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n\twg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("go goroutine 执行完毕就会直接退出,程序的执行跟主 goroutine 有关,只要主 goroutine 不退出程序就会正常执行下去,反之,主 goroutine 如果退出了,其它的 goroutine 可能没有执行完毕,但是整个程序还是结束了。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi there"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这个程序将无法保证能输出 hi there")]),t._v(" "),n("p",[t._v("要想让 age 输出正常的值,必须保证主 goroutine 不能退出,比如使用 sync.WaitGroup,比如直接让主 goroutine 休眠")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("20000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi there"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("下面让我们正式学习 go 并发语言,channel 等相关知识!")]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://mp.weixin.qq.com/s/TvHY2i1FX1zS_WHdCvK-wA")]),t._v(" "),n("li",[t._v("https://book.douban.com/subject/26337939/")]),t._v(" "),n("li",[t._v("https://book.douban.com/subject/35720728/ 315 页 - 317 页")]),t._v(" "),n("li",[t._v("极客时间《go 进阶训练营》")])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/109.55b5f850.js b/assets/js/109.55b5f850.js new file mode 100644 index 000000000..8334cb16a --- /dev/null +++ b/assets/js/109.55b5f850.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[109],{540:function(t,n,v){"use strict";v.r(n);var _=v(36),s=Object(_.a)({},(function(){var t=this,n=t.$createElement,v=t._self._c||n;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"go-编译器"}},[t._v("go 编译器")]),t._v(" "),v("h2",{attrs:{id:"编译器概述"}},[t._v("编译器概述")]),t._v(" "),v("p",[t._v("默认编译器 gc 介绍\n编译原理和过程\n编译器组件工具链\n编译优化技术")]),t._v(" "),v("h2",{attrs:{id:"编译器特性"}},[t._v("编译器特性")]),t._v(" "),v("p",[t._v("编译速度快\n生成自包含可执行文件\n内存安全保证\n跨平台支持\n模块化支持")]),t._v(" "),v("h2",{attrs:{id:"编译器实战"}},[t._v("编译器实战")]),t._v(" "),v("p",[t._v("常见编译错误和解决方法\n编译参数和定制\n增量编译\nhook 编译过程\n交叉编译")]),t._v(" "),v("h2",{attrs:{id:"编译器源码"}},[t._v("编译器源码")]),t._v(" "),v("p",[t._v("gc 编译器源码解析\n编译器前端实现\n编译器后端实现")]),t._v(" "),v("h2",{attrs:{id:"其他编译器"}},[t._v("其他编译器")]),t._v(" "),v("p",[t._v("gccgo\ngollvm\n编译器比较")])])}),[],!1,null,null,null);n.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/11.25dd6abf.js b/assets/js/11.25dd6abf.js new file mode 100644 index 000000000..e71616b20 --- /dev/null +++ b/assets/js/11.25dd6abf.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{431:function(t,s,a){t.exports=a.p+"assets/img/ringwaiter.c4e44723.png"},539:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"同步原语"}},[t._v("同步原语")]),t._v(" "),n("p",[t._v("传统同步原语是 go 提供的相对底层的同步机制,它更加灵活,但是同时也更加复杂,如果可能的话,我们应该尽量使用 csp 的并发模型,使用 channel 去代替传统同步原语。")]),t._v(" "),n("p",[t._v("本单元讲的传统同步原语,channel 和 contex 也属于同步原语,他们属于 csp 的并发模型,所以他们会单独为列。")]),t._v(" "),n("p",[t._v("下面讲一下这么多同步原语 (也叫并发原语) 的基本功能:")]),t._v(" "),n("ul",[n("li",[n("code",[t._v("sync.Mutex, sync.RWMutex")]),t._v(" 共享资源,避免数据竞争 (data race)")]),t._v(" "),n("li",[n("code",[t._v("sync.Waitgroup, channel")]),t._v(" 任务编排,各个 goroutine 所代表的任务的前后顺序关系")]),t._v(" "),n("li",[n("code",[t._v("channel")]),t._v(" 传递消息")])]),t._v(" "),n("p",[t._v("这是基本的划分,当然这个划分还不严谨,但是你只需要知道,这些属于最常见的同步原语,以及他们最常见的功能。")]),t._v(" "),n("h2",{attrs:{id:"sync-mutex"}},[t._v("sync.Mutex")]),t._v(" "),n("p",[t._v("下面介绍的众多并发原语,甚至下一章的 channel,都使用了这个核心内容,它就是 "),n("code",[t._v("sync.Mutex")]),t._v(",它是所有同步原语包含 channel 的底层核心。")]),t._v(" "),n("p",[t._v("Mutex 也就是互斥锁,它主要是为了解决多线程下数据的竞争问题,所以互斥锁是同步原语的最底层最核心的组件")]),t._v(" "),n("p",[t._v("让我们看几个场景")]),t._v(" "),n("ol",[n("li",[n("p",[t._v("计数器,多个线程去更新一个计数器的时候,如果不加锁,就会出现数据的错误,本来你只加上了 1,正当你读的时候你发现别的线程也加上了 1,所以导致读取的错误")])]),t._v(" "),n("li",[n("p",[t._v("秒杀服务,这也是一个常见的场景,如果不加锁,就会导致超卖的情况出现")])]),t._v(" "),n("li",[n("p",[t._v("往一个 buffer 中传入数据,如果不加锁,数据的顺序就会发生乱序")])])]),t._v(" "),n("h3",{attrs:{id:"临界区"}},[t._v("临界区")]),t._v(" "),n("p",[t._v("临界区的概念是指在多线程的时候,临界区域的内容会被不同的线程去获取和释放,这个区域会发生数据的争夺问题。")]),t._v(" "),n("p",[t._v("这个区域因为会发生争夺,所以会被保护起来,可以这么说,临界区是"),n("strong",[t._v("多线程中整体数据中的共享部分")])]),t._v(" "),n("p",[t._v("所以临界区是要保护的区域,"),n("strong",[t._v("一次只能让一个线程去使用")])]),t._v(" "),n("p",[t._v("所以 sync.Mutex 就是用来保护临界区的,它可以保证临界区的互斥")]),t._v(" "),n("p",[t._v("共享资源通常是某个变量,例如临界区是变量 count,临界区操作是 count++,只要在临界区前面获取\n锁,在离开临界区的时候释放锁,就能解决 data race 的问题。")]),t._v(" "),n("h3",{attrs:{id:"sync-mutex-基础操作"}},[t._v("sync.Mutex 基础操作")]),t._v(" "),n("p",[t._v("我们现看一下它的基础使用功能:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 跨goroutine 加解锁")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi there"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("sync.Mutex 即为互斥锁,规则是:")]),t._v(" "),n("ul",[n("li",[t._v("锁的加锁和解锁可以跨 goroutine 使用,比如 a goroutine 加锁,在 b goroutine 将锁解开。")]),t._v(" "),n("li",[t._v("只有现解锁才能继续上锁,happens-before 就是:"),n("em",[n("strong",[t._v("n 次解锁一定 happens-before n+1 次加锁")])])])]),t._v(" "),n("h3",{attrs:{id:"sync-locker-接口"}},[t._v("sync.Locker 接口")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Locker "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("Mutex 就实现了这个 Locker 接口")]),t._v(" "),n("p",[t._v("Locker 定义了锁的基本方法,加锁 + 解锁")]),t._v(" "),n("h3",{attrs:{id:"什么是-data-race-的本质"}},[t._v("什么是 data race 的本质")]),t._v(" "),n("p",[t._v("我们常说 data race 的情况,是多线程同时对于某块内存进行数据的变更,那么问题来了,这个地方谈到的同时,是真的物理层面的同时还是近似同时?")]),t._v(" "),n("p",[t._v("关于 data race 中的 “同时” 通常是"),n("strong",[t._v("指逻辑上的同时或近似同时,而不是物理层面严格的同一时刻。")])]),t._v(" "),n("p",[t._v("主要原因有以下几点:")]),t._v(" "),n("ul",[n("li",[t._v("现代 CPU 中,同一时刻真正执行指令的只有一个核心。不同核心之间以及同一核心的不同执行周期之间,不存在物理层面严格的同步。")]),t._v(" "),n("li",[t._v("即使在单核 CPU 上,由于指令流水线、内存缓存、分支预测等机制,实际执行顺序也可能与代码顺序不一致,很难定义物理层面严格的同步。")]),t._v(" "),n("li",[t._v("不同线程之间进行切换的时间间隔非常小 (几十到几百纳秒),对程序逻辑而言可以视为同时进行。")]),t._v(" "),n("li",[t._v("要构成 data race,不同线程对同一地址的访问之间间隔不能太长,必须在一个指令/操作的启始和完成之间,所以也符合逻辑上的近似同时。")])]),t._v(" "),n("p",[t._v("所以,data race 中的 “同时” 就是指逻辑上近似同时,或者无法确定准确执行顺序的情况,而不是物理层面严格同一时刻。这种近似同时从程序角度就是可能造成冲突,需要进行同步处理。")]),t._v(" "),n("h3",{attrs:{id:"检测-data-race-的工具"}},[t._v("检测 data race 的工具")]),t._v(" "),n("p",[t._v("并发问题不是一定能肉眼看出来的,如果只是基础的,容易看出来的也就罢了,但是很多隐藏的 data race 问题必须使用专业的工具去鉴别,go 语言提供了 "),n("code",[t._v("-race")]),t._v(" 功能,在编译,测试,run 的时候,会自动检测到 data race 问题,并且给出详细的错误信息。")]),t._v(" "),n("div",{staticClass:"language-bash extra-class"},[n("pre",{pre:!0,attrs:{class:"language-bash"}},[n("code",[t._v(" go run -race main.go\n")])])]),n("p",[t._v("我们看一个例子")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvalue "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tvalue "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\t "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("本能的你会以为能输出 10000,但是结果确实 9000 多,而且还不一定,这是为啥呢?")]),t._v(" "),n("p",[t._v("因为你以为 ++ 操作是原子操作,其实并不是。")]),t._v(" "),n("p",[t._v("++ 操作分为三个步骤")]),t._v(" "),n("ul",[n("li",[t._v("获取 value 值")]),t._v(" "),n("li",[t._v("值+1")]),t._v(" "),n("li",[t._v("将新值写回")])]),t._v(" "),n("p",[t._v("这其实是三个步骤,10000 个线程,假如同时有 10 个去读了这个 value,在他们看来都是初始值是 0,然后他们+1,然后写回去了结果 value 是 1,相当于 10 个 goroutine 都去写,本来应该是 10,但是赋值回去都变成了 1")]),t._v(" "),n("p",[t._v("这个时候,如果你使用 run -race 就能检测出来")]),t._v(" "),n("div",{staticClass:"language-bash extra-class"},[n("pre",{pre:!0,attrs:{class:"language-bash"}},[n("code",[t._v("go1 go run -race main.go \n"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v("\nWARNING: DATA RACE\nRead at 0x00c00010a018 by goroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),t._v(":\n main.main.func1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n /Users/shgopher/Desktop/1/go1/main.go:23 +0x2c\n\nPrevious "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("write")]),t._v(" at 0x00c00010a018 by goroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),t._v(":\n main.main.func1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n /Users/shgopher/Desktop/1/go1/main.go:23 +0x3c\n\nGoroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("running"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" created at:\n main.main"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n /Users/shgopher/Desktop/1/go1/main.go:22 +0x48\n\nGoroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("finished"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" created at:\n main.main"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n /Users/shgopher/Desktop/1/go1/main.go:22 +0x48\n"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("9957")]),t._v("\nFound "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" data race"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("exit")]),t._v(" status "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("66")]),t._v("\n")])])]),n("p",[t._v("多线程多某个区域的内存进行同时 (或者近似同时) 操作,这就是数据竞争")]),t._v(" "),n("p",[t._v("使用这个内置工具有个很大的缺陷,就是只有在数据真的执行中发生了数据竞争才能被发现,并且,使用-race 会影响编译的程序执行速度")]),t._v(" "),n("p",[t._v("如果我们使用 "),n("code",[t._v("go tool compile -race -S x.go")]),t._v(" 的时候就发现使用-race 之后,编译的时候 go 编译器往代码中加入了很多运行时监控代码,"),n("strong",[t._v("这些运行时的监控代码")]),t._v("会影响性能")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\t"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x001c")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("00028")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\tPCDATA\t$"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" $"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x001c")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("00028")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\tCALL\truntime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("racefuncenter")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SB"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x0020")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("00032")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\tMOVD\t$"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SB"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" R0\n\t"),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x0028")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("00040")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\tCALL\truntime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("newobject")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("SB"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[n("code",[t._v("runtime.xx")]),t._v(" 的代码就是添加的运行时监控")]),t._v(" "),n("blockquote",[n("p",[t._v("小知识,使用 go tool compile 的时候不要加入第三方库,标准库也不行,编译工具只能编译本文件,跟 go build 那种能查找依赖树的方式不同")])]),t._v(" "),n("h3",{attrs:{id:"将互斥锁嵌入到结构体中"}},[t._v("将互斥锁嵌入到结构体中")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyAge "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n value "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("或者直接嵌入")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyAge "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n value "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" age MyAge\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" age"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tage"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("age"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"sync-mutex-互斥锁的实现原理"}},[t._v("sync.Mutex 互斥锁的实现原理")]),t._v(" "),n("p",[t._v("go 语言互斥锁的实现非常简单,只有这一个结构体就是核心:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Mutex "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n state "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v("\n sema "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("blockquote",[n("p",[t._v("在阅读下面互斥锁的几个阶段之前,建议先读一下 G:M:P 模型")])]),t._v(" "),n("h4",{attrs:{id:"互斥锁演变的四个阶段一-简单实现"}},[t._v("互斥锁演变的四个阶段一:简单实现")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 最初的代码")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Mutex "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n key "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 锁是否被持有的标志,1 被持有,0 没有被持有")]),t._v("\n sema "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 锁的具体状态,此信号量具有高级语意,用来控制goroutine的状态")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// compare and swap 操作:val 和 old 进行对比,如果相同,使用new去替代 val的值")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("cas")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" old"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("new")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// val 数据添加一个 delta 值,返回新的值")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("xadd")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" delta "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("new")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("val\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("cas")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("val"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("delta"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("delta\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"unreached"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("xadd")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("key"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 标识+1 ,如果等于1 获取到锁")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里就是说,当key >1 的时候,我们通知goroutine休眠等待锁")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只有key 等于 1 才能算获取锁")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("semacquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("xadd")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("key"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 标识-1 ,如果等于0 表示没有其它等待者")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这个函数是汇编语言写的,上面那个 semacquire 也是")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("semrelease")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 唤醒等待锁的其它的goroutine中的一个")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("可以看到,这种简单的实现,完全没有考虑任何的情况,仅仅是简单的加锁和解锁,不考虑 goroutne 的任何情况,就是随机的,随机的获取锁然后解锁。")]),t._v(" "),n("p",[t._v("注意 go 语言的锁可以 a 加 b 解,所以一定要谁加锁就谁解锁,不然就无法构成互斥锁这个概念了。")]),t._v(" "),n("h4",{attrs:{id:"互斥锁演变的四个阶段二-优先新-goroutine"}},[t._v("互斥锁演变的四个阶段二:优先新 goroutine")]),t._v(" "),n("p",[t._v("在这个演变中,go 的互斥锁调度会优先将锁权分给新创建的 goroutine")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n mutexLock "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n mutexWoken\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n mutexWaiterShift "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Mutex "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n state "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v("\n sema "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("state 的内容变成了三个:")]),t._v(" "),n("ul",[n("li",[t._v("第一个字段:mutexWaiters 阻塞等待的数量")]),t._v(" "),n("li",[t._v("第二个字段:mutexWoken 唤醒标记")]),t._v(" "),n("li",[t._v("第三个字段:mutexLocked 持有锁的标记")])]),t._v(" "),n("p",[t._v("我们先前知道,如果想要获取锁的 goroutine 没有机会获取到锁,就会进行休眠,但是在锁释放唤醒之后,它并不能像先前一样直接获取到锁,还是要和正在请求锁 goroutine 进行竞争。这会给后来请求锁的 goroutine 一个机会,也让 CPU 中正在执行的 goroutine 有更多的机会获取到锁,在一定程度上提高了程序的性能。")]),t._v(" "),n("p",[t._v("在这次演变中,go 的调度器会将新的 goroutine 给赋予锁,因为新的 goroutine 就是正在 cpu 执行片段中执行的 goroutine,这个时候将锁给他们无疑是效率最高的。")]),t._v(" "),n("h4",{attrs:{id:"互斥锁演变的四个阶段三-多给机会-优先新-goroutine-以及被唤醒的-goroutine"}},[t._v("互斥锁演变的四个阶段三:多给机会,优先新 goroutine 以及被唤醒的 goroutine")]),t._v(" "),n("p",[t._v("如果新来的 goroutine 或者是被唤醒的 goroutine 首次获取不\n到锁,它们就会通过"),n("strong",[t._v("自旋")]),t._v(" (spin,通过循环不断尝试) 的方式,尝试检查锁是否被释放。在尝试"),n("strong",[t._v("一定")]),t._v("的自旋次数后,再执行原来的逻辑。")]),t._v(" "),n("h4",{attrs:{id:"互斥锁演变的四个阶段四-在第三个阶段的基础上引入饥饿模式"}},[t._v("互斥锁演变的四个阶段四:在第三个阶段的基础上引入饥饿模式")]),t._v(" "),n("p",[t._v("为什么会加入饥饿模式呢?就是因为如果都优先给新的 goroutine,那么等待队列中的 goroutine 就永远不会被执行,所以引入了饥饿模式,优先执行等待中的 goroutine\n然后新的 gorontine 就被添加到了等待队列中的队尾,这个时期称之为饥饿模式,因为新的 goroutine 基本上都要在 cpu 的时间片段中执行,所以在这个模式下,执行效率反而是底下的,因为正在执行的 goroutine 被强行放到队尾了。")]),t._v(" "),n("p",[t._v("当等待的队首的 goroutine 等待时间超过 1ms 就会进入这个模式")]),t._v(" "),n("p",[t._v("当队首的 goroutine 等待时间小于 1ms 或者已经执行到队尾了,那么这个模式就会从饥饿模式改为正常的模式")]),t._v(" "),n("h3",{attrs:{id:"sync-mutex-易错的几种场景"}},[t._v("sync.Mutex 易错的几种场景")]),t._v(" "),n("h4",{attrs:{id:"lock-unlock-不是成对出现"}},[t._v("Lock/Unlock 不是成对出现")]),t._v(" "),n("p",[t._v("因为 go 语言中,互斥锁是无法获取 goroutine 的信息的,所以存在 a 锁 b 解的情况,即:a goroutine 上了锁,b goroutine 给解开了。")]),t._v(" "),n("p",[t._v("如果你不是为了实现锁,是为了任务编排,那么可以这么做。")]),t._v(" "),n("p",[t._v("如果是为了锁,请不要这么做,因为这么做的后果就是这将不能形成锁这个概念")]),t._v(" "),n("p",[t._v("或者说当你使用了 lock 的时候忘记 unlock 了,那么最终都会导致系统走向失败")]),t._v(" "),n("h4",{attrs:{id:"copy-已经使用的-mutex"}},[t._v("Copy 已经使用的 Mutex")]),t._v(" "),n("p",[t._v("go 语言的 mutex 使用 state 字段去表示锁的含义,所以当你 copy 一个锁的时候,实际上已经 copy 了这个锁的状态,这将导致错误的结果")]),t._v(" "),n("p",[t._v("go 语言的同步原语众多,使用的底层都是 mutex (包括 channel),所以说,不仅仅是 mutex 不能使用 copy,其它的同步原语都不能。")]),t._v(" "),n("h4",{attrs:{id:"重入"}},[t._v("重入")]),t._v(" "),n("p",[t._v("所谓重入,就是多次上锁,注意这里是拥有锁的这个线程去请求这把锁")]),t._v(" "),n("p",[t._v("go 语言不支持重入,系统会 panic,这种重入锁无法实现也跟 go 语言的互斥锁没有记录使用它的 goroutine 有关系")]),t._v(" "),n("p",[t._v("那么如果 go 语言也实现一个重入锁,核心就是将持有锁的 goroutine 的 id 记录下来")]),t._v(" "),n("h4",{attrs:{id:"死锁"}},[t._v("死锁")]),t._v(" "),n("p",[t._v("当多线程的情况下,多个线程陷入了争抢资源的情况,当他们都陷入了停滞状态,或者阻塞状态的时候,就会发生死锁,deaadlock")]),t._v(" "),n("p",[t._v("一般来讲,当你发现系统多个线程都堵死的时候,就会发生死锁情况了,但是通常发生死锁是发生在满足这四个情况下")]),t._v(" "),n("ul",[n("li",[t._v("互斥:资源具有排他性,只能有一个 goroutine 访问")]),t._v(" "),n("li",[n("strong",[t._v("持有和等待")]),t._v(":goroutine 持有资源,并还在请求其它资源")]),t._v(" "),n("li",[t._v("不可剥夺:资源只有被它持有的 goroutine 释放")]),t._v(" "),n("li",[n("strong",[t._v("环路等待")]),t._v(":发生了环路等待事件,下面这个案例可以解释这个理论")])]),t._v(" "),n("p",[t._v("举一个案例")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wg sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu1 sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu2 sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n mu1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n mu2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n mu2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n mu1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" mu1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("在这个案例中,mu1 和 mu2 代表两个资源,两个 goroutine 在争夺这两个资源,下面我们盘点一下上文说的四个理论知识:")]),t._v(" "),n("ul",[n("li",[t._v("互斥性:资源只能被一个 goroutine 持有")]),t._v(" "),n("li",[t._v("持有和等待,一个 goroutine 获取了一把锁,还想获取第二把")]),t._v(" "),n("li",[t._v("不可剥夺,持有锁的 goroutine 释放锁后,其他 goroutine 不能再获取该锁")]),t._v(" "),n("li",[t._v("环路等待,两个 goroutine 陷入了环路这个概念总,第一个先持有 mu1,第二个 goroutine 先持有 mu2,他们又分别要获取另一个锁,所以陷入了环路等待中")])]),t._v(" "),n("p",[n("img",{attrs:{src:a(431),alt:"h"}})]),t._v(" "),n("p",[t._v("所以这个案例中,发生了死锁")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("fatal "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" all goroutines are asleep "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" deadlock"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n\ngoroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("semacquire"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("runtime_Semacquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xc0000a4020")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("runtime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("62")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x25")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("WaitGroup"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x0")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("waitgroup"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("116")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x48")]),t._v("\nmain"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("tmp"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sandbox1712910389"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("prog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("31")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x125")]),t._v("\n\ngoroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("17")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("runtime_SemacquireMutex")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x1")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x58")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x459218")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("runtime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("77")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x25")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("lockSlow")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xc0000a2028")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("171")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x15d")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("90")]),t._v("\nmain"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("main"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("func1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("tmp"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sandbox1712910389"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("prog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xd1")]),t._v("\ncreated by main"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("main in goroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("tmp"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sandbox1712910389"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("prog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("15")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xb9")]),t._v("\n\ngoroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("18")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Lock"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("runtime_SemacquireMutex")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x1")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x58")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x459218")]),t._v("?"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("runtime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("77")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x25")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("lockSlow")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xc0000a2020")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("171")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x15d")]),t._v("\nsync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("usr"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("local"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("faketime"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("90")]),t._v("\nmain"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("main"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("func2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("tmp"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sandbox1712910389"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("prog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("28")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xd1")]),t._v("\ncreated by main"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("main in goroutine "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("tmp"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sandbox1712910389"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("prog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("23")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x119")]),t._v("\n\n")])])]),n("h3",{attrs:{id:"sync-mutex-扩展"}},[t._v("sync.Mutex 扩展")]),t._v(" "),n("p",[t._v("这里主要讲解如何对 sync.Mutex 进行功能扩展")]),t._v(" "),n("p",[t._v("基本的原理就是"),n("strong",[t._v("将 sync.Mutex 嵌入到一个新的接口体中,然后重载 Lock 和 Unlock 的方法进行改造")])]),t._v(" "),n("h4",{attrs:{id:"改造一个重入锁"}},[t._v("改造一个重入锁")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" RecursiveMutex "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n owner "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// goroutine id")]),t._v("\n recursion "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//当前goroutine重入次数")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("lock 操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("RecursiveMutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 第三方包,目的是获取正在获取锁的lock 操作的 runtime id")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// github.com/petermattis/goid")]),t._v("\n gid "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goid"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 判断当前goroutine是否是要重入的goroutine")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LoadInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" gid "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 重入指标+1")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recursion"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取得到锁的goroutine的id")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("StoreInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" gid"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("StoreInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recursion"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("unlock 操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("RecursiveMutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n gid "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" goid"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 非持有锁的goroutine去释放锁直接panic")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LoadInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" gid "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wrong"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("owner"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("gid"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 重入指标-1")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("StoreInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recursion"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recursion "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LoadInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recursion"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 持有的goroutine还没有全部unlock")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将 重入指标设置为-1")]),t._v("\n atomic"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("StoreInt64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("recursion"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"sync-rwmutex"}},[t._v("sync.RWMutex")]),t._v(" "),n("p",[t._v("上文我们提到了互斥锁,互斥锁是真的锁,不论是读还是写都只能有一个 goroutine 去操作,所以说互斥锁才是真的锁,那么我们这里讲的读写锁是什么含义呢?")]),t._v(" "),n("p",[t._v("读写锁:允许多个 goroutine 同时去读一个数据,但是这个时候是不允许写的;只允许一个 goroutine 去写一个数据,并且不允许其它 goroutine 去读这个数据。")]),t._v(" "),n("p",[t._v("所以,读写锁跟互斥锁相比,把读的权限给增大了,但是写的权限不变。")]),t._v(" "),n("p",[t._v("当我们遇到一个读多写少的场景,那么使用读写锁的效率要比互斥锁的效率高的多。")]),t._v(" "),n("p",[t._v("读写锁拥有以下几个方法:")]),t._v(" "),n("ul",[n("li",[t._v("Lock/Unlock:写操作时加的锁")]),t._v(" "),n("li",[t._v("Rlock/RUnlock:读操作时加的锁")]),t._v(" "),n("li",[t._v("Rlocker:为读操作返回一个 Locker 接口的对象")])]),t._v(" "),n("p",[t._v("RWMutex 跟 mutex 一样,初始值都是未加锁的状态,当然他们都是有状态的结构体,所以也不能复制锁,因为初始值就是未加锁,所以直接声明即可。")]),t._v(" "),n("p",[t._v("总结一下读写锁的几个注意事项")]),t._v(" "),n("ul",[n("li",[t._v("上文提到了,不可复制")]),t._v(" "),n("li",[t._v("lock 和 unlock 要成对出现;Rlock 和 RUnlock 也要成对出现")])]),t._v(" "),n("p",[t._v("下面我们看一下,使用读写锁造成的死锁问题")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这个写法出问题的原因是:读锁还没结束就开启了写锁")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RWMutex\n\n\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RLock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RUnlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("出现死锁的原因就是出现了环形等待,读锁等待写锁解锁,写锁等待读锁解锁")]),t._v(" "),n("h2",{attrs:{id:"sync-waitgroup"}},[t._v("sync.WaitGroup")]),t._v(" "),n("p",[t._v("它的作用是任务的编排")]),t._v(" "),n("p",[t._v("waitgroup 一共有三个方法:")]),t._v(" "),n("ul",[n("li",[t._v("Add(delta int):增加 delta 个任务")]),t._v(" "),n("li",[t._v("Done():任务完成,减少一个任务")]),t._v(" "),n("li",[t._v("Wait():阻塞等待,直到所有任务完成")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wg sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wg "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"常见错误"}},[t._v("常见错误")]),t._v(" "),n("ul",[n("li",[t._v("add 的时候数值传入负值")]),t._v(" "),n("li",[t._v("done 的次数超过 add 中的次数")]),t._v(" "),n("li",[t._v("在 add 之前调用了 wait")]),t._v(" "),n("li",[t._v("当前一个 waitgroup 还没有完结就开始重用了 waitgroup,也就是说,必须等到上一轮的 wait 执行完毕了才能开启新的一轮")])]),t._v(" "),n("p",[t._v("最后这个错误我们看一个案例:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wg sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// AA")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("在这个案例中,AA 处的 add 行为有可能发生在主 goroutine 之后,那么相当于一轮未结束又开启了新的一轮,就会发生 panic 行为")]),t._v(" "),n("p",[t._v("当然了,我不是说 add 只能调用一次,但是 add 虽然能调用多次,但是不能发生在 wait 之后")]),t._v(" "),n("p",[t._v("正确的多次调用 add 的案例:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" wg sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("注意,我们这里每次循环都调用了一次 add,但是 add 的调用始终发生在 wait 之前,这还是属于同一轮的多次 add 调用,这符合 waigroup 的规定")]),t._v(" "),n("h2",{attrs:{id:"singleflight"}},[t._v("SingleFlight")]),t._v(" "),n("blockquote",[n("p",[t._v("著名缓存库 "),n("a",{attrs:{href:"https://github.com/golang/groupcache",target:"_blank",rel:"noopener noreferrer"}},[t._v("groupcache"),n("OutboundLink")],1),t._v(" 就使用了 singleflight 去通过缓存来减少后端查询数据库的请求")])]),t._v(" "),n("p",[t._v("在处理多个 goroutine 同时调用同一个函数的时候,只让一个 goroutine 去调用这个函数,等到这个 goroutine 返回结果的时候,再把结果返回给这几个同时调用的 goroutine")]),t._v(" "),n("p",[t._v("在面对多个 goroutine 并发去读一个数据的时候,使用 SingleFlight 可以大大降低请求量,从 n 的请求量降低到 1,比如在秒杀的场景下,n 个 goroutine 去请求数据,那么我们使用 SingleFlight 就能大大提高读的性能")]),t._v(" "),n("p",[t._v("SingleFlight 提供了三个公开方法:")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("func (g *Group) Do(key string,fn func() (interface {},error)) (v interface {},err error,shared bool)")])]),t._v(" "),n("li",[n("p",[t._v("func (g *Group) DoChan(key string,fn func() (interface {},error)) <-chan Result")])]),t._v(" "),n("li",[n("p",[t._v("func (g *Group) Forget(key string)")])]),t._v(" "),n("li",[n("p",[t._v("Do:Do 执行并返回函数的结果,同样 key 值下的只能有一个 goroutine 持有的 do 方法会执行,其它的都会等待,直到唯一一个执行完毕有了结果,那么大家 (指都执行 do 的众多 goroutine) 都有了结果")])]),t._v(" "),n("li",[n("p",[t._v("DoChan:跟 do 类似,返回值是一个 channel")])]),t._v(" "),n("li",[n("p",[t._v("Forget:告诉这个 group,忘记 key,之后,这个 key 请求回执行 f 函数,而不是等待前一个未完成的 fn 函数的结果")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v(" sf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("SingleFlight"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n\n sf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Do")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"param"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...function logic")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \tsf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Do")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"param"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n \t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result\n \t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n \t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 对于同一个key 下(这里是param)这些动作只执行一次,后续注册的函数会直接返回第一个函数的结果。")]),t._v("\n \t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n\n\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 后续想重新执行")]),t._v("\n sf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Forget")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"param"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n sf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Do")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"param"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这次会再次执行函数逻辑")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])]),t._v(" "),n("p",[t._v("下面我们看一下 DoChan 的基本使用方法:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"golang.org/x/sync/singleflight"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tg "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("singleflight"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Group"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tblock "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tres1c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" g"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoChan")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("block\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"func 1"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tres2c "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" g"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoChan")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("block\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"func 2"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("block"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tres1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("res1c\n\n\tres2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("res2c\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用相同的key执行的函数共享结果")]),t._v("\n\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Shared:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" res2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Shared"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 只有第一个函数被执行:它使用"key"被注册和启动,在第二个函数被注册相同的key之前就完成了执行。')]),t._v("\n\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Equal results:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" res1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Val"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" res2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Val"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Result:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" res1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Val"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("div",{staticClass:"language-bash extra-class"},[n("pre",{pre:!0,attrs:{class:"language-bash"}},[n("code",[t._v("Shared: "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\nEqual results: "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\nResult: func "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n")])])]),n("p",[t._v("g.DoChan / g.Do 都会在内部会启动一个新的 goroutine 来执行传入的函数。")]),t._v(" "),n("p",[t._v("g.DoChan 的签名如下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("g "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Group"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("DoChan")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fn "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Result\n")])])]),n("p",[t._v("它接受一个 key 和一个函数 fn,并返回一个 Result 类型的 channel。")]),t._v(" "),n("p",[t._v("在 g.DoChan 内部,会首先根据 key 在内部 map 中查找是否已经有相同 key 的函数在执行:")]),t._v(" "),n("ul",[n("li",[t._v("如果存在,则直接返回已有的 Result channel")]),t._v(" "),n("li",[t._v("如果不存在,则启动一个新的 goroutine 执行 fn 函数,并将 Result 发送到返回的 channel 中")])]),t._v(" "),n("p",[t._v("所以 g.DoChan 会确保对于相同的 key,最多只有一个 goroutine 在执行 fn,后续的调用会直接复用已有的结果。")]),t._v(" "),n("p",[t._v("这就实现了 key 去重重复执行的语义。")]),t._v(" "),n("p",[t._v("所以,g.DoChan 会隐式地启动 goroutine 来运行函数,这是它实现并发和协调的基础。")]),t._v(" "),n("p",[t._v("我们在处理缓存击穿的问题时,通常采用 singleflight 会有比较好的适用,所谓缓存击穿就是大量请求在请求一个 key 值时,key 值失效了,大量数据开始请求数据库,使用 singleflight 时,大量数据只需要一次请求,完美解决了缓存击穿问题")]),t._v(" "),n("blockquote",[n("p",[t._v("缓存击穿:指一个 key 非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个 key 在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像弹丸穿透目标一样。当某个 key 在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会对数据库造成压力。")])]),t._v(" "),n("blockquote",[n("p",[t._v("缓存穿透:指查询一个数据库一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。")])]),t._v(" "),n("blockquote",[n("p",[t._v("缓存雪崩:指在某一个时间段,缓存集中过期失效。所有访问都落到数据库上,对数据库造成巨大压力。这通常因为缓存服务器宕机或缓存时效过短导致,可通过服务器保护或增大缓存过期时间来避免。")])]),t._v(" "),n("h2",{attrs:{id:"cyclicbarrier"}},[t._v("cyclicBarrier")]),t._v(" "),n("blockquote",[n("p",[t._v("github.com/marusama/cyclicbarrier")])]),t._v(" "),n("p",[t._v("允许一组 goroutine 彼此等待,到达一个共同的执行点。同时,因为它可\n以被重复使用,所以叫循环栅栏")]),t._v(" "),n("p",[t._v("基本用法就是 Await 方法,等待所有的参与者到达,到达了就往下走,然后开始新的循环")]),t._v(" "),n("p",[t._v("那么看起来很像 waitgroup,那么为什么不使用 wg 呢?")]),t._v(" "),n("p",[t._v("在一种场景下 wg 通常很难使用,也就是循环这个含义,因为你需要在 wait 之后再次调用 add 方法充值,然后继续 done wait,麻烦,并且万一在继续 add 的时候发生了并发问题就跟灾难了")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("WaitGroup 更适合用在 “一个 goroutine 等待一组 goroutine 到达同一个执行点” 的场景中,或者是不需要重用的场景中。")])]),t._v(" "),n("li",[n("p",[t._v("CyclicBarrier 更适合用在 “固定数量的 goroutine 等待同一个执行点” 的场景中,而且在放行 goroutine 之后,CyclicBarrier 可以重复利用,不像 WaitGroup 重用的时候,必须小心翼翼避免 panic。")])])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 数字代表执行任务的 goroutine 的个数")]),t._v("\nb1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" cyclicbarrier"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 或者带有方法的循环栅栏")]),t._v("\nb2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" cyclicbarrier"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewWithAction")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\nb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Await")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// await other parties")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将循环栅栏重置")]),t._v("\nb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Reset")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// reset the barrier")]),t._v("\n")])])]),n("p",[t._v("我们可以发现循环栅栏会一直循环的执行,虽然它有 await 方法,但是每次到这个 await 都会继续执行下一轮的循环,那么该如何跳出循环呢?")]),t._v(" "),n("p",[t._v("通常我们会配合 sync.WaitGroup 一起执行")]),t._v(" "),n("h2",{attrs:{id:"errgroup"}},[t._v("errgroup")]),t._v(" "),n("p",[t._v("将一个通用的父任务,拆成几个小任务并发执行的场景")]),t._v(" "),n("ul",[n("li",[t._v("WithContex 表示创建一个 group 实例,并且创建一个 withcancel 的上下文 context,一旦子任务返回错误,或者 wait 调用返回,context 就会被 cancel")]),t._v(" "),n("li",[t._v("Go Go(f func()error) 传入的子任务,一旦 error,就会促发 withcancel 的 cancel 操作")]),t._v(" "),n("li",[t._v("Wait 等待所有任务都完成后,wait 才会执行")])]),t._v(" "),n("h2",{attrs:{id:"sync-once"}},[t._v("sync.Once")]),t._v(" "),n("p",[t._v("once 用来执行仅发生一次的动作,常用与单例模式,对象初始化的行为,并且经常在 init 函数中使用")]),t._v(" "),n("p",[t._v("sync.Once 仅仅暴漏了一个 do 方法,而且多次调用 do,仅有第一次的无返回值的 f 函数可以执行,即便 f 不同:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" once sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Once\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n once"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Do")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 仅执行一次")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这次不会执行")]),t._v("\n once"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Do")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"讨论线程安全的-map-在多线程中的使用"}},[t._v("讨论线程安全的 map 在多线程中的使用")]),t._v(" "),n("p",[t._v("go 语言中的 map 并不是并发安全的,一个 map 如果不加锁的去处理数据的时候就会出现 panic 的情况,比如:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始化一个map")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//设置key")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//访问这个map")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这种写法就会发生 panic,原因是 go 语言不支持并发读写 map,必须加锁")]),t._v(" "),n("p",[t._v("其实我们如果分析这段代码,并没有说对同一个 key 值进行读写,也没有涉及到扩容的问题,但是仍然会 panic,go 在操作 map 时会进行 data race 的检测,只要检测有,就会直接 panic")]),t._v(" "),n("h3",{attrs:{id:"直接加锁"}},[t._v("直接加锁")]),t._v(" "),n("p",[t._v("我们可以人为的加锁,这样就可以避免 data race 的行为")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始化一个map")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//设置key")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//访问这个map")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("如果数据量比较低的话,这么做毫无问题,如果数据量较大,或者每次操作都比较耗时,读写公用一锁就比较浪费了。")]),t._v(" "),n("p",[t._v("那么可以使用读写锁吗?当然可以啦,我们使用读写锁可以更优秀的去解决这个问题")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("RWMutex\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始化一个map")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//设置key")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RLock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//访问这个map")]),t._v("\n\t\t\tmu"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("RUnlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("RWMutex 在同时有读写需求时,会优先获取写锁,读锁需要等待")]),t._v(" "),n("p",[t._v("如果当前有读锁,则后续的写锁请求会被阻塞,但读锁可以继续获取,")]),t._v(" "),n("p",[t._v("如果当前有写锁,则后续的读锁和写锁请求都会被阻塞。")]),t._v(" "),n("p",[t._v("所以,如果读多写少,使用读写锁是非常方便的,假如读和写都异常的高,那么读和写其实是不能同时进行的,如果读贼多,写就可能被阻塞等待了。")]),t._v(" "),n("h3",{attrs:{id:"细颗粒度并发安全-map"}},[t._v("细颗粒度并发安全 Map")]),t._v(" "),n("p",[t._v("我们都知道,锁对于性能的影响是特别大的,尤其是线程非常多的时候,那么多线程公用一个锁,各种等待,能不影响效率吗,那么怎么做能提高效率呢?")]),t._v(" "),n("p",[t._v("降低锁的颗粒度就可以提高效率,换言之就是本来 1000 个线程公用一个,现在,我们把数据分为 10 份,100 个线程用一个锁,性能就能大范围的提高")]),t._v(" "),n("p",[t._v("我们可以使用 https://github.com/orcaman/concurrent-map 这个分片儿锁去替代互斥锁")]),t._v(" "),n("p",[t._v("分片儿锁的基本原理就是将一个大的 map 的内容,变成 10 个或者是更多个 map 的内容,我们可以这么做:")]),t._v(" "),n("p",[t._v("本身需要一个 map 的数据结构,我们改成一个 slice,slice 含有 10 个 map 的数据结构\n我们还需要一个定位分片的算法,基本上都是使用一个哈希算法先定位分片,然后后续就跟一般的互斥锁一致了。\n用法如下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a new map.")]),t._v("\n\tm "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" cmap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("New"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Sets item within map, sets "bar" under key "foo"')]),t._v("\n\tm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"foo"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bar"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Retrieve item from map.")]),t._v("\n\tbar"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"foo"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// Removes item under key "foo"')]),t._v("\n\tm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Remove")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"foo"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("h3",{attrs:{id:"sync-map"}},[t._v("sync.Map")]),t._v(" "),n("p",[t._v("这是 go 官方提供的一个线程安全的 map,先说使用场景,只写一次,大量读的场景。")]),t._v(" "),n("p",[t._v("sync.Map 跟分片锁不同,分片锁是直接降低颗粒度,sync.Map 它的基本原理是读写分离,用空间换时间。通过一个只读的数据结构来提高读取速度。")]),t._v(" "),n("p",[t._v("当读少写多的时候,它的效率甚至比直接使用互斥锁还低,总之如果不是写少读多的场景,千万不要用,这个包的使用率挺低的。")]),t._v(" "),n("h2",{attrs:{id:"sync-pool"}},[t._v("sync.Pool")]),t._v(" "),n("p",[t._v("sync.Pool 是一个对象池,如果我们有一些重复使用的,并且需要频繁的申请和释放的临时对象,那么可以用这个对象池来提高性能。不过这个池子里的对象有可能会被垃圾回收,所以非常重要的数据不能使用这种方法")]),t._v(" "),n("p",[t._v("我来描述一种场景,我们有数据需要被 goroutine 去处理,但是谁处理都行,不 care 是哪位,那么我们就可以创建很多的 goroutine,然后放入到 goroutine 池中 (就跟外包一样。。。)")]),t._v(" "),n("p",[t._v("sync.Pool 有两个注意事项,首先,它线程安全,其次,不能复制 sync.Pool,如果你复制一个 sync.Pool,实际上得到的只是一个指针的拷贝,并不会复制本地池子,所以多个拷贝的 sync.Pool 指针指向的是同一个本地池子,达不到复用的目的。应该定义一个全局的 sync.Pool 实例,不同的 goroutine 都使用这个实例,才能达到对象复用和减少内存分配的目的")]),t._v(" "),n("p",[t._v("pool 包拥有三个方法")]),t._v(" "),n("ul",[n("li",[t._v("New,pool 的 new 方法后面跟的是创建的内容,一旦 pool 里面空了,就会调用这个 new 方法,当然你也可以不指定这个参数,那么创建的就是 nil 了")]),t._v(" "),n("li",[t._v("Get 从 pool 中获取一个对象")]),t._v(" "),n("li",[t._v("Set 将对象送回 pool 中")])]),t._v(" "),n("p",[t._v("下面举一个演示的例子:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" buffer "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n New"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" any "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetBuffer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" buffer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("PutBuffer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Reset会将缓冲区重置为空,但它会保留底层存储以供将来写入使用")]),t._v("\n buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Reset")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n buffers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Put")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这段代码是会有内存泄露的风险的,原因也很简单,buf.Reset() 并不会删除底层 slice 的容量,它会保存底层数据结构中的容量,所以 gc 的时候这个 buffer 就非常有可能不会被回收,造成内存泄露")]),t._v(" "),n("p",[t._v("改正方法也很简单,底层数据太大了直接丢弃 gc 就 ok 了,小的放到池子里")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("PutBuffer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Reset会将缓冲区重置为空,但它会保留底层存储以供将来写入使用")]),t._v("\n buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Reset")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" maxSize"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n buffers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Put")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"pool-内存浪费"}},[t._v("pool 内存浪费")]),t._v(" "),n("p",[t._v("当我们需求的内存比池子中的内存小很多的时候,就会造成内存浪费,解决方法就是多造几个池子,比如小池子,中池子,大池子,使用这种方案合理的使用内存")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n readerPool sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pool\n reader2kPool sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pool\n reader4kPool sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pool\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("推荐一个三方库,特点是能更加高效的发挥系统性能节约内存以及避免内存泄露问题等,他可以动态的去调节池子的 dafault size 和 max size")]),t._v(" "),n("p",[t._v("https://github.com/valyala/bytebufferpool")]),t._v(" "),n("p",[t._v("连接池也是一个很常见的需求,但是通常不会使用 pool,因为 pool 会被 gc,所以并不靠谱,通常我们使用 map 或者 slice 去实现一个需要真的长时间稳定连接的连接池比如:")]),t._v(" "),n("ul",[n("li",[t._v("http client 池")]),t._v(" "),n("li",[t._v("tcp 连接池,推荐三方库:https://github.com/fatih/pool")]),t._v(" "),n("li",[t._v("数据库连接池")]),t._v(" "),n("li",[t._v("memcached client 连接池")])]),t._v(" "),n("h3",{attrs:{id:"worker-pool"}},[t._v("worker pool")]),t._v(" "),n("p",[t._v("worker pool 其实就是 goroutine 的池子,虽然 go 语言的 goroutine 非常的轻量化,但是如果几十万上百万的 goroutine 被创建还是会出问题的")]),t._v(" "),n("p",[t._v("因为 goroutine 是一种要求长期存在的资源,所以一般不使用 pool,而是使用 channel 去作为池子,毕竟 channel 自带线程安全")]),t._v(" "),n("p",[t._v("Worker pool 的目的是为了重用 goroutine。但它重用的不是 goroutine 本身,而是通过 goroutine 执行任务的能力。")]),t._v(" "),n("p",[t._v("如果直接在 channel 中传递 goroutine,那么每个 goroutine 只能执行唯一的一个任务,执行完就退出了。这并没有实现重用。")]),t._v(" "),n("p",[t._v("而 worker pool 的设计是:")]),t._v(" "),n("p",[t._v("创建固定数量的 goroutine 作为 workers。\nworkers 在 loop 中持续从任务 channel 接收任务并执行。\n向任务 channel 不断发送不同的任务。\n这样,每个 worker(goroutine) 就可以执行多个任务,实现重用。")]),t._v(" "),n("p",[t._v("所以 channel 中的内容不是 goroutine,而是任务信息,用于指导 goroutine 执行什么任务。goroutine 从 channel 收任务,利用自身的执行能力反复执行不同的任务。")]),t._v(" "),n("p",[t._v("这才是 worker pool 设计的核心思想 - 通过固定数量的 goroutine 反复执行不同的任务,以重用 goroutine 实现高效调度。")]),t._v(" "),n("p",[t._v("所以,worker pool 的目的是重用 goroutine 的执行能力,而不是重用 goroutine 本身。这是通过 channel+goroutine 的组合实现的,channel 用于传递任务信息,goroutine 负责执行任务")]),t._v(" "),n("p",[t._v("让我们简单的实现一个方案:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 任务类型")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Task "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n f "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 任务函数")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 执行任务")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Task"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Execute")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 单个worker池 ")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Worker "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n TaskChan "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Task\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Worker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Start")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n task "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TaskChan\n task"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Execute")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 为worker 池 分配 goroutine ,这得结合下面的 Newpool 才能看出来")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Pool "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n TaskChan "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Task\n Workers "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Worker\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建worker池")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewPool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("numWorkers "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Pool "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n taskChan "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Task"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始化workers")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" workers "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Worker\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" numWorkers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n worker "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Worker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n TaskChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" taskChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n workers "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("workers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" worker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" worker"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Start")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Pool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n TaskChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" taskChan"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n Workers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" workers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 分发任务")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Pool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Schedule")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("task "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Task"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("TaskChan "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" task\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("使用方式")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 定义任务")]),t._v("\ntask1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Task"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n f"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// do something")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\npool "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewPool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 分发任务")]),t._v("\npool"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Schedule")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("task1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("提供一些个优秀的 worker pool 方案")]),t._v(" "),n("ul",[n("li",[t._v("gammazero/workerpool")]),t._v(" "),n("li",[t._v("ivpusic/grpool")]),t._v(" "),n("li",[t._v("dpaks/goworkers")]),t._v(" "),n("li",[t._v("https://github.com/alitto/pond")])]),t._v(" "),n("h2",{attrs:{id:"semaphore"}},[t._v("semaphore")]),t._v(" "),n("p",[t._v("信号量 (英语:semaphore) 又称为信号标,是一个同步对象,用于保持在 0 至指定最大值之间的一个计数值。")]),t._v(" "),n("p",[t._v("在系统中,给予每一个进程一个信号量,代表每个进程目前的状态,未得到控制权的进程会在特定地方被强迫停下来,等待可以继续进行的信号到来")]),t._v(" "),n("p",[t._v("根据信号量的不同可以分为计数信号量和二进制信号量,前者使用一个整数作为信号量,后者使用一个二进制 0 1 作为信号量")]),t._v(" "),n("p",[t._v("信号量拥有两个操作:")]),t._v(" "),n("ul",[n("li",[t._v("p 操作会减少信号量的数值")]),t._v(" "),n("li",[t._v("v 操作会增加信号量的数值")])]),t._v(" "),n("p",[t._v("其中二进制信号量是特殊的信号量,它就是互斥锁的功能")]),t._v(" "),n("p",[t._v("go 语言在 x/sync 中提供了一个 weighted 的包,它就是提供的信号量的功能")]),t._v(" "),n("ul",[n("li",[t._v("Acquire p 操作,减少信号量的数值,表示获取了资源 -1")]),t._v(" "),n("li",[t._v("Release v 操作,增加信号量的数值,表示释放了资源 +1")]),t._v(" "),n("li",[t._v("TryAcquire 尝试获取资源,如果获取成功,则返回 true,否则返回 false\n它类似于 trylock 锁,也就是失败直接返回 false,并不会阻塞")])]),t._v(" "),n("p",[t._v("注意,信号量为了简洁的设计要求,pv 操作使用 +1 和 -1 这种非常简单的递增递减设计,是有意为之的。这种简单性使得信号量在各种同步情况下都很容易理解和正确使用。更复杂的操作可能会引入难以发现的 bug 或误用场景。")]),t._v(" "),n("p",[t._v("让我们使用信号量来实现一个 worker pool")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"log"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"runtime"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 最大的worker数量")]),t._v("\n\tmaxWorkers "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("GOMAXPROCS")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsema "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewWeighted")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("int64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maxWorkers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//信号量")]),t._v("\n\ttask "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" maxWorkers"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 任务数,是worker的四倍")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tctx "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" task "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果没有worker可用,会阻塞在这里,直到某个worker被释放")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Acquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 启动worker goroutine")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Release")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Millisecond"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 模拟一个耗时操作")]),t._v("\n\t\t\ttask"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 请求所有的worker,这样能确保前面的worker都执行完")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" sema"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Acquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ctx"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("int64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maxWorkers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tlog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"获取所有的worker失败: %v"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("task"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"使用信号量时的注意事项"}},[t._v("使用信号量时的注意事项")]),t._v(" "),n("ul",[n("li",[t._v("请求了资源,忘记了释放")]),t._v(" "),n("li",[t._v("释放了从未请求的资源")]),t._v(" "),n("li",[t._v("长时间持有一个资源但是不使用它")]),t._v(" "),n("li",[t._v("不持有一个资源,但是直接使用了它")])]),t._v(" "),n("h3",{attrs:{id:"使用-channel-去实现一个信号量"}},[t._v("使用 channel 去实现一个信号量")]),t._v(" "),n("p",[t._v("使用一个缓存为 n 的 channel 去实现一个信号量")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Semaphore 数据结构,并且还实现了Locker接口")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" semaphore "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建一个新的信号量")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewSemaphore")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("capacity "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Locker "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" capacity "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tcapacity "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 容量为1就变成了一个互斥锁")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" capacity"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 请求一个资源")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 释放资源")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),n("h3",{attrs:{id:"问题一-有互斥锁就一定有临界区吗"}},[t._v("问题一:有互斥锁就一定有临界区吗?")]),t._v(" "),n("p",[t._v("互斥锁的存在不等于必须存在临界区。")]),t._v(" "),n("p",[t._v("构成一个合理的临界区,需要满足:")]),t._v(" "),n("ul",[n("li",[t._v("有真正需要互斥访问的共享资源 (比如共享内存,变量等)")]),t._v(" "),n("li",[t._v("通过加锁,在访问该资源前后形成互斥的代码区域")]),t._v(" "),n("li",[t._v("确保同一时间只有一个线程/goroutine 可以进入该互斥区域")])]),t._v(" "),n("p",[t._v("所以互斥锁只是手段之一,用于保证临界区互斥性的需要。")]),t._v(" "),n("p",[t._v("如果没有需要保护的共享资源,或者互斥逻辑不严密,那么使用再多的锁也不等于形成了临界区")]),t._v(" "),n("h3",{attrs:{id:"问题二-如果-mutex-已经被一个-goroutine-获取了锁-其它等待中的-goroutine-们只能一直等待。那么-等这个锁释放后-等待中的-goroutine-中哪一个会优先获取-mutex-呢"}},[t._v("问题二:如果 Mutex 已经被一个 goroutine 获取了锁,其它等待中的 goroutine 们只能一直等待。那么,等这个锁释放后,等待中的 goroutine 中哪一个会优先获取 Mutex 呢?")]),t._v(" "),n("p",[t._v("上文中的锁的饥饿模式和正常模式可以解释这个问题。")]),t._v(" "),n("p",[t._v("如果是正常的模式下,就是按照正常队列 FIFO 的顺序去获取锁,除非这个时候有新的 goroutine 生成,那么这个 goroutine 会优先获取锁。")]),t._v(" "),n("p",[t._v("但是如果一个队头的 goroutine 等待时间过长超过了 1ms,那么它就会将互斥锁的模式变成饥饿模式,自动获取锁")]),t._v(" "),n("h3",{attrs:{id:"问题三-mutext-的底层中-使用-state-和-sema-来表示锁的状态-sema-是信号量-为什么在有信号量表示锁的状态之后还需要一个-state-表示锁是否上锁呢"}},[t._v("问题三:Mutext 的底层中,使用 state 和 sema 来表示锁的状态,sema 是信号量,为什么在有信号量表示锁的状态之后还需要一个 state 表示锁是否上锁呢?")]),t._v(" "),n("ul",[n("li",[t._v("state 作为一个 boolean 变量,可以非常简单直观地表示锁的基本状态。")]),t._v(" "),n("li",[t._v("sema 是一个整数计数器,可以灵活地表示多种状态,如等待队列长度等。")]),t._v(" "),n("li",[t._v("将两者分开,可以清晰地分离基本锁状态和高级同步语义,符合分而治之的设计思想。")]),t._v(" "),n("li",[t._v("sema 可直接 reused 现成的信号量实现代码,state 又足够轻量不需要复杂机制。")]),t._v(" "),n("li",[t._v("将两者组合可以充分发挥各自的优势,实现一个功能完备但设计简单的 mutex。")]),t._v(" "),n("li",[t._v("如果全部只依赖 sema 来表示所有状态,实现可能会更复杂,语义也不够清晰。")])]),t._v(" "),n("h3",{attrs:{id:"问题四-使用循环栅栏-信号量去完成经典并发题-水的制造工厂"}},[t._v("问题四:使用循环栅栏,信号量去完成经典并发题:水的制造工厂")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//并发趣题:一氧化二氢制造工厂")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//题目是这样的:")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//有一个名叫大自然的搬运工的工厂,生产一种叫做一氧化二氢的神秘液体。这种液体的分子是由一个氧原子和两个氢原子组成的,也就是水。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//这个工厂有多条生产线,每条生产线负责生产氧原子或者是氢原子,每条生产线由一个 goroutine 负责。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//这些生产线会通过一个栅栏,只有一个氧原子生产线和两个氢原子生产线都准备好,才能生成出一个水分子,")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//否则所有的生产线都会处于等待状态。也就是说,一个水分子必须由三个不同的生产线提供原子,而且水分子是一个一个按照顺序产生的,")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//每生产一个水分子,就会打印出 HHO、HOH、OHH 三种形式的其中一种。HHH、OOH、OHO、HOO、OOO 都是不允许的。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//生产线中氢原子的生产线为 2N 条,氧原子的生产线为 N 条。")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/marusama/cyclicbarrier"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"golang.org/x/sync/semaphore"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"math/rand"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sort"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"time"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// h2o 水的组成,其中我们需要俩h一个o所以我们给定他们信号量,来对他们的任务进行控制。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" H2O "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 控制的h的信号量")]),t._v("\n\tseaH "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Weighted\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 控制O的信号量")]),t._v("\n\tseaO "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Weighted\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 栅栏,这里也就是重复的使用栅栏,也就是 重复栅栏。")]),t._v("\n\tcyc cyclicbarrier"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("CyclicBarrier\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewH2O")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("H2O "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("H2O"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// h 两个")]),t._v("\n\t\tseaH"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewWeighted")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// o 需要一个")]),t._v("\n\t\tseaO"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" semaphore"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewWeighted")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 我们要控制的循环栅栏就是3个,因为一共需要三个嘛。")]),t._v("\n\t\tcyc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" cyclicbarrier"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 处理h")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("H2O"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("dealH")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("outH "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将这个信号量给拿出来1,因为h充盈来2,所以会有俩线程做这个动作")]),t._v("\n\to"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("seaH"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Acquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 输出 h")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("outH")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// wait的意思就是不等到三个线程,我就不走")]),t._v("\n\to"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cyc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Await")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 走动完毕后再把资源塞进去。")]),t._v("\n\to"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("seaH"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Release")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 处理 o")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("H2O"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("dealO")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("outO "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 氧气将信号量中的信号取出来,")]),t._v("\n\to"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("seaO"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Acquire")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 输出o")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("outO")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等待三个线程跟上一个函数一样意思,也不用担心用两次不行,随便用。这个函数调用几次都OK。")]),t._v("\n\to"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("cyc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Await")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 释放掉。")]),t._v("\n\to"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("seaO"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Release")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// channel 传递信息。")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" ch "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" outO "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"O"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" outH "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"H"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 一共有 300个channel需要。")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// wg是为了控制这300个线程,栅栏是为了控制生成水的这个控制器,两者的作用不同哦。")]),t._v("\n\twg "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\twg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\th "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewH2O")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Duration")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rand"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Intn")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Millisecond"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\th"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("dealO")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("outO"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("200")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" wg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\ttime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Duration")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("rand"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Intn")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Millisecond"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\th"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("dealH")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("outH"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\twg"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("300")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"❌"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ts "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ts"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch\n\t\ts"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch\n\t\ts"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里,对于hho进行排序了,不然也不一定是hho这个顺序")]),t._v("\n\t\tsort"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Strings")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tresult "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" result "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"HHO"')]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"错误 ❌ :"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://mp.weixin.qq.com/s/iPpWd8vjyaN2sJFwxzN9Bg")]),t._v(" "),n("li",[t._v("https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-sync-primitives/")]),t._v(" "),n("li",[t._v("https://time.geekbang.org/column/intro/100061801")]),t._v(" "),n("li",[t._v("https://colobu.com/2018/12/18/dive-into-sync-mutex/")]),t._v(" "),n("li",[t._v("《go 语言精进之路》")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/110.9afae874.js b/assets/js/110.9afae874.js new file mode 100644 index 000000000..c0a885156 --- /dev/null +++ b/assets/js/110.9afae874.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[110],{541:function(e,t,v){"use strict";v.r(t);var _=v(36),o=Object(_.a)({},(function(){var e=this,t=e.$createElement,v=e._self._c||t;return v("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[v("h1",{attrs:{id:"go-语言官方编译器-gc"}},[e._v("go 语言官方编译器 gc")]),e._v(" "),v("h2",{attrs:{id:"前端组件"}},[e._v("前端组件")]),e._v(" "),v("ul",[v("li",[e._v("Lexer:进行词法分析,将代码分割成词法单元")]),e._v(" "),v("li",[e._v("Parser:进行语法分析,检查代码正确性,生成 AST")]),e._v(" "),v("li",[e._v("Type checker:进行类型检查,确保类型使用正确")])]),e._v(" "),v("h2",{attrs:{id:"中端组件"}},[e._v("中端组件")]),e._v(" "),v("ul",[v("li",[e._v("SSA:构建程序的静态单赋值形式中间表示")]),e._v(" "),v("li",[e._v("Optimizer:进行各种形式的优化,如内联、逃逸分析等")])]),e._v(" "),v("h2",{attrs:{id:"后端组件"}},[e._v("后端组件")]),e._v(" "),v("ul",[v("li",[e._v("Code generator:将优化后的代码生成对应的汇编代码")]),e._v(" "),v("li",[e._v("Assembler:汇编器,将汇编代码转换为机器代码")]),e._v(" "),v("li",[e._v("Linker:链接器,将对象代码链接成最终的可执行文件")]),e._v(" "),v("li",[e._v("运行时,Runtime:提供垃圾回收、协程调度等运行时功能")])]),e._v(" "),v("p",[e._v("gc 不仅包含 frontend,还包含了中间 representation、优化器、代码生成器等组件,可以完成 Go 代码的全部编译工作。它既是一个编译器,也提供了部分运行时支持。所以说 gc 是 Go 语言的整体编译与工具链解决方案。")]),e._v(" "),v("p",[e._v("gc 编译器由 Go 语言的创造者 Robert Griesemer、Rob Pike 及 Ken Thompson 开发,首次在2007年与 Go 一起开源发布。")]),e._v(" "),v("p",[e._v("gc 实现了对 Go 语言的完整支持,可以编译包括复杂特性如 goroutine、channel 和接口在内的所有 Go 语言程序。它输出自包含的可执行文件,不需要外部依赖。")]),e._v(" "),v("p",[e._v("gc 编译器写在 Go 语言本身并采用了 Go 的并发特性,编译速度非常快。它与 Go 的发布周期同步,确保语言 feature 得到及时支持。")]),e._v(" "),v("p",[e._v("所以 Go 语言默认编译器的全称就是 gc,它是官方提供的 Go 语言编译器。")]),e._v(" "),v("h2",{attrs:{id:"参考资料"}},[e._v("参考资料")]),e._v(" "),v("ul",[v("li",[e._v("https://go.dev/src/cmd/compile/README")])])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/111.fcb96ca2.js b/assets/js/111.fcb96ca2.js new file mode 100644 index 000000000..d8531316a --- /dev/null +++ b/assets/js/111.fcb96ca2.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[111],{543:function(c,g,t){"use strict";t.r(g);var n=t(36),o=Object(n.a)({},(function(){var c=this,g=c.$createElement,t=c._self._c||g;return t("ContentSlotsDistributor",{attrs:{"slot-key":c.$parent.slotKey}},[t("h1",{attrs:{id:"gccgo"}},[c._v("gccgo")]),c._v(" "),t("p",[c._v("gccgo 是 Gо 语言到 C 语言的编译器,它将 Gо 语言源代码编译成 C 语言源代码。")]),c._v(" "),t("p",[c._v("gccgo 本身只是一个编译器前端,负责解析 Gо 语言代码并生成 C 语言代码。要生成最终的可执行文件,还需要一个编译器后端。")]),c._v(" "),t("p",[c._v("gccgo 常见的后端有:")]),c._v(" "),t("p",[c._v("gcc - GNU 编译器,可以将 gccgo 生成的 C 语言代码进一步编译成机器代码,生成最终的可执行文件。\nclang - LLVM 编译器,同样可以将 C 语言编译成机器代码。\ntcc - Tiny C Compiler,一个小型快速的 C 语言编译器。\n所以简单来说,gccgo 编译器的常见后端是 gcc 和 clang。完整的编译流程是:")]),c._v(" "),t("p",[c._v("gccgo 前端 → C 语言代码 → gcc/clang 后端 → 机器代码 (可执行文件)")]),c._v(" "),t("p",[c._v("开发者可以根据需要选择不同的编译器后端,来编译 gccgo 生成的 C 语言代码。")])])}),[],!1,null,null,null);g.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/112.9e9125b6.js b/assets/js/112.9e9125b6.js new file mode 100644 index 000000000..c02affaf6 --- /dev/null +++ b/assets/js/112.9e9125b6.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[112],{544:function(l,v,_){"use strict";_.r(v);var o=_(36),L=Object(o.a)({},(function(){var l=this,v=l.$createElement,_=l._self._c||v;return _("ContentSlotsDistributor",{attrs:{"slot-key":l.$parent.slotKey}},[_("h1",{attrs:{id:"llvm"}},[l._v("llvm")]),l._v(" "),_("p",[l._v("LLVM 可以通过以下两种主要方式为 Go 语言代码提供编译支持:")]),l._v(" "),_("h2",{attrs:{id:"gollvm"}},[l._v("gollvm")]),l._v(" "),_("p",[l._v("gollvm 项目实现了将 Go 代码编译为 LLVM IR 的 frontend。它可以直接生成 LLVM IR,然后通过 LLVM 进行后端代码生成。")]),l._v(" "),_("p",[l._v("主要步骤是:")]),l._v(" "),_("ul",[_("li",[l._v("gollvm 解析 Go 代码,生成对应的 LLVM IR")]),l._v(" "),_("li",[l._v("执行 LLVM 优化流水线进行优化")]),l._v(" "),_("li",[l._v("LLVM 后端生成目标平台的机器码")]),l._v(" "),_("li",[l._v("嵌入 LLVM pass")])]),l._v(" "),_("h2",{attrs:{id:"可以通过修改-go-compiler-工具链-在编译过程中调用-llvm-pass-执行优化。"}},[l._v("可以通过修改 Go Compiler 工具链,在编译过程中调用 LLVM Pass 执行优化。")]),l._v(" "),_("p",[l._v("主要步骤是:")]),l._v(" "),_("ul",[_("li",[l._v("Go Compiler 前端生成 initial IR")]),l._v(" "),_("li",[l._v("将 IR 传递给 LLVM Pass 执行优化")]),l._v(" "),_("li",[l._v("LLVM Pass 输出优化后的 IR")]),l._v(" "),_("li",[l._v("Go Compiler 后端根据 IR 生成机器码")])]),l._v(" "),_("p",[l._v("这种方式需要 invasive 修改 Go 编译器,较为复杂。")]),l._v(" "),_("p",[l._v("总结:")]),l._v(" "),_("p",[l._v("gollvm 通过完全 External 的方式引入 LLVM,而嵌入 LLVM Pass 需要修改 Go Compiler。")]),l._v(" "),_("p",[l._v("gollvm 方式集成更简单,但是需要保证 IR 的转换正确性;嵌入 Pass 可以利用 Go Compiler 的 Context 信息进行更准确的优化。")]),l._v(" "),_("p",[l._v("根据需求和成本进行抉择。")]),l._v(" "),_("h2",{attrs:{id:"llvm-golang"}},[l._v("llvm -golang")]),l._v(" "),_("p",[l._v("llvm-golang 是另一个用于 Go 语言编译的 LLVM 集成项目。")]),l._v(" "),_("p",[l._v("它与 gollvm 的主要区别有:")]),l._v(" "),_("p",[l._v("实现方式不同")]),l._v(" "),_("ul",[_("li",[l._v("gollvm 是独立的 Go frontend,将 Go 代码编译成 LLVM IR")]),l._v(" "),_("li",[l._v("llvm-golang 直接使用 LLVM 对 Go 代码进行编译\n编译入口不同")]),l._v(" "),_("li",[l._v("gollvm 通过调用 gollvm 命令,传入 Go 源文件")]),l._v(" "),_("li",[l._v("llvm-golang 编译时调用 clang 命令,并使用-femulate-llvm-golang 参数\n编译过程不同")]),l._v(" "),_("li",[l._v("gollvm 编译生成完整的 LLVM IR 然后优化")]),l._v(" "),_("li",[l._v("llvm-golang 是逐函数生成 LLVM IR 并编译\n项目状态不同")]),l._v(" "),_("li",[l._v("gollvm 活跃维护,可正常使用")]),l._v(" "),_("li",[l._v("llvm-golang 最后更新在5年前,未维护\n总之,llvm-golang 是直接使用 LLVM 编译 Go 的早期尝试,但维护情况不佳。gollvm 作为独立 frontend 集成 LLVM,是更可靠的解决方案。")])]),l._v(" "),_("p",[l._v("但 llvm-golang 的直接编译方式也具有借鉴意义,合理结合两种方式可以获得更好的 LLVM 集成效果。")])])}),[],!1,null,null,null);v.default=L.exports}}]); \ No newline at end of file diff --git a/assets/js/12.521ef871.js b/assets/js/12.521ef871.js new file mode 100644 index 000000000..d9005c7a5 --- /dev/null +++ b/assets/js/12.521ef871.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{436:function(t,e,s){"use strict";s.r(e);var n=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],o={methods:{getMsg:function(){return n[Math.floor(Math.random()*n.length)]}}},i=s(36),h=Object(i.a)(o,(function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"theme-container"},[e("div",{staticClass:"theme-default-content"},[e("h1",[this._v("404")]),this._v(" "),e("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),e("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=h.exports}}]); \ No newline at end of file diff --git a/assets/js/13.6a579e8b.js b/assets/js/13.6a579e8b.js new file mode 100644 index 000000000..ab5f3b89c --- /dev/null +++ b/assets/js/13.6a579e8b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[13],{439:function(t,s,e){"use strict";e.r(s);var i=e(36),n=Object(i.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("p",[s("a",{attrs:{name:"v0.3.0"}})]),this._v(" "),s("h2",{attrs:{id:"v0-3-0-2022-03-02"}},[this._v("v0.3.0 (2022-03-02)")]),this._v(" "),s("h2",{attrs:{id:"features"}},[this._v("Features")]),this._v(" "),s("p",[this._v("引入 ci")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/14.fa863532.js b/assets/js/14.fa863532.js new file mode 100644 index 000000000..c68d1e845 --- /dev/null +++ b/assets/js/14.fa863532.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[14],{441:function(t,r,e){"use strict";e.r(r);var E=e(36),a=Object(E.a)({},(function(){var t=this,r=t.$createElement,e=t._self._c||r;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"runtime"}},[t._v("runtime")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"./%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95"}},[t._v("三色 gc 算法")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D"}},[t._v("堆内存分配")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86"}},[t._v("栈内存管理")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7"}},[t._v("系统监控")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./gmp"}},[t._v("G:M:P")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./%E5%AE%9A%E6%97%B6%E5%99%A8"}},[t._v("定时器")])]),t._v(" "),e("li",[e("a",{attrs:{href:"./netpool"}},[t._v("netpool")])])])])}),[],!1,null,null,null);r.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/15.ccbbdb7a.js b/assets/js/15.ccbbdb7a.js new file mode 100644 index 000000000..c5f08e61b --- /dev/null +++ b/assets/js/15.ccbbdb7a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[15],{442:function(t,i,e){"use strict";e.r(i);var n=e(36),s=Object(n.a)({},(function(){var t=this,i=t.$createElement,e=t._self._c||i;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"g-m-p"}},[t._v("G:M:P")]),t._v(" "),e("h2",{attrs:{id:"参考文章"}},[t._v("参考文章")]),t._v(" "),e("ul",[e("li",[t._v("https://mp.weixin.qq.com/s/iAy9ReQhnmCYUFvwYroGPA")]),t._v(" "),e("li",[t._v("https://www.bilibili.com/video/BV19r4y1w7Nx/")])])])}),[],!1,null,null,null);i.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/16.d5f6c328.js b/assets/js/16.d5f6c328.js new file mode 100644 index 000000000..12be6c880 --- /dev/null +++ b/assets/js/16.d5f6c328.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{444:function(t,s,i){"use strict";i.r(s);var e=i(36),n=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"go-语言网络模型"}},[this._v("go 语言网络模型")]),this._v(" "),s("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),s("ul",[s("li",[this._v("https://mp.weixin.qq.com/s/jGrPM0UgqjZ10cXafoC0wQ")])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/17.1312d121.js b/assets/js/17.1312d121.js new file mode 100644 index 000000000..6233477bf --- /dev/null +++ b/assets/js/17.1312d121.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[17],{443:function(t,s,e){"use strict";e.r(s);var n=e(36),i=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),s("ul",[s("li",[this._v("https://draveness.me/golang/")])])])}),[],!1,null,null,null);s.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/18.4b8a1599.js b/assets/js/18.4b8a1599.js new file mode 100644 index 000000000..df2dce647 --- /dev/null +++ b/assets/js/18.4b8a1599.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[18],{445:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/19.5ed73af4.js b/assets/js/19.5ed73af4.js new file mode 100644 index 000000000..6d96732b4 --- /dev/null +++ b/assets/js/19.5ed73af4.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{446:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/2.5c331e53.js b/assets/js/2.5c331e53.js new file mode 100644 index 000000000..a51712ce6 --- /dev/null +++ b/assets/js/2.5c331e53.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{376:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"g",(function(){return l})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return h})),n.d(e,"e",(function(){return p})),n.d(e,"k",(function(){return f})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return v})),n.d(e,"j",(function(){return m}));n(32),n(97),n(377),n(127),n(209),n(206),n(96),n(99),n(10),n(100),n(45),n(130),n(204);var i=/#.*$/,r=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function u(t){return s.test(t)}function l(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function h(t){if(u(t))return t;var e=t.match(i),n=e?e[0]:"",r=o(t);return a.test(r)?t:r+".html"+n}function p(t,e){var n=decodeURIComponent(t.hash),r=function(t){var e=t.match(i);if(e)return e[0]}(e);return(!r||n===r)&&o(t.path)===o(e)}function f(t,e,n){if(u(e))return{type:"external",path:e};n&&(e=function(t,e,n){var i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;var r=e.split("/");n&&r[r.length-1]||r.pop();for(var a=t.replace(/^\//,"").split("/"),s=0;s<a.length;s++){var o=a[s];".."===o?r.pop():"."!==o&&r.push(o)}""!==r[0]&&r.unshift("");return r.join("/")}(e,n));for(var i=o(e),r=0;r<t.length;r++)if(o(t[r].regularPath)===i)return Object.assign({},t[r],{type:"page",path:h(t[r].path)});return console.error('[vuepress] No matching page found for sidebar item "'.concat(e,'"')),{}}function d(t,e,n,i){var r=n.pages,a=n.themeConfig,s=i&&a.locales&&a.locales[i]||a;if("auto"===(t.frontmatter.sidebar||s.sidebar||a.sidebar))return g(t);var o=s.sidebar||a.sidebar;if(o){var u=function(t,e){if(Array.isArray(e))return{base:"/",config:e};for(var n in e)if(0===(i=t,/(\.html|\/)$/.test(i)?i:i+"/").indexOf(encodeURI(n)))return{base:n,config:e[n]};var i;return{}}(e,o),l=u.base,c=u.config;return"auto"===c?g(t):c?c.map((function(t){return function t(e,n,i){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1;if("string"==typeof e)return f(n,e,i);if(Array.isArray(e))return Object.assign(f(n,e[0],i),{title:e[1]});var a=e.children||[];return 0===a.length&&e.path?Object.assign(f(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map((function(e){return t(e,n,i,r+1)})),collapsable:!1!==e.collapsable}}(t,r,l)})):[]}return[]}function g(t){var e=v(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map((function(e){return{type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}}))}]}function v(t){var e;return(t=t.map((function(t){return Object.assign({},t)}))).forEach((function(t){2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)})),t.filter((function(t){return 2===t.level}))}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},377:function(t,e,n){"use strict";var i=n(6),r=n(137),a=n(11),s=n(69),o=n(15),u=n(25),l=n(46),c=n(138),h=n(139);r("match",(function(t,e,n){return[function(e){var n=u(this),r=null==e?void 0:l(e,t);return r?i(r,e,n):new RegExp(e)[t](o(n))},function(t){var i=a(this),r=o(t),u=n(e,i,r);if(u.done)return u.value;if(!i.global)return h(i,r);var l=i.unicode;i.lastIndex=0;for(var p,f=[],d=0;null!==(p=h(i,r));){var g=o(p[0]);f[d]=g,""===g&&(i.lastIndex=c(r,s(i.lastIndex),l)),d++}return 0===d?null:f}]}))},378:function(t,e,n){},379:function(t,e,n){"use strict";var i=n(1),r=n(207).trim;i({target:"String",proto:!0,forced:n(410)("trim")},{trim:function(){return r(this)}})},380:function(t,e,n){var i=n(7),r=n(0),a=n(2),s=n(101),o=n(133),u=n(20),l=n(47).f,c=n(33),h=n(135),p=n(15),f=n(381),d=n(131),g=n(212),v=n(14),m=n(3),b=n(9),k=n(37).enforce,_=n(211),x=n(5),C=n(205),y=n(214),$=x("match"),L=r.RegExp,w=L.prototype,O=r.SyntaxError,S=a(w.exec),I=a("".charAt),E=a("".replace),j=a("".indexOf),T=a("".slice),R=/^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/,A=/a/g,N=/a/g,P=new L(A)!==A,D=d.MISSED_STICKY,U=d.UNSUPPORTED_Y,H=i&&(!P||D||C||y||m((function(){return N[$]=!1,L(A)!=A||L(N)==N||"/a/i"!=L(A,"i")})));if(s("RegExp",H)){for(var W=function(t,e){var n,i,r,a,s,l,d=c(w,this),g=h(t),v=void 0===e,m=[],_=t;if(!d&&g&&v&&t.constructor===W)return t;if((g||c(w,t))&&(t=t.source,v&&(e=f(_))),t=void 0===t?"":p(t),e=void 0===e?"":p(e),_=t,C&&"dotAll"in A&&(i=!!e&&j(e,"s")>-1)&&(e=E(e,/s/g,"")),n=e,D&&"sticky"in A&&(r=!!e&&j(e,"y")>-1)&&U&&(e=E(e,/y/g,"")),y&&(t=(a=function(t){for(var e,n=t.length,i=0,r="",a=[],s={},o=!1,u=!1,l=0,c="";i<=n;i++){if("\\"===(e=I(t,i)))e+=I(t,++i);else if("]"===e)o=!1;else if(!o)switch(!0){case"["===e:o=!0;break;case"("===e:S(R,T(t,i+1))&&(i+=2,u=!0),r+=e,l++;continue;case">"===e&&u:if(""===c||b(s,c))throw new O("Invalid capture group name");s[c]=!0,a[a.length]=[c,l],u=!1,c="";continue}u?c+=e:r+=e}return[r,a]}(t))[0],m=a[1]),s=o(L(t,e),d?this:w,W),(i||r||m.length)&&(l=k(s),i&&(l.dotAll=!0,l.raw=W(function(t){for(var e,n=t.length,i=0,r="",a=!1;i<=n;i++)"\\"!==(e=I(t,i))?a||"."!==e?("["===e?a=!0:"]"===e&&(a=!1),r+=e):r+="[\\s\\S]":r+=e+I(t,++i);return r}(t),n)),r&&(l.sticky=!0),m.length&&(l.groups=m)),t!==_)try{u(s,"source",""===_?"(?:)":_)}catch(t){}return s},G=l(L),B=0;G.length>B;)g(W,L,G[B++]);w.constructor=W,W.prototype=w,v(r,"RegExp",W,{constructor:!0})}_("RegExp")},381:function(t,e,n){var i=n(6),r=n(9),a=n(33),s=n(213),o=RegExp.prototype;t.exports=function(t){var e=t.flags;return void 0!==e||"flags"in o||r(t,"flags")||!a(o,t)?e:i(s,t)}},382:function(t,e,n){var i=n(0),r=n(7),a=n(205),s=n(26),o=n(383),u=n(37).get,l=RegExp.prototype,c=i.TypeError;r&&a&&o(l,"dotAll",{configurable:!0,get:function(){if(this!==l){if("RegExp"===s(this))return!!u(this).dotAll;throw c("Incompatible receiver, RegExp required")}}})},383:function(t,e,n){var i=n(210),r=n(12);t.exports=function(t,e,n){return n.get&&i(n.get,e,{getter:!0}),n.set&&i(n.set,e,{setter:!0}),r.f(t,e,n)}},384:function(t,e,n){var i=n(0),r=n(7),a=n(131).MISSED_STICKY,s=n(26),o=n(383),u=n(37).get,l=RegExp.prototype,c=i.TypeError;r&&a&&o(l,"sticky",{configurable:!0,get:function(){if(this!==l){if("RegExp"===s(this))return!!u(this).sticky;throw c("Incompatible receiver, RegExp required")}}})},385:function(t,e,n){"use strict";var i=n(98).PROPER,r=n(14),a=n(11),s=n(15),o=n(3),u=n(381),l=RegExp.prototype.toString,c=o((function(){return"/a/b"!=l.call({source:"a",flags:"b"})})),h=i&&"toString"!=l.name;(c||h)&&r(RegExp.prototype,"toString",(function(){var t=a(this);return"/"+s(t.source)+"/"+s(u(t))}),{unsafe:!0})},386:function(t,e,n){},387:function(t,e,n){},388:function(t,e,n){},389:function(t,e,n){},390:function(t,e,n){},391:function(t,e,n){},392:function(t,e){t.exports=function(t){return null==t}},393:function(t,e,n){},394:function(t,e,n){},395:function(t,e,n){},396:function(t,e,n){},397:function(t,e,n){},398:function(t,e,n){},402:function(t,e,n){"use strict";n.r(e);n(128),n(10);var i=n(376),r={name:"SidebarGroup",components:{DropdownTransition:n(403).a},props:["item","open","collapsable","depth"],beforeCreate:function(){this.$options.components.SidebarLinks=n(402).default},methods:{isActive:i.e}},a=(n(422),n(36)),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?n("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):n("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[n("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?n("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),n("DropdownTransition",[t.open||!t.collapsable?n("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,"initial-open-group-index":t.item.initialOpenGroupIndex,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null).exports;n(423),n(32),n(127),n(96);function o(t,e,n,i,r){var a={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:i,"sidebar-link":!0}};return r>2&&(a.style={"padding-left":r+"rem"}),t("RouterLink",a,n)}function u(t,e,n,r,a){var s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1;return!e||s>a?null:t("ul",{class:"sidebar-sub-headers"},e.map((function(e){var l=Object(i.e)(r,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[o(t,n+"#"+e.slug,e.title,l,e.level-1),u(t,e.children,n,r,a,s+1)])})))}var l={functional:!0,props:["item","sidebarDepth"],render:function(t,e){var n=e.parent,r=n.$page,a=(n.$site,n.$route),s=n.$themeConfig,l=n.$themeLocaleConfig,c=e.props,h=c.item,p=c.sidebarDepth,f=Object(i.e)(a,h.path),d="auto"===h.type?f||h.children.some((function(t){return Object(i.e)(a,h.basePath+"#"+t.slug)})):f,g="external"===h.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,h.path,h.title||h.path):o(t,h.path,h.title||h.path,d),v=[r.frontmatter.sidebarDepth,p,l.sidebarDepth,s.sidebarDepth,1].find((function(t){return void 0!==t})),m=l.displayAllHeaders||s.displayAllHeaders;return"auto"===h.type?[g,u(t,h.children,h.basePath,a,v)]:(d||m)&&h.headers&&!i.d.test(h.path)?[g,u(t,Object(i.c)(h.headers),h.path,a,v)]:g}};n(424);function c(t,e){if("group"===e.type){var n=e.path&&Object(i.e)(t,e.path),r=e.children.some((function(e){return"group"===e.type?c(t,e):"page"===e.type&&Object(i.e)(t,e.path)}));return n||r}return!1}var h={name:"SidebarLinks",components:{SidebarGroup:s,SidebarLink:Object(a.a)(l,void 0,void 0,!1,null,null,null).exports},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data:function(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route:function(){this.refreshIndex()}},created:function(){this.refreshIndex()},methods:{refreshIndex:function(){var t=function(t,e){for(var n=0;n<e.length;n++){var i=e[n];if(c(t,i))return n}return-1}(this.$route,this.items);t>-1&&(this.openGroupIndex=t)},toggleGroup:function(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive:function(t){return Object(i.e)(this.$route,t.regularPath)}}},p=Object(a.a)(h,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.items.length?n("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(e,i){return n("li",{key:i},["group"===e.type?n("SidebarGroup",{attrs:{item:e,open:i===t.openGroupIndex,collapsable:e.collapsable||e.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(i)}}}):n("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:e}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=p.exports},403:function(t,e,n){"use strict";var i={name:"DropdownTransition",methods:{setHeight:function(t){t.style.height=t.scrollHeight+"px"},unsetHeight:function(t){t.style.height=""}}},r=(n(414),n(36)),a=Object(r.a)(i,(function(){var t=this.$createElement;return(this._self._c||t)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.a=a.exports},404:function(t,e,n){"use strict";var i=n(1),r=n(405);i({target:"String",proto:!0,forced:n(406)("link")},{link:function(t){return r(this,"a","href",t)}})},405:function(t,e,n){var i=n(2),r=n(25),a=n(15),s=/"/g,o=i("".replace);t.exports=function(t,e,n,i){var u=a(r(t)),l="<"+e;return""!==n&&(l+=" "+n+'="'+o(a(i),s,""")+'"'),l+">"+u+"</"+e+">"}},406:function(t,e,n){var i=n(3);t.exports=function(t){return i((function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}))}},407:function(t,e,n){"use strict";n(378)},408:function(t,e,n){var i=n(1),r=n(409);i({global:!0,forced:parseInt!=r},{parseInt:r})},409:function(t,e,n){var i=n(0),r=n(3),a=n(2),s=n(15),o=n(207).trim,u=n(208),l=i.parseInt,c=i.Symbol,h=c&&c.iterator,p=/^[+-]?0x/i,f=a(p.exec),d=8!==l(u+"08")||22!==l(u+"0x16")||h&&!r((function(){l(Object(h))}));t.exports=d?function(t,e){var n=o(s(t));return l(n,e>>>0||(f(p,n)?16:10))}:l},410:function(t,e,n){var i=n(98).PROPER,r=n(3),a=n(208);t.exports=function(t){return r((function(){return!!a[t]()||" "!==" "[t]()||i&&a[t].name!==t}))}},411:function(t,e,n){"use strict";var i,r=n(1),a=n(2),s=n(34).f,o=n(69),u=n(15),l=n(134),c=n(25),h=n(136),p=n(16),f=a("".endsWith),d=a("".slice),g=Math.min,v=h("endsWith");r({target:"String",proto:!0,forced:!!(p||v||(i=s(String.prototype,"endsWith"),!i||i.writable))&&!v},{endsWith:function(t){var e=u(c(this));l(t);var n=arguments.length>1?arguments[1]:void 0,i=e.length,r=void 0===n?i:g(o(n),i),a=u(t);return f?f(e,a,r):d(e,r-a.length,r)===a}})},412:function(t,e,n){"use strict";n(386)},413:function(t,e,n){"use strict";n(387)},414:function(t,e,n){"use strict";n(388)},415:function(t,e,n){"use strict";n(389)},416:function(t,e,n){"use strict";n(390)},417:function(t,e,n){"use strict";n(391)},418:function(t,e,n){"use strict";n(393)},419:function(t,e,n){var i=n(49),r=n(21),a=n(38);t.exports=function(t){return"string"==typeof t||!r(t)&&a(t)&&"[object String]"==i(t)}},420:function(t,e,n){"use strict";n(394)},421:function(t,e,n){"use strict";n(395)},422:function(t,e,n){"use strict";n(396)},423:function(t,e,n){"use strict";var i=n(1),r=n(48).find,a=n(132),s=!0;"find"in[]&&Array(1).find((function(){s=!1})),i({target:"Array",proto:!0,forced:s},{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),a("find")},424:function(t,e,n){"use strict";n(397)},425:function(t,e,n){"use strict";n(398)},435:function(t,e,n){"use strict";n.r(e);n(404),n(128),n(10),n(129);var i=n(376),r={name:"NavLink",props:{item:{required:!0}},computed:{link:function(){return Object(i.b)(this.item.link)},exact:function(){var t=this;return this.$site.locales?Object.keys(this.$site.locales).some((function(e){return e===t.link})):"/"===this.link},isNonHttpURI:function(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget:function(){return"_blank"===this.target},isInternal:function(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target:function(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel:function(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction:function(){this.$emit("focusout")}}},a=n(36),s=Object(a.a)(r,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.isInternal?n("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):n("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?n("OutboundLink"):t._e()],1)}),[],!1,null,null,null).exports,o={name:"Home",components:{NavLink:s},computed:{data:function(){return this.$page.frontmatter},actionLink:function(){return{link:this.data.actionLink,text:this.data.actionText}}}},u=(n(407),Object(a.a)(o,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("main",{staticClass:"home",attrs:{"aria-labelledby":null!==t.data.heroText?"main-title":null}},[n("header",{staticClass:"hero"},[t.data.heroImage?n("img",{attrs:{src:t.$withBase(t.data.heroImage),alt:t.data.heroAlt||"hero"}}):t._e(),t._v(" "),null!==t.data.heroText?n("h1",{attrs:{id:"main-title"}},[t._v("\n "+t._s(t.data.heroText||t.$title||"Hello")+"\n ")]):t._e(),t._v(" "),null!==t.data.tagline?n("p",{staticClass:"description"},[t._v("\n "+t._s(t.data.tagline||t.$description||"Welcome to your VuePress site")+"\n ")]):t._e(),t._v(" "),t.data.actionText&&t.data.actionLink?n("p",{staticClass:"action"},[n("NavLink",{staticClass:"action-button",attrs:{item:t.actionLink}})],1):t._e()]),t._v(" "),t.data.features&&t.data.features.length?n("div",{staticClass:"features"},t._l(t.data.features,(function(e,i){return n("div",{key:i,staticClass:"feature"},[n("h2",[t._v(t._s(e.title))]),t._v(" "),n("p",[t._v(t._s(e.details))])])})),0):t._e(),t._v(" "),n("Content",{staticClass:"theme-default-content custom"}),t._v(" "),t.data.footer?n("div",{staticClass:"footer"},[t._v("\n "+t._s(t.data.footer)+"\n ")]):n("Content",{staticClass:"footer",attrs:{"slot-key":"footer"}})],1)}),[],!1,null,null,null).exports),l=(n(408),n(379),n(204),n(130),n(45),n(32),n(377),n(215),n(216),n(206),n(97),n(380),n(382),n(384),n(385),n(96),n(209),n(127),n(411),n(218)),c=n.n(l),h=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,i=c()(e,"title","");return c()(e,"frontmatter.tags")&&(i+=" ".concat(e.frontmatter.tags.join(" "))),n&&(i+=" ".concat(n)),p(t,i)},p=function(t,e){var n=function(t){return t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")},i=new RegExp("[^\0-]"),r=t.split(/\s+/g).map((function(t){return t.trim()})).filter((function(t){return!!t}));if(i.test(t))return r.some((function(t){return e.toLowerCase().indexOf(t)>-1}));var a=t.endsWith(" ");return new RegExp(r.map((function(t,e){return r.length!==e+1||a?"(?=.*\\b".concat(n(t),"\\b)"):"(?=.*\\b".concat(n(t),")")})).join("")+".+","gi").test(e)},f={name:"SearchBox",data:function(){return{query:"",focused:!1,focusIndex:0,placeholder:void 0}},computed:{showSuggestions:function(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions:function(){var t=this.query.trim().toLowerCase();if(t){for(var e=this.$site.pages,n=this.$site.themeConfig.searchMaxSuggestions||5,i=this.$localePath,r=[],a=0;a<e.length&&!(r.length>=n);a++){var s=e[a];if(this.getPageLocalePath(s)===i&&this.isSearchable(s))if(h(t,s))r.push(s);else if(s.headers)for(var o=0;o<s.headers.length&&!(r.length>=n);o++){var u=s.headers[o];u.title&&h(t,s,u.title)&&r.push(Object.assign({},s,{path:s.path+"#"+u.slug,header:u}))}}return r}},alignRight:function(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted:function(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy:function(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath:function(t){for(var e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable:function(t){var e=null;return null===e||(e=Array.isArray(e)?e:new Array(e)).filter((function(e){return t.path.match(e)})).length>0},onHotkey:function(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp:function(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown:function(){this.showSuggestions&&(this.focusIndex<this.suggestions.length-1?this.focusIndex++:this.focusIndex=0)},go:function(t){this.showSuggestions&&(this.$router.push(this.suggestions[t].path),this.query="",this.focusIndex=0)},focus:function(t){this.focusIndex=t},unfocus:function(){this.focusIndex=-1}}},d=(n(412),Object(a.a)(f,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"search-box"},[n("input",{ref:"input",class:{focused:t.focused},attrs:{"aria-label":"Search",placeholder:t.placeholder,autocomplete:"off",spellcheck:"false"},domProps:{value:t.query},on:{input:function(e){t.query=e.target.value},focus:function(e){t.focused=!0},blur:function(e){t.focused=!1},keyup:[function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"enter",13,e.key,"Enter")?null:t.go(t.focusIndex)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"up",38,e.key,["Up","ArrowUp"])?null:t.onUp.apply(null,arguments)},function(e){return!e.type.indexOf("key")&&t._k(e.keyCode,"down",40,e.key,["Down","ArrowDown"])?null:t.onDown.apply(null,arguments)}]}}),t._v(" "),t.showSuggestions?n("ul",{staticClass:"suggestions",class:{"align-right":t.alignRight},on:{mouseleave:t.unfocus}},t._l(t.suggestions,(function(e,i){return n("li",{key:i,staticClass:"suggestion",class:{focused:i===t.focusIndex},on:{mousedown:function(e){return t.go(i)},mouseenter:function(e){return t.focus(i)}}},[n("a",{attrs:{href:e.path},on:{click:function(t){t.preventDefault()}}},[n("span",{staticClass:"page-title"},[t._v(t._s(e.title||e.path))]),t._v(" "),e.header?n("span",{staticClass:"header"},[t._v("> "+t._s(e.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports),g=(n(413),Object(a.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"sidebar-button",on:{click:function(e){return t.$emit("toggle-sidebar")}}},[n("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[n("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null).exports),v=n(67),m=(n(217),n(403)),b=n(219),k=n.n(b),_={name:"DropdownLink",components:{NavLink:s,DropdownTransition:m.a},props:{item:{required:!0}},data:function(){return{open:!1}},computed:{dropdownAriaLabel:function(){return this.item.ariaLabel||this.item.text}},watch:{$route:function(){this.open=!1}},methods:{setOpen:function(t){this.open=t},isLastItemOfArray:function(t,e){return k()(e)===t},handleDropdown:function(){0===event.detail&&this.setOpen(!this.open)}}},x=(n(415),{name:"NavLinks",components:{NavLink:s,DropdownLink:Object(a.a)(_,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[n("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow down"})]),t._v(" "),n("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[n("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),n("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),n("DropdownTransition",[n("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(e,i){return n("li",{key:e.link||i,staticClass:"dropdown-item"},["links"===e.type?n("h4",[t._v("\n "+t._s(e.text)+"\n ")]):t._e(),t._v(" "),"links"===e.type?n("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(e.items,(function(i){return n("li",{key:i.link,staticClass:"dropdown-subitem"},[n("NavLink",{attrs:{item:i},on:{focusout:function(n){t.isLastItemOfArray(i,e.items)&&t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0):n("NavLink",{attrs:{item:e},on:{focusout:function(n){t.isLastItemOfArray(e,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null).exports},computed:{userNav:function(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav:function(){var t=this,e=this.$site.locales;if(e&&Object.keys(e).length>1){var n=this.$page.path,i=this.$router.options.routes,r=this.$site.themeConfig.locales||{},a={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(e).map((function(a){var s,o=e[a],u=r[a]&&r[a].label||o.lang;return o.lang===t.$lang?s=n:(s=n.replace(t.$localeConfig.path,a),i.some((function(t){return t.path===s}))||(s=a)),{text:u,link:s}}))};return[].concat(Object(v.a)(this.userNav),[a])}return this.userNav},userLinks:function(){return(this.nav||[]).map((function(t){return Object.assign(Object(i.j)(t),{items:(t.items||[]).map(i.j)})}))},repoLink:function(){var t=this.$site.themeConfig.repo;return t?/^https?:/.test(t)?t:"https://github.com/".concat(t):null},repoLabel:function(){if(this.repoLink){if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;for(var t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"],n=0;n<e.length;n++){var i=e[n];if(new RegExp(i,"i").test(t))return i}return"Source"}}}}),C=(n(416),Object(a.a)(x,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.userLinks.length||t.repoLink?n("nav",{staticClass:"nav-links"},[t._l(t.userLinks,(function(t){return n("div",{key:t.link,staticClass:"nav-item"},["links"===t.type?n("DropdownLink",{attrs:{item:t}}):n("NavLink",{attrs:{item:t}})],1)})),t._v(" "),t.repoLink?n("a",{staticClass:"repo-link",attrs:{href:t.repoLink,target:"_blank",rel:"noopener noreferrer"}},[t._v("\n "+t._s(t.repoLabel)+"\n "),n("OutboundLink")],1):t._e()],2):t._e()}),[],!1,null,null,null).exports);function y(t,e){return t.ownerDocument.defaultView.getComputedStyle(t,null)[e]}var $={name:"Navbar",components:{SidebarButton:g,NavLinks:C,SearchBox:d,AlgoliaSearchBox:{}},data:function(){return{linksWrapMaxWidth:null}},computed:{algolia:function(){return this.$themeLocaleConfig.algolia||this.$site.themeConfig.algolia||{}},isAlgoliaSearch:function(){return this.algolia&&this.algolia.apiKey&&this.algolia.indexName}},mounted:function(){var t=this,e=parseInt(y(this.$el,"paddingLeft"))+parseInt(y(this.$el,"paddingRight")),n=function(){document.documentElement.clientWidth<719?t.linksWrapMaxWidth=null:t.linksWrapMaxWidth=t.$el.offsetWidth-e-(t.$refs.siteName&&t.$refs.siteName.offsetWidth||0)};n(),window.addEventListener("resize",n,!1)}},L=(n(417),Object(a.a)($,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("header",{staticClass:"navbar"},[n("SidebarButton",{on:{"toggle-sidebar":function(e){return t.$emit("toggle-sidebar")}}}),t._v(" "),n("RouterLink",{staticClass:"home-link",attrs:{to:t.$localePath}},[t.$site.themeConfig.logo?n("img",{staticClass:"logo",attrs:{src:t.$withBase(t.$site.themeConfig.logo),alt:t.$siteTitle}}):t._e(),t._v(" "),t.$siteTitle?n("span",{ref:"siteName",staticClass:"site-name",class:{"can-hide":t.$site.themeConfig.logo}},[t._v(t._s(t.$siteTitle))]):t._e()]),t._v(" "),n("div",{staticClass:"links",style:t.linksWrapMaxWidth?{"max-width":t.linksWrapMaxWidth+"px"}:{}},[t.isAlgoliaSearch?n("AlgoliaSearchBox",{attrs:{options:t.algolia}}):!1!==t.$site.themeConfig.search&&!1!==t.$page.frontmatter.search?n("SearchBox"):t._e(),t._v(" "),n("NavLinks",{staticClass:"can-hide"})],1)],1)}),[],!1,null,null,null).exports),w=n(392),O=n.n(w),S={name:"PageEdit",computed:{lastUpdated:function(){return this.$page.lastUpdated},lastUpdatedText:function(){return"string"==typeof this.$themeLocaleConfig.lastUpdated?this.$themeLocaleConfig.lastUpdated:"string"==typeof this.$site.themeConfig.lastUpdated?this.$site.themeConfig.lastUpdated:"Last Updated"},editLink:function(){var t=O()(this.$page.frontmatter.editLink)?this.$site.themeConfig.editLinks:this.$page.frontmatter.editLink,e=this.$site.themeConfig,n=e.repo,i=e.docsDir,r=void 0===i?"":i,a=e.docsBranch,s=void 0===a?"master":a,o=e.docsRepo,u=void 0===o?n:o;return t&&u&&this.$page.relativePath?this.createEditLink(n,u,r,s,this.$page.relativePath):null},editLinkText:function(){return this.$themeLocaleConfig.editLinkText||this.$site.themeConfig.editLinkText||"Edit this page"}},methods:{createEditLink:function(t,e,n,r,a){if(/bitbucket.org/.test(e))return e.replace(i.a,"")+"/src"+"/".concat(r,"/")+(n?n.replace(i.a,"")+"/":"")+a+"?mode=edit&spa=0&at=".concat(r,"&fileviewer=file-view-default");return/gitlab.com/.test(e)?e.replace(i.a,"")+"/-/edit"+"/".concat(r,"/")+(n?n.replace(i.a,"")+"/":"")+a:(i.i.test(e)?e:"https://github.com/".concat(e)).replace(i.a,"")+"/edit"+"/".concat(r,"/")+(n?n.replace(i.a,"")+"/":"")+a}}},I=(n(418),Object(a.a)(S,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("footer",{staticClass:"page-edit"},[t.editLink?n("div",{staticClass:"edit-link"},[n("a",{attrs:{href:t.editLink,target:"_blank",rel:"noopener noreferrer"}},[t._v(t._s(t.editLinkText))]),t._v(" "),n("OutboundLink")],1):t._e(),t._v(" "),t.lastUpdated?n("div",{staticClass:"last-updated"},[n("span",{staticClass:"prefix"},[t._v(t._s(t.lastUpdatedText)+":")]),t._v(" "),n("span",{staticClass:"time"},[t._v(t._s(t.lastUpdated))])]):t._e()])}),[],!1,null,null,null).exports),E=n(419),j=n.n(E),T={name:"PageNav",props:["sidebarItems"],computed:{prev:function(){return A(R.PREV,this)},next:function(){return A(R.NEXT,this)}}};var R={NEXT:{resolveLink:function(t,e){return N(t,e,1)},getThemeLinkConfig:function(t){return t.nextLinks},getPageLinkConfig:function(t){return t.frontmatter.next}},PREV:{resolveLink:function(t,e){return N(t,e,-1)},getThemeLinkConfig:function(t){return t.prevLinks},getPageLinkConfig:function(t){return t.frontmatter.prev}}};function A(t,e){var n=e.$themeConfig,r=e.$page,a=e.$route,s=e.$site,o=e.sidebarItems,u=t.resolveLink,l=t.getThemeLinkConfig,c=t.getPageLinkConfig,h=l(n),p=c(r),f=O()(p)?h:p;return!1===f?void 0:j()(f)?Object(i.k)(s.pages,f,a.path):u(r,o)}function N(t,e,n){var i=[];!function t(e,n){for(var i=0,r=e.length;i<r;i++)"group"===e[i].type?t(e[i].children||[],n):n.push(e[i])}(e,i);for(var r=0;r<i.length;r++){var a=i[r];if("page"===a.type&&a.path===decodeURIComponent(t.path))return i[r+n]}}var P=T,D=(n(420),{components:{PageEdit:I,PageNav:Object(a.a)(P,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return t.prev||t.next?n("div",{staticClass:"page-nav"},[n("p",{staticClass:"inner"},[t.prev?n("span",{staticClass:"prev"},[t._v("\n ←\n "),"external"===t.prev.type?n("a",{staticClass:"prev",attrs:{href:t.prev.path,target:"_blank",rel:"noopener noreferrer"}},[t._v("\n "+t._s(t.prev.title||t.prev.path)+"\n\n "),n("OutboundLink")],1):n("RouterLink",{staticClass:"prev",attrs:{to:t.prev.path}},[t._v("\n "+t._s(t.prev.title||t.prev.path)+"\n ")])],1):t._e(),t._v(" "),t.next?n("span",{staticClass:"next"},["external"===t.next.type?n("a",{attrs:{href:t.next.path,target:"_blank",rel:"noopener noreferrer"}},[t._v("\n "+t._s(t.next.title||t.next.path)+"\n\n "),n("OutboundLink")],1):n("RouterLink",{attrs:{to:t.next.path}},[t._v("\n "+t._s(t.next.title||t.next.path)+"\n ")]),t._v("\n →\n ")],1):t._e()])]):t._e()}),[],!1,null,null,null).exports},props:["sidebarItems"]}),U=(n(421),Object(a.a)(D,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("main",{staticClass:"page"},[t._t("top"),t._v(" "),n("Content",{staticClass:"theme-default-content"}),t._v(" "),n("PageEdit"),t._v(" "),n("PageNav",t._b({},"PageNav",{sidebarItems:t.sidebarItems},!1)),t._v(" "),t._t("bottom")],2)}),[],!1,null,null,null).exports),H={name:"Sidebar",components:{SidebarLinks:n(402).default,NavLinks:C},props:["items"]},W=(n(425),{name:"Layout",components:{Home:u,Page:U,Sidebar:Object(a.a)(H,(function(){var t=this.$createElement,e=this._self._c||t;return e("aside",{staticClass:"sidebar"},[e("NavLinks"),this._v(" "),this._t("top"),this._v(" "),e("SidebarLinks",{attrs:{depth:0,items:this.items}}),this._v(" "),this._t("bottom")],2)}),[],!1,null,null,null).exports,Navbar:L},data:function(){return{isSidebarOpen:!1}},computed:{shouldShowNavbar:function(){var t=this.$site.themeConfig;return!1!==this.$page.frontmatter.navbar&&!1!==t.navbar&&(this.$title||t.logo||t.repo||t.nav||this.$themeLocaleConfig.nav)},shouldShowSidebar:function(){var t=this.$page.frontmatter;return!t.home&&!1!==t.sidebar&&this.sidebarItems.length},sidebarItems:function(){return Object(i.l)(this.$page,this.$page.regularPath,this.$site,this.$localePath)},pageClasses:function(){var t=this.$page.frontmatter.pageClass;return[{"no-navbar":!this.shouldShowNavbar,"sidebar-open":this.isSidebarOpen,"no-sidebar":!this.shouldShowSidebar},t]}},mounted:function(){var t=this;this.$router.afterEach((function(){t.isSidebarOpen=!1}))},methods:{toggleSidebar:function(t){this.isSidebarOpen="boolean"==typeof t?t:!this.isSidebarOpen,this.$emit("toggle-sidebar",this.isSidebarOpen)},onTouchStart:function(t){this.touchStart={x:t.changedTouches[0].clientX,y:t.changedTouches[0].clientY}},onTouchEnd:function(t){var e=t.changedTouches[0].clientX-this.touchStart.x,n=t.changedTouches[0].clientY-this.touchStart.y;Math.abs(e)>Math.abs(n)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}}),G=Object(a.a)(W,(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?n("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),n("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),n("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t.$page.frontmatter.home?n("Home"):n("Page",{attrs:{"sidebar-items":t.sidebarItems},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("page-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("page-bottom")]},proxy:!0}],null,!0)})],1)}),[],!1,null,null,null);e.default=G.exports}}]); \ No newline at end of file diff --git a/assets/js/20.fea9a837.js b/assets/js/20.fea9a837.js new file mode 100644 index 000000000..6a2956ba4 --- /dev/null +++ b/assets/js/20.fea9a837.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{447:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/21.321b1448.js b/assets/js/21.321b1448.js new file mode 100644 index 000000000..6f5b835ce --- /dev/null +++ b/assets/js/21.321b1448.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[21],{448:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/22.e3bbafa7.js b/assets/js/22.e3bbafa7.js new file mode 100644 index 000000000..61c74a6cc --- /dev/null +++ b/assets/js/22.e3bbafa7.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{449:function(t,E,r){"use strict";r.r(E);var a=r(36),e=Object(a.a)({},(function(){var t=this,E=t.$createElement,r=t._self._c||E;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"基础"}},[t._v("基础")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"./%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E"}},[t._v("变量声明")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E"}},[t._v("常量声明")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E9%9B%B6%E5%80%BC"}},[t._v("零值")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F"}},[t._v("复合字面量")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B"}},[t._v("数字类型")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./slice"}},[t._v("slice")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./string"}},[t._v("string")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./map"}},[t._v("map")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95"}},[t._v("函数方法")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./interface"}},[t._v("interface")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5"}},[t._v("逻辑和判断语句")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%85%B3%E9%94%AE%E5%AD%97"}},[t._v("关键字")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E6%B3%9B%E5%9E%8B"}},[t._v("泛型")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9"}},[t._v("其他内容")])])])])}),[],!1,null,null,null);E.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/23.6633ca8a.js b/assets/js/23.6633ca8a.js new file mode 100644 index 000000000..56cc5fce3 --- /dev/null +++ b/assets/js/23.6633ca8a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[23],{450:function(t,s,n){"use strict";n.r(s);var a=n(36),e=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"hello-world"}},[t._v("hello world")]),t._v(" "),n("h2",{attrs:{id:"诞生背景"}},[t._v("诞生背景")]),t._v(" "),n("p",[t._v("Go 语言是 Google 的 Robert Griesemer,Rob Pike 和 Ken Thompson 于 2007 年开始设计开发的一门编程语言。Go 语言吸收了 C 语言的表达能力,并添加了像动态语言中的并发性等特性,目的是让编程更简单高效。")]),t._v(" "),n("h2",{attrs:{id:"语言哲学"}},[t._v("语言哲学")]),t._v(" "),n("p",[t._v("Go 语言编程哲学如下:")]),t._v(" "),n("ul",[n("li",[t._v("面向接口编程")]),t._v(" "),n("li",[t._v("组合替换继承")]),t._v(" "),n("li",[t._v("简单优于复杂")]),t._v(" "),n("li",[t._v("内置并发支持")])]),t._v(" "),n("h2",{attrs:{id:"语言特点"}},[t._v("语言特点")]),t._v(" "),n("p",[t._v("Go 语言的主要特点有:")]),t._v(" "),n("ul",[n("li",[t._v("语法简单,容易学习使用")]),t._v(" "),n("li",[t._v("编译非常迅速,执行速度较快")]),t._v(" "),n("li",[t._v("静态类型语言 - 变量和函数需要声明类型")]),t._v(" "),n("li",[t._v("垃圾回收 - 自动的内存管理,不需要手动释放内存")]),t._v(" "),n("li",[t._v("并发支持 - 原生支持 goroutine 和 channel")]),t._v(" "),n("li",[t._v("简洁规范 - 语法简单一致,容易阅读理解")]),t._v(" "),n("li",[t._v("代码风格统一 - 提供了标准的代码风格")])]),t._v(" "),n("h2",{attrs:{id:"安装-go"}},[t._v("安装 Go")]),t._v(" "),n("p",[t._v("要安装 Go 语言,可以去官网 https://go.dev 下载最新的安装包。")]),t._v(" "),n("p",[t._v("安装非常简单,一般直接使用默认设置即可完成安装。")]),t._v(" "),n("p",[t._v("安装完成后,可以使用 "),n("code",[t._v("go version")]),t._v(" 命令检查安装是否成功。")]),t._v(" "),n("h2",{attrs:{id:"hello-world-2"}},[t._v("hello world")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello World"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tch "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ch\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/24.edf743ad.js b/assets/js/24.edf743ad.js new file mode 100644 index 000000000..6cb46e82a --- /dev/null +++ b/assets/js/24.edf743ad.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{451:function(t,s,n){"use strict";n.r(s);var a=n(36),e=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"接口"}},[t._v("接口")]),t._v(" "),n("blockquote",[n("p",[t._v("有关泛型相关的约束内容均放置在"),n("a",{attrs:{href:"../%E6%B3%9B%E5%9E%8B"}},[t._v("泛型")]),t._v("这一章节,这里不再赘述")])]),t._v(" "),n("p",[t._v("重点内容前情提要")]),t._v(" "),n("ul",[n("li",[t._v("方法集合决定接口的实现")]),t._v(" "),n("li",[t._v("接口的嵌入")]),t._v(" "),n("li",[t._v("类型断言")]),t._v(" "),n("li",[t._v("接口类型的底层")]),t._v(" "),n("li",[t._v("如何判断接口类型的相等")]),t._v(" "),n("li",[t._v("论述 “nil error != nil” 的原因")]),t._v(" "),n("li",[t._v("小接口的意义")]),t._v(" "),n("li",[t._v("不可滥用空接口")]),t._v(" "),n("li",[t._v("接口作为程序水平组合的连接点,提供程序的可扩展性")]),t._v(" "),n("li",[t._v("接口提供程序的可测试性")]),t._v(" "),n("li",[t._v("接口的严格对比函数的宽松")])]),t._v(" "),n("p",[t._v("接口,go 语言提供的,用于抽象以及数据解耦的组件,"),n("strong",[t._v("在操作接口时,go 语言要求的严格程度远大于函数和方法。")])]),t._v(" "),n("p",[t._v("在 go1.18+ 中接口的概念从包含抽象的方法变成了类型,但是我们在外部可以操作的接口仍然只能是经典接口,不过经典接口是可以当做约束在内部使用的,不过官方不推荐经典接口当做一般约束那种使用方式。")]),t._v(" "),n("p",[t._v("go 语言为了区分,将传统接口称之为接口,将扩展的接口称之为约束,实际上传统接口是约束概念的子集。扩展的约束并不能在函数或者方法以及类型之外使用。")]),t._v(" "),n("p",[t._v("这一章我们只介绍经典接口的基本概念和使用方法。")]),t._v(" "),n("p",[t._v("接口具有静态语言和动态语言的共同特点。")]),t._v(" "),n("p",[t._v("静态类型特点:")]),t._v(" "),n("ul",[n("li",[t._v("接口可以作为类型:"),n("code",[t._v("var e error")])]),t._v(" "),n("li",[t._v("支持在编译期进行类型检查:在编译器期间会对右边的变量进行类型的检查,检查是否实现了接口定义的方法类型中的所有方法")])]),t._v(" "),n("p",[t._v("动态类型的特点:")]),t._v(" "),n("ul",[n("li",[t._v("在运行时可以对接口进行动态赋值")]),t._v(" "),n("li",[t._v("接口类型可以在运行时被赋予不同的动态类型变量,从而进行 “多态”")])]),t._v(" "),n("h2",{attrs:{id:"方法集合决定接口的实现"}},[t._v("方法集合决定接口的实现")]),t._v(" "),n("p",[t._v("通常,我们使用下面这种形式去完成接口的实现")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Writer "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BufferWrite "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvalue bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("BufferWrite"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们知道,go 语言规定,不可跨包去实现类型的方法,所以我们只讨论自定义的类型与接口之间的关系,首先抛出结论:松耦合关系。")]),t._v(" "),n("p",[t._v("go 语言使用一种叫做鸭子理论的方式去实现接口:只要实现了接口的方法 (go 泛型,go1.18+, 理论从方法改为了类型) 就算是实现了这个接口,这属于隐式接口实现。即:接口和它的实现者之间为正交关系。")]),t._v(" "),n("p",[t._v("通常来说,例如 es6,Java 等都是要显式的说明实现了哪个接口的,但是 go 不需要,它只需要实现方法即可,而且,它还可以实现多个接口,毕竟多实现几个方法就可以算是实现了这个接口。由此还可以推断出,go 可以多实现方法,而不会影响对接口的实现。")]),t._v(" "),n("p",[t._v("这里要说明一下,go 语言对于定义在指针类型上的变量有语法糖:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Writer "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" t Student\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" tp "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" w Writer \n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n\tw "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" t\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ✅")]),t._v("\n\tw "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tp\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们可以看到,get 和 set 分别是一个值类型和一个指针类型上实现的,这里我们的结论是:当实现接口时,"),n("strong",[t._v("类型的指针变量")]),t._v("在实现方法上可以包括"),n("em",[n("strong",[t._v("定义在类型指针上的方法以及定义在值类型上的方法***,但是")]),t._v("值类型变量")]),n("em",[t._v("只包含定义在")]),n("em",[t._v("值类型")]),t._v("*上的方法")]),t._v(" "),n("p",[t._v("这里是提示信息:")]),t._v(" "),n("div",{staticClass:"language-bash extra-class"},[n("pre",{pre:!0,attrs:{class:"language-bash"}},[n("code",[t._v("cannot use t "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("variable of "),n("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("type")]),t._v(" Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" as Writer value "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" assignment: Student does not implement Writer "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("method "),n("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("set")]),t._v(" has pointer receiver"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("通常来说,这不应该成为程序员的烦恼,所以想用谁就好好的定义在谁上面的方法即可,完全不会出错。")]),t._v(" "),n("h2",{attrs:{id:"接口嵌入"}},[t._v("接口嵌入")]),t._v(" "),n("h3",{attrs:{id:"在接口中嵌入接口类型"}},[t._v("在接口中嵌入接口类型")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Writer "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Error1 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" WriterError "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tWriter\n\tError1\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这样的组合就可以组合成一个新的接口,并且嵌入的接口还可以有方法上的交集,go 是不介意的 (go1.14+)。")]),t._v(" "),n("h3",{attrs:{id:"在结构体中嵌入接口类型"}},[t._v("在结构体中嵌入接口类型")]),t._v(" "),n("p",[t._v("在结构体中嵌入一个接口,就相当于实现了这个接口 (当然结构体的指针类型也实现了这个接口),拥有了它的方法,但是注意,拥有的是这种抽象方法,那么我们为什么要将一个接口类型嵌入到一个结构体中呢?")]),t._v(" "),n("p",[t._v("因为 go 语言规定,嵌入接口,结构体相当于实现了这些接口,这里注意,这里必须是直接嵌入,如果是接口类型作为变量类型的方式是不能拥有接口的方法的。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ✅")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A1 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tA\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A2 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tA A\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A3 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta A\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[n("em",[n("strong",[t._v("当结构体本身也实现了方法时,优先调用结构体的方法。")])])]),t._v(" "),n("p",[t._v("这个场景是这样的,在某个函数中,它的参数是一个接口类型,并且这个函数调用的只是这个接口类型的某个,或几个方法,并不是全部,那么我们作为结构体,想实现这个接口,又不想多实现额外的方法,那么这种方法就很好用了。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tBI\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BI "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果想调用被嵌入的接口的方法可以这么用,")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 我们知道调用直接嵌入的对象时候,变量名称默等于后面的类型名称,")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 看下面演示")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// var a A")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a.BI.get()")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b BI"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("注意上文提到了,接口中内嵌接口的时候,内嵌的接口方法可以重复,但是结构体中内嵌的接口,不允许出现方法重复的问题:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌ : ambiguous selector a.get")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tBI\n\tBI1\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BI "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BI1 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("err")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("不过,要想解决这个问题,我们只需要让结构体实现这种重复的方法即可,这样,优先级就提升到了结构体,接口的方法就不会被调用了。比如:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a A\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tBI\n\tBI1\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BI "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" BI1 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("err")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b BI"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b BI1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("下面让我们看一下,这种用法在单元测试场景中的应用")]),t._v(" "),n("p",[t._v("让我们描述一个场景:")]),t._v(" "),n("p",[t._v("有一个函数,它接受一个接口类型作为参数,我们要对它进行单元测试,而且我们要伪造一些数据。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数体")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("MaleCount")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s stmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresult"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Exec")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SELECT count(*) FROM exployee_tab WHERE gender=?"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 抽象接口")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" stmt "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tClose "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NumInput")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Exec")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("stmt "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("args "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Query")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("args "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Rows"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口相关的一些数据")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Result "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tCount "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r Result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Count"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Rows "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们可以看到,要想对这个 MaleCount 函数进行处理,那么一个实现了 stmt 接口的动态类型必不可少,但是我们并不需要所有的方法,仅仅需要 Exec 方法。")]),t._v(" "),n("p",[t._v("所以我们第一步就是设置一个 fake 类型,并且将接口内嵌来完成 “继承”。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" fakeStmtForMaleCount "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tstmt\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里实际上只是简写,")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//真正的测试要对smt和arg进行测试的")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f fakeStmtForMaleCount"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Exec")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("stmt "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("args "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" Result"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("当我们内嵌完成继承之后,我们相当于拥有了这些抽象方法,然后我们在这个接口体上自行实现 Exec,这样就可以将结构体的 Exec 优先级提前。")]),t._v(" "),n("p",[t._v("那么让我们开始使用虚假数据 "),n("code",[t._v("Result{1}")]),t._v(" 开始测试 MaleCount 函数")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("TestEmployeeMaleCount")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("testing"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("T"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfs "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fakeStmtForMaleCount"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("MaleCount")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"error is :"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"we want %d, actual is %d"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"匿名接口"}},[t._v("匿名接口")]),t._v(" "),n("p",[t._v("与普通命名接口不同,匿名接口没有类型名,只通过方法集来定义接口")]),t._v(" "),n("p",[t._v("匿名接口的作用主要有:")]),t._v(" "),n("ul",[n("li",[t._v("临时使用,不需要命名")]),t._v(" "),n("li",[t._v("作为参数或返回值,减少接口命名")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("doSomething")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("returnInterface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Foo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ...")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" x\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"类型断言"}},[t._v("类型断言")]),t._v(" "),n("p",[t._v("当使用空接口作为类型参数的时候,空接口已经充盈了一个动态类型,如果我们要将这个空接口类型转化为原来的类型就需要断言。")]),t._v(" "),n("h3",{attrs:{id:"常规的断言方式"}},[t._v("常规的断言方式:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a any\n\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 第二个参数 ok 变量可以省略")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// v := a.(int)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// fmt.Println(v)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"存在于-switch-中的断言方式"}},[t._v("存在于 switch 中的断言方式:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" f any\n\tf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"12"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (type)里面的type为固定用法,不能更改。")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" f"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NO"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"断言类型也可以是接口"}},[t._v("断言类型也可以是接口")]),t._v(" "),n("p",[t._v("断言中的类型不止是实际类型比如 int 比如一个具体的 struct,还能是接口类型,比如一个接口类型:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyAget "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("IsMyAget")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("ok"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v("e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("MyAget"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("ok"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这个函数的意义是这样的,接受一个 error 接口类型的对象,然后断言看它是否是 MyAget 接口类型。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Age "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvalue "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\te "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Age"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Age"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("IsMyAget")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Age"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"10"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"接口类型的底层"}},[t._v("接口类型的底层")]),t._v(" "),n("p",[t._v("这是接口的底层数据:")]),t._v(" "),n("p",[t._v("一般接口:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// interface")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" iface "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ttab "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("itab\n\tdata unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pointer\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("空接口:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// empty interface")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" eface "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t_type "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("_type\n\tdata unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pointer\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("data 表示的意思一样,值是动态类型的地址。我们比较 value 时,比较的是地址指向的数据是否相同而不是地址本身。")]),t._v(" "),n("p",[t._v("空接口并没有定义接口的方法,因此 "),n("code",[t._v("_type")]),t._v(" 定义的均为动态类型的元数据")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" _type "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tsize "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n\tptrdata "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n\thash "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v("\n\ttflag tflag\n\talign "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v("\n\tfieldalign "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v("\n\tkind "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v("\n\talg "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("typeAlg\n\tgcdata "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v("\n\tstr nameOff\n\tptrToThis typeOff\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("一般接口因为本身定义了方法,因此它需要定义自己的方法,以及动态类型的数据,因此它除了 "),n("code",[t._v("_type")]),t._v(" 外,还定义了 "),n("code",[t._v("interfacetype")]),t._v(" 用来存储自己定义的方法元数据。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" itab "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 非空接口本身的信息")]),t._v("\n\tinter "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("interfacetype\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 动态类型数据")]),t._v("\n\t_type "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("_type\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// _type.hash的copy,用于 switch 判断类型")]),t._v("\n\thash "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 动态类型已实现接口方法的调用地址数组")]),t._v("\n\tfun "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("注意这里的 fun 数组,这里定义的 "),n("code",[t._v("[1]uintptr")]),t._v(" 在实际使用时,可能不是 [1],这里的数据时可变的,如果是 2,就表示实现了两个方法。")]),t._v(" "),n("p",[t._v("原文的注释是这样的 "),n("code",[t._v("// variable sized. fun[0]==0 means _type does not implement inter.")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" interfacetype "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口本身的类型信息")]),t._v("\n\ttyp _type\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口所在的包路径")]),t._v("\n\tpkgpath name\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接口方法集合")]),t._v("\n\tmhdr "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("imethod\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("h2",{attrs:{id:"如何判断接口类型的相等"}},[t._v("如何判断接口类型的相等")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("当接口类型未被赋予动态类型时")])]),t._v(",它的两个字段,即:动态类型字段和动态类型 value 字段均为 nil,那么这个未初始化的接口变量就恒等于 "),n("code",[t._v("nil")])]),t._v(" "),n("p",[t._v("当接口类型被赋予了动态类型,那么如果判断这时候的接口类型,必须为类型相同以及值相同,接下来我们看一个案例:")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("两个非空非 nil 接口变量比较:")])])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("printNonEmptyInterface1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" T "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bad error"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("printNonEmptyInterface1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err1 "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 非空接口类型")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err1ptr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 非空接口类型")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err2 "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 非空接口类型")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err2ptr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 非空接口类型")]),t._v("\n\n err1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" T"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"eden"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n err1ptr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("T"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"eden"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n err2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" T"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"eden"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n err2ptr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("T"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"eden"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err2:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1 = err2:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" err2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1ptr:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err1ptr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err2ptr:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err2ptr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1ptr = err2ptr:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err1ptr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" err2ptr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// false")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("err1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x104c959a8")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x1400004c748")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nerr2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x104c959a8")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x1400004c728")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nerr1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" err2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\nerr1ptr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x104c95988")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x1400004c738")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nerr2ptr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x104c95988")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x1400004c758")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nerr1ptr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" err2ptr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n")])])]),n("blockquote",[n("p",[t._v("println,预定义函数,在编译期间,会由编译器根据要输出的参数的类型,将 println 替换为特定的函数,这些预定义函数定义在 "),n("a",{attrs:{href:"https://github.com/golang/go/blob/96d16803c2aae5407e99c2a1db79bb51d9e1c8da/src/runtime/print.go#L255",target:"_blank",rel:"noopener noreferrer"}},[t._v("runtime/print.go"),n("OutboundLink")],1),t._v(" 中,针对 eface 和 iface 的打印函数是:\n"),n("code",[t._v("go \tfunc printeface(e eface){ \t\tprint(e._type, e.data) \t}")]),t._v(" "),n("code",[t._v("go \tfunc printiface(i iface){ \t\tprint(i.tab, i.data) \t}")])])]),t._v(" "),n("p",[t._v("如代码所示,我们要判断的是,非空接口,并且已经实现了动态类型的两组接口类型,答案已经写在代码里了,即:"),n("code",[t._v("err1 == err2")]),t._v(" "),n("code",[t._v("err1ptr != err2ptr")])]),t._v(" "),n("p",[t._v("现在就让我们从源码出发来探究一下原因。")]),t._v(" "),n("p",[t._v("首先,我们知道"),n("strong",[t._v("类型相同以及值相同才是真的相等")]),t._v(",err1 和 err2 的动态类型均为 "),n("code",[t._v("T")]),t._v(",值也均为 "),n("code",[t._v('T{"eden"}')]),t._v(",所以他们相等;err1ptr,和 err2ptr 的类型均为 "),n("code",[t._v("*T")]),t._v(",值均为 "),n("code",[t._v('&T{"eden"}')]),t._v(",但是系统却判断他们不相等,从源码来看,二者的 "),n("code",[t._v("tab *itab")]),t._v(",因为动态类型的元数据相同,这个字段一致,所以类型一致,从第二个字段 data 来说,"),n("em",[n("strong",[t._v("data 存储了 "),n("code",[t._v('&T{"edent"}')]),t._v(" 的地址,这个地址指向的内容仍为地址")])]),t._v(",从内容上来说地址指向的地址值并不相同,所以这就可以解释为什么结果是 false 了。")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("接下来我们看一下两个空非 nil 接口类型的比较:")])])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a any\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b any\n\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x102f8aaa0,0x1400004c758)")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x102f8aaa0,0x1400004c748)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// false")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" S "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("根据源码所知,a 和 b 的 "),n("code",[t._v("_type")]),t._v(" 是完全相同的,然而地址指向的地址不相同,所以结果是 false,下面让我们稍微改动一下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a any\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b any\n\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x104422aa0,0x1400004c767)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x104422aa0,0x1400004c767)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" S "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这个时候你惊奇的发现,结果竟然是 true,这是为什么呢?不是说,地址指向的地址应该是不同的吗?nonono,并不是所有的情况都是那样,如果结果是空接口,那么空接口的所有变量指向的都是同一个地址,所以从结果上来说,data 其实地址是相同的,指向的是同一个数据,所以答案是 true。")]),t._v(" "),n("blockquote",[n("p",[t._v("在 Go 中,空数据结构 (比如 struct {}) 不占用任何内存空间,因此在创建空数据结构时,它们实际上是指向同一个地址的。这是因为在 Go 中,每个变量都需要分配内存空间,以便可以存储它们的值。但是,由于空结构体没有任何字段,因此它们不需要分配任何内存空间。因此,在创建空结构体时,它们实际上是指向同一个已经分配的零大小内存块的指针。")])]),t._v(" "),n("p",[n("em",[n("strong",[t._v("一个非空接口类型和一个空接口类型一定不相等吗?")])])]),t._v(" "),n("p",[t._v("如果你根据源码来看,第一个字段本身就不一样,肯定不相等了,但是 go 在比较相等时,比较的是 "),n("code",[t._v("_type")]),t._v(" 字段,并不是全部的 tab 数据,所以当两者字段中的 "),n("code",[t._v("_type")]),t._v(" 相同就表示类型相同:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a any "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b B "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x1040dfae0,0x1400004c760) ")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x1040e5a68,0x1400004c758)")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//true")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" S "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" B "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("S"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("所以从结果来看,_type 字段相同均为 S,data 也是一致的,所以答案是 true")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("nil 接口类型:")])])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" e "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a any\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x0,0x0)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x0,0x0)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("当一个接口是未给定动态类型的接口类型,它就是 nil 接口,那么它的类型和 data 值均为空,所以只要是 nil 接口,他们均相等,并且等于 nil。")]),t._v(" "),n("p",[t._v("最后说明一下,"),n("em",[n("strong",[t._v("当接口类型获取动态类型的时候,绝大多数情况下,会将动态类型的值复制,并且放置在一个新的内存空间里,所以原始数据跟接口类型的数据再无瓜葛,指针类型除外")])]),t._v(",不过为了节省空间,有一种情况,go 编译器就会放弃这个动作,并不会每次都重新分配。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" x any "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("34")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" y any "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" x\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" z any "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" x\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x1023343e0,0x10232c1b0)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x1023343e0,0x10232c1b0)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x1023343e0,0x10232c1b0)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("y"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("z"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("可以看到,go 判断,x y z 三个空接口类型的动态类型,类型均相同都是 int,并且 data 指向同一块内存地址。")]),t._v(" "),n("p",[t._v("非空接口也是一样:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a2 a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a1\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// \t(0x102791a48,0x1400004c758)")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x102791a48,0x1400004c758)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们如果想获取关于接口的内部实现细节,可以看一下这个"),n("a",{attrs:{href:"https://github.com/bigwhite/GoProgrammingFromBeginnerToMaster/blob/main/chapter5/sources/dumpinterface.go",target:"_blank",rel:"noopener noreferrer"}},[t._v("项目"),n("OutboundLink")],1),t._v(",可以输出内部的信息")]),t._v(" "),n("h2",{attrs:{id:"小接口的意义"}},[t._v("小接口的意义")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("接口越小,抽象程度越高,使用范围也就越大")])])]),t._v(" "),n("p",[t._v("一群飞禽走兽,我们可以给他们的行为抽象为 “飞行”,一群能游泳的动物我们可以给他们的行为抽象为 “游泳”。那么飞行和游泳涵盖的内容就会非常的多,使用范围就会很大,比如我们现在有一个函数,要求对所有能飞行的动物做出打印动作,那么众多飞行的动物就都可以使用这个函数。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\te1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"大鹅"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ty1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" y"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"老鹰"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// {大鹅} 他们的具体行为模式是: 大鹅慢慢的飞")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("PrintFlyer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// {老鹰} 他们的具体行为模式是: 老鹰迅速飞行")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("PrintFlyer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("y1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Flyer "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fly")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("flyMod "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("PrintFlyer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f Flyer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"他们的具体行为模式是:"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fly")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 大鹅")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" e "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fly")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"大鹅慢慢的飞"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 老鹰")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" y "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("y"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fly")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"老鹰迅速飞行"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[n("em",[n("strong",[t._v("易于实现和测试")])])]),t._v(" "),n("p",[t._v("当接口的方法较少时,动态类型实现的方法就少了,必然容易实现以及容易测试。")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("高內聚,易于复合组合")])])]),t._v(" "),n("p",[t._v("我们抽象程度很高的接口,接口做的事情就很单一,比如飞行类的接口方法就是飞行,游泳动物的接口方法就只有游泳,当有会游泳也会飞行的动物时,我们只需要成立一个新的接口,将飞机类和游泳类的接口嵌入到新接口中就形成了一个全新的会飞行也会游泳的接口了。")]),t._v(" "),n("p",[t._v("如果一个接口涵盖了各种方法,那么当组合接口的时候,势必某些方法是被弃用的,所以综上所述,设置单一的,高内聚的方法是好的设计方案。")]),t._v(" "),n("h3",{attrs:{id:"如何设计小接口"}},[t._v("如何设计小接口")]),t._v(" "),n("ol",[n("li",[n("p",[t._v("先初步抽象出接口,这个时候可以有耦合,也可以不够高抽象,但是你得先定义出一个初步的接口出来,与此同时我们也得清楚,越是业务代码,抽象出一个高内聚的接口越难。")])]),t._v(" "),n("li",[n("p",[t._v("将大接口拆分为小接口,使用一段时间以后,我们会发现某些操作是可以单出被提取出来的,比如 io 包的 writer 和 reader,那么我们就可以把这个动作单独抽象出来。抽象的最高程度就是只有一个方法,这就非常的內聚了,可以说,这种程度的抽象在日常业务中还是相对比较难的,需要在长时间的使用中,慢慢摸索。")])])]),t._v(" "),n("p",[t._v("综上所述:现搞出一个能用的大接口再说,以后慢慢解耦,形成抽象程度更高的小接口。")]),t._v(" "),n("h2",{attrs:{id:"不可滥用空接口"}},[t._v("不可滥用空接口")]),t._v(" "),n("p",[t._v("空接口和非空接口最大的差异性其实不止是底层数据的不同,我们知道他们一个是 eface 一个是 iface,最重要的差距是,非空接口在编译期是会对接口变量要赋值的动态类型做编译检查的,也就是说会对实参进行检查,来确定他真的实现了这个接口定义的方法,这就是一次安全的保护屏障")]),t._v(" "),n("p",[t._v("与此同时,空接口并没有提供任何的保护屏障,他没有给编译器提供要检查的参数,因此我们说不要滥用空接口,因为它让你的代码缺少编译期间的安全检查屏障。")]),t._v(" "),n("p",[t._v("因为空接口的不安全性,我们可以得出一下结论")]),t._v(" "),n("ul",[n("li",[t._v("尽量不使用空接口")]),t._v(" "),n("li",[t._v("仅仅在未知类型的时候使用空接口")]),t._v(" "),n("li",[t._v("如果存在已知类型,并且类型较多的情况下,可以使用泛型编程")]),t._v(" "),n("li",[t._v("尽可能的抽象出带有方法的接口,并使用非空接口去作为函数参数")])]),t._v(" "),n("h2",{attrs:{id:"接口作为程序水平组合的连接点-提供程序的可扩展性"}},[t._v("接口作为程序水平组合的连接点,提供程序的可扩展性")]),t._v(" "),n("p",[t._v("在 go 语言中,一切皆组合,不过组合分为两种:")]),t._v(" "),n("ol",[n("li",[t._v("垂直组合,也就是类似接口的嵌入,结构体的嵌入,这种类型的组合被称之为垂直组合")]),t._v(" "),n("li",[t._v("水平组合,接口是水平组合的关键,当函数使用接口作为参数之后,实际参数可以无限制的水平扩展,只要我们传入的变量实现了这个接口")])]),t._v(" "),n("p",[t._v("垂直组合的三种方法:")]),t._v(" "),n("ul",[n("li",[t._v("往接口中嵌入接口实现新接口")]),t._v(" "),n("li",[t._v("往结构体中嵌入接口,实现接口体实现接口这个操作")]),t._v(" "),n("li",[t._v("往接口体中嵌入结构体,实现新的结构体这个操作")])]),t._v(" "),n("p",[t._v("水平组合的几种形式:")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("基本形式:")])])]),t._v(" "),n("p",[t._v("函数或者方法的参数是接口类型,接口类型作为连接点,将多个包的数据连接在一起。这种方法满足了 “依赖抽象”,“里氏替换原则”,“接口隔离” 等代码设计原则。")]),t._v(" "),n("blockquote",[n("p",[t._v("依赖抽象原则 (Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。("),n("strong",[t._v("接口本身就是一种抽象,高层模块和底层模块都依赖接口这个抽象组件组合在一起")]),t._v(")\n里氏替换原则 (Liskov Substitution Principle,LSP):子类对象应该能够替换掉程序中的任何父类对象。也就是说,在任何需要父类对象的地方,都可以使用子类对象来替换,而不会影响程序的正确性。("),n("strong",[t._v("接口动态类型将替换接口变量")]),t._v(")\n接口隔离原则 (Interface Segregation Principle,ISP):客户端不应该依赖于它不需要的接口。也就是说,一个类对另外一个类的依赖应该建立在最小的接口上。("),n("strong",[t._v("go 推崇最小接口模式")]),t._v(")")])]),t._v(" "),n("p",[t._v("这些原则都是为了提高代码的可维护性、可扩展性和可重用性。它们可以帮助我们设计出更加灵活、健壮和易于维护的代码。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Read")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r io"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Reader"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("cap")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Copy")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r io"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Writer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("src io"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Reader"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[n("em",[n("strong",[t._v("包裹函数:")])])]),t._v(" "),n("p",[t._v("函数或者方法,接受一个接口类型的参数,返回值也是这个接口类型。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LimitReader")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r Reader"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Reader"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Reade")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们可以定义类似的内容,来实现链式调用。例如")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token function"}},[t._v("CapReader")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("LimitReader")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AReader")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[n("em",[n("strong",[t._v("适配器函数类型:")])])]),t._v(" "),n("p",[t._v("将一个普通函数,转化为一个满足接口类型的动态类型:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ListenAndServe")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":80"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("greeting"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("greeting")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Handler "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ServeHTTP")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" HandlerFunc "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ServeHTTP")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("这就是适配器函数类型。http.HandlerFunc 就是这个适配器函数。")]),t._v(" "),n("p",[n("em",[n("strong",[t._v("中间件:")])])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\thttp"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ListenAndServe")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":80"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("aHandler")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("bHandler")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("greeting"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("具体的实现过程可以参考"),n("RouterLink",{attrs:{to:"/基础/函数方法/3.html"}},[t._v("这里")])],1),t._v(" "),n("p",[t._v("通常来说,web 编程中的中间件就是这么用的,使用 pipline 的方法,使用修饰器模式 (包裹函数) 然后链式调用,使用 http.HandlerFunc 进行适配器 (也就是类型的转换) 进而实现中间件的功能。")]),t._v(" "),n("h2",{attrs:{id:"接口提供程序的可测试性"}},[t._v("接口提供程序的可测试性")]),t._v(" "),n("p",[t._v("主要思想就是从引入一个结构体变成引入一个接口,这样就可以完美的解耦上下的数据。")]),t._v(" "),n("p",[t._v("下面有一个场景,使用接口来降低耦合达到可以测试函数的目的。")]),t._v(" "),n("p",[t._v("首先我们先看一下原版:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"example.com/s/cache"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddA")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\n\tcache"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们发现,整个数据耦合在一起了,如果想替换掉 cache 包,那就是不可能的,下面我们使用接口将 AddA 改造一下。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Ader "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddA")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a Ader"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("下面我们实现一下这个接口")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ExampleAd "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tyear "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ExampleAd"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\td"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name\n\td"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" year\n\tcache"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" d"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("最后的运行")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ExampleAd"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("AddA")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"liming"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\n")])])]),n("h2",{attrs:{id:"接口的严格和函数的宽松对比"}},[t._v("接口的严格和函数的宽松对比")]),t._v(" "),n("p",[t._v("接口的实现是严格的:在实现接口的时候函数需要显示转换 (适配器模式)")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ListenAndServe")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":8080"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandlerFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hi"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fprintf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("这是正确的用法,不能因为 hi 跟 http.HandlerFunc 底层一样,就认为它俩相等,因为 http.HandlerFunc 实现了接口,并不代表 hi 实现了接口。")]),t._v(" "),n("p",[t._v("实际上是不等于的关系,需要显式的转换一下。")]),t._v(" "),n("p",[t._v("接下来让我们看一下刚才代码原理:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1 a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("y "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("a1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("y"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" t "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("y "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" x"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("y\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" bb b "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n bb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("函数的使用是宽松的。当直接使用函数,以及 return 函数的的时候,(其它引用类型也一样:slice,map,func,interface,chan) 是不需要显式转换的,只有非引用类型比如 int,bool string struct ... 需要。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不需要显示的转换")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 或者也可以说:系统自动把这个匿名函数推导为了b类型。")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数类型 return ")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数类型 直接使用")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" N "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n N"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 当然你如果显式的转换一下也是没有问题的")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 或者说,你人为的帮它推导出了类型是b类型")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("b")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("不过除了函数等引用类型之外的非引用类型还是必须显示的转换的")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 整数类型")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a\n\ta1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// struct 也需要显示的转换")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n i "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b1 b\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get7")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("b1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" b1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 或者是")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get8")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" b1 "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("b1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),n("h3",{attrs:{id:"interface-如何判断-nil"}},[n("em",[n("strong",[t._v("interface 如何判断 nil")])])]),t._v(" "),n("p",[t._v("只有类型是 nil + value 是 nil 的接口类型才是 nil,否则它不等于 nil")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// true")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("b\n\ta1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" b1\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// false")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"论述-nil-error-nil-的原因"}},[n("em",[n("strong",[t._v("论述 “nil error != nil” 的原因")])])]),t._v(" "),n("p",[t._v("nil error 通常可以用这种方法来输出:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//(0x102205988,0x0)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//false,原因主要是动态类型赋予了这个指针类型具体的类型了,只是没有类型的值而已")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("可以发现,nil error 的类型并不是 0x0,而 nil 接口变量是 0X0,0x0,所以这两者并不相同。")]),t._v(" "),n("h3",{attrs:{id:"eface-和-iface-的区别"}},[n("em",[n("strong",[t._v("eface 和 iface 的区别")])])]),t._v(" "),n("p",[t._v("eface 和 iface 的第二个字段相同均存储的是动态类型的地址,然而 eface 的第一个字段保存的是动态类型的元数据,即:_type 字段,而 iface 的第一个字段不仅仅保存了动态类型的元数据 _type,还保存了自己的方法集合的相关数据,以及动态类型实现的方法地址等数据。")]),t._v(" "),n("h3",{attrs:{id:"如何查找-interface-中的方法"}},[n("em",[n("strong",[t._v("如何查找 interface 中的方法")])])]),t._v(" "),n("p",[t._v("除了查找文档,以及查看源码,还可以通过反射来查找 interface 中的方法。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyInterface "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//这里就是将nil转化为*MyInterface类型,elem()是一个非常重要的方法, Elem返回接口 v 包含的值或指针 v 指向的值")]),t._v("\nt "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("TypeOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("MyInterface"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Elem")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NumMethod")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("使用反射,判断某个类型是否实现了某个接口:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"io"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"os"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"reflect"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// As interface types are only used for static typing, a")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// common idiom to find the reflection Type for an interface")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// type Foo is to use a *Foo value.")]),t._v("\n\twriterType "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("TypeOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("io"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Writer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Elem")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\tfileType "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" reflect"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("TypeOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fileType"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Implements")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("writerType"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h3",{attrs:{id:"interface-设计的优缺点"}},[n("em",[n("strong",[t._v("interface 设计的优缺点")])])]),t._v(" "),n("p",[t._v("优点:")]),t._v(" "),n("ul",[n("li",[t._v("可扩展性:程序拥有横向扩展的能力")]),t._v(" "),n("li",[t._v("松耦合:接口可以实现代码的松耦合,因为接口只是定义了一组方法,而不是实现,因此它们可以被许多不同的类型实现,这使得代码更加灵活。")]),t._v(" "),n("li",[t._v("可测试性:使用接口编写的代码更容易进行单元测试,因为可以提供模拟对象来模拟接口所定义的方法。这有助于在代码库中提供更高的测试覆盖率。")]),t._v(" "),n("li",[t._v("可读性:使用接口编写的代码更容易阅读和理解,因为可以通过接口名称和方法签名来查看类型所提供的功能。")])]),t._v(" "),n("p",[t._v("缺点:")]),t._v(" "),n("ul",[n("li",[t._v("过度设计:如果使用不当,接口可能会导致过度设计,这可能会令代码库变得复杂、难以理解和维护。因此,在设计接口时应该遵循简单性原则,"),n("strong",[t._v("仅定义必要的方法")]),t._v("。")]),t._v(" "),n("li",[t._v("性能损失:使用接口可能会导致一些性能损失,因为在运行时需要进行类型断言和方法查找。虽然这种影响通常很小,但在高性能场景下可能会有所不同。")]),t._v(" "),n("li",[t._v("难以理解:对于新手来说,理解接口的概念和使用可能会比较困难,这可能会导致一些代码可读性差的问题。")])]),t._v(" "),n("h3",{attrs:{id:"空接口类型和一般类型是从属关系吗"}},[n("em",[n("strong",[t._v("空接口类型和一般类型是从属关系吗?")])])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" \n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("上面的代码就表示,"),n("em",[n("strong",[t._v("空接口类型和一般的类型是平级关系")])]),t._v(",不能说 any 被所有类型实现了,就说 any 是所有类型的父类,这是错误的。所以当我们的 age 中 value 是 any 类型,那么我们传入的数据的类型也得是 any 类型,不然不就是类型错误了吗")]),t._v(" "),n("p",[t._v("那么我们学的,所有类型都实现了空接口这句话如何使用呢,很简单,让任何类型转化为 any 类型即可,任何类型转化为 any 类型之后,就会变成 any 类型,并不是之前它的类型。")]),t._v(" "),n("p",[t._v("所以这里的代码应该这么写:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a any "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所以这里的 true 从 布尔类型 直接变成了any类型 ")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ✅")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),n("p",[t._v("即便你直接传入字面量也可以:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的 字面量 1 其实就是 any 类型 并不是所谓的int或者uint")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value any"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://book.douban.com/subject/35720728/ 246 页 - 286 页")]),t._v(" "),n("li",[t._v("https://mp.weixin.qq.com/s/6_ygmyd64LP7rlkrOh-kRQ")]),t._v(" "),n("li",[t._v("https://github.com/golang/go/blob/master/src/runtime/runtime2.go")]),t._v(" "),n("li",[t._v("https://github.com/golang/go/blob/master/src/runtime/type.go")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/25.831fd7ee.js b/assets/js/25.831fd7ee.js new file mode 100644 index 000000000..9b6c45766 --- /dev/null +++ b/assets/js/25.831fd7ee.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{452:function(t,s,a){"use strict";a.r(s);var n=a(36),p=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"切片"}},[t._v("切片")]),t._v(" "),a("p",[t._v("导读:")]),t._v(" "),a("ul",[a("li",[t._v("切片的基本操作")]),t._v(" "),a("li",[t._v("切片和数组的基本概念")]),t._v(" "),a("li",[t._v("切片数组的底层数据结构")]),t._v(" "),a("li",[t._v("issues")])]),t._v(" "),a("h2",{attrs:{id:"基本操作"}},[t._v("基本操作")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始化一个切片,设置长度为5,容量为10")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取一个新的切片,遵循左闭右开的原则,取值时并且只看长度不能看容量")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// b切片,长度为1,容量为8(下文有讲,向右原则)")]),t._v("\nb"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 判断切片长度为0")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// append 数据")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 将切片内容清空(element设置为初始值,比如int就是0,string就是"")')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("clear")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将一个切片转为一个数组,注意,新数组不能超过切片的长度,且是数据的深度拷贝")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("h2",{attrs:{id:"切片和数组的基本概念"}},[t._v("切片和数组的基本概念")]),t._v(" "),a("p",[t._v("数组是拥有一段连续内存的数据结构,切片是存储了这个数据结构地址,长度以及容量的 struct,这里俗称这种数据结构 (类似切片) 叫引用类型")]),t._v(" "),a("p",[t._v("生成数组有两种方式 "),a("code",[t._v("[3]int")]),t._v(" 和 "),a("code",[t._v("[...]int")]),t._v(" 但是后者其实只是一种语法题,go 会自动推断出容量,因为推断是在编译期搞定的,所以并不会影响数组运行时的效率。")]),t._v(" "),a("p",[t._v("不同长度的相同数据类型数组不是一个类型,比如 "),a("code",[t._v("[1]string{}")]),t._v(" 和 "),a("code",[t._v("[2]string{}")]),t._v(" 就是两个类型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Extra "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Array"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Elem"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" elem"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Bound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" bound"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码可以解释一下,它来自 go 的源代码,可以看出,生成数组的是一个 struct,那么显而易见了,里面的各项参数都必须一致的情况下 struct 才是一致的,所以,必须类型和容量都满足才行")]),t._v(" "),a("p",[t._v("但是切片没有这个烦恼,只要数据类型一致就是一种类型,因为它在编译期间的结构体中只有类型,并没有数量,数量需要在运行时才能确定")]),t._v(" "),a("p",[t._v("“切片的切片” 的容量是和 “切片的” 容量是不一致的 (比如这里的 a 和 b),我们来看一个例子:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("output:"),a("code",[t._v("6, 6, 3, 4")])]),t._v(" "),a("p",[t._v("我猜你肯定以为 b 的容量也是 6,但是不是,go 规定,"),a("em",[a("strong",[t._v("切片只能向右看")])]),t._v(",不能向左看,我们来说一下上面这个例子,a 就不用说了,a 的底层数据结构数组就是 6 个长度,所以 a 自然长度和容量都是 6,但是 b,它是切片的切片,遵从左闭右开的规则,它的长度是从 index 的 2 到 4,也就是说是 "),a("code",[t._v("[3 4 5]")]),t._v(",自然它的长度就是 3,这毫无疑问,又因为切片遵从 “只能向右看容量” 的规则,它的容量从 index 2 开始往后算,也就是 "),a("code",[t._v("6 - 2 = 4")]),t._v(" 所以它的长度是 3 容量是 4")]),t._v(" "),a("h2",{attrs:{id:"切片-数组的底层数据结构"}},[t._v("切片,数组的底层数据结构")]),t._v(" "),a("p",[t._v("严格意义来说,go 的切片不存在扩容,如果切片想要的数据量大于底层数组的容量时,那么系统会做两件事,开辟新的数组,给这个数组生成新的切片,之前的数组和切片并没有任何的改变,而且如果没有被引用了,还会被 gc 掉")]),t._v(" "),a("p",[t._v("数组在数量小于等于 4 的时候,直接分配在栈内存里,如果大于四且没有逃逸到堆上时,变量就会在静态存储区初始化然后拷贝到栈上")]),t._v(" "),a("blockquote",[a("p",[t._v("静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。")])]),t._v(" "),a("blockquote",[a("p",[t._v("栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。任何临时变量都是处于栈区的,包括在 main () 函数中定义的变量")])]),t._v(" "),a("blockquote",[a("p",[t._v("堆区:亦称动态内存分配。程序在运行的时候用 malloc 或 new 申请任意大小的内存,程序员自己负责在适当的时候用 free 或 delete 释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。")])]),t._v(" "),a("p",[a("strong",[t._v("切片的底层数据结构。")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" SliceHeader "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tData "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n\tLen "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tCap "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("实际上,切片就是一个 struct (struct 是 go 的基本组成单位,实际上很多东西都可以使用结构体来表达,比如接口底层也是结构体)")]),t._v(" "),a("p",[t._v("当我们使用字面量的方式去生成一个 slice 的时候,会在编译期间搞定,但是如果使用 make 去生成一个切片时,就会在运行时生成一个切片,在运行时生成切片,不仅仅会进行边界检查,而且还会看是否逃逸到堆上。")]),t._v(" "),a("p",[t._v("**slice 的扩容规律,**如果期望容量大于当前容量的两倍就会使用期望容量,如果当前切片的长度小于 "),a("a",{attrs:{href:"https://github.com/golang/go/blob/fd0ffedae2dd9e202efc2dd7f7937baa08600d26/src/runtime/slice.go#L178",target:"_blank",rel:"noopener noreferrer"}},[t._v("256"),a("OutboundLink")],1),t._v(" 就会将容量 x2,\n如果当前切片的长度大于 256 就会逐步 (按照这个公式 "),a("code",[t._v("cap += (cap + 768) / 4")]),t._v(") 从 2 倍的倍增速率调整到 1.25 的倍率,增加到新容量大于期望容量。不过这还不是全部")]),t._v(" "),a("p",[t._v("slice 扩容具体操作。扩容的时候并不是严格按照这个规律来的,这只是一个大致的规律,实际运行的时候会进行 "),a("code",[t._v("padding")]),t._v(" (填充),也就是内存的对齐,将容量字节数尽量靠近 2 的次方,比如说期望的新容量是 5,这时期望分配的内存大小为 40 字节 (具体看一个位置多少个字节,这里是按照 8 举例子),运行时会向上取整内存的大小到 48 字节 (取整到 go 的"),a("a",{attrs:{href:"https://github.com/golang/go/blob/b634f5d97a6e65f19057c00ed2095a1a872c7fa8/src/runtime/sizeclasses.go#L84",target:"_blank",rel:"noopener noreferrer"}},[t._v("推荐值"),a("OutboundLink")],1),t._v("),所以新切片的容量是 "),a("code",[t._v("48 / 8 = 6")])]),t._v(" "),a("p",[t._v("我们知道当切片扩容的时候,重新分配底层数组是会牵涉到内存的复制的,因此尽量减少内存复制就是我们要追求的事情了,当我们往后面追加数据的时候,如果可以提前预估要使用的容量,那么就不牵涉到多次的内存复制了")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" sliceSize "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1000")]),t._v("\n\tm "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sliceSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" sliceSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tm "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[a("strong",[t._v("slice 的浅拷贝")]),t._v(" "),a("code",[t._v("s := make([]int, 3,12)")]),t._v(","),a("code",[t._v("s1 := s[1:2]")]),t._v(",那么 s1 和 s 是浅层拷贝,他们拥有一个共同的底层数组,更改任意一个另一个的值也会发生改变。")]),t._v(" "),a("p",[t._v("**slice 的深拷贝。**copy 内置函数会将源内存 data 直接一次性拷贝,所以慎用,很消耗资源。")]),t._v(" "),a("p",[a("strong",[t._v("slice 的边界检查消除以及优化。"),a("strong",[t._v("go 在编译数组或者切片的时候都会在编译期间进行边界越界的检查,不过也只是普通的检查,比如直接使用整数或者常量访问数组,对于")]),t._v("用变量去获取切片数组的情况")]),t._v("根本就检查不了,这个时候 go 的运行时就会起作用,发出 Panic,那么边界检查有什么缺点呢?就是会降低运行时的效率,当然这里指的是运行时的检查,因为编译器的检查首先本身能力有限,其次只会降低编译速度而已,所以 go 从 1.17 开始,就开始支持了边界检查的消除,为了就是在证明不会越界的情况下,提高代码的运行效率,下面我们看一下取消运行时边界检查的例子:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这种不能确定,所以还是会检查")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这样,就可以消除边界检查,因为运行时确定不可能出现问题")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 或者这样也可以")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("A")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("256")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("256")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里就是给运行时一个暗示,表示i的最大index不会超过 256")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// v的最大值也不会超过 256(byte最大值 255)")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("h2",{attrs:{id:"append-追加数据的操作"}},[t._v("append 追加数据的操作")]),t._v(" "),a("p",[t._v("前文我们知道 slice 会发生扩容情况,那么这种扩容一般是在 append 操作的时候发生的,通常来说操作是这样的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 注意,append操作是追加的意思,所以这里不是 100,而是0001")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 0001")]),t._v("\n")])])]),a("p",[t._v("当 slice 底层数组不够 append 的时候,就会发生扩容:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\na"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\na"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里还是相同的数组,因为容量没有超过")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的a 指向的就不同于之前的那个数组了。")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//底层就变成了一个新的数组 1 2 3 4 5 0 0 0 ;fmt.Println(cap(a)) : 8")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("同样底层数组的不同区域的切片 append 的时候经常会发生意想不到的结果:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//[0 0 0] [0]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// [0 0 2] [0 2]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// [0 0 2 4] [0 2]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// [0 0 2 5] [0 2 5]")]),t._v("\n")])])]),a("p",[t._v("从上面的案例可以说明,首先,a1 a 指向同一个底层数组,其次,a1 和 a 在 append 的时候,都是在各自切片的后面添加数据,他们会互相影响,在写代码的时候容易出现 bug")]),t._v(" "),a("h3",{attrs:{id:"对-append-的优化"}},[t._v("对 append 的优化")]),t._v(" "),a("p",[t._v("对一个未知大小的切片进行 append 操作的最佳选择是初始化一个 nil 切片:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("s 在初始化的时候没有分配内存,在 append 的时候分配了一个底层数组,下面这种方式就会浪费一次内存分配")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("这种方式,在 s 初始化的时候会给予它一个底层长度为 0 的数组,即便长度为 0,go 并未分配实际的内存空间,但是仍然浪费了执行片段,append 的时候还要再次分配底层数组。")]),t._v(" "),a("p",[t._v("不过使用 make 的方式比较适合"),a("strong",[t._v("已知容量")]),t._v("的场景。")]),t._v(" "),a("p",[t._v("除此之外还有两种初始化的方式:")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("[]int(nil)")])]),t._v(" "),a("li",[a("code",[t._v('[]string("a")')])])]),t._v(" "),a("p",[t._v("我们知道 "),a("code",[t._v("[]int{}")]),t._v(" 和 "),a("code",[t._v("var s []int")]),t._v(" 是两种皆然不同的初始化方式,虽然都是 0 长度,但是前者不是 nil,后者是 nil,不过 append 的时候不会介意是否是 nil,这也提醒了我们判断是否是空切片的方式,使用 len == 0 才是正确的方法,“是否等于 nil” 是错误用法。")]),t._v(" "),a("p",[a("code",[t._v("[]string(nil)")]),t._v(" 的用法非常少见,通常来说,使用场景就下面这么一个:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("src "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"there"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"!"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("我们这里使用一个值为 nil 的切片主要是为了符合类型的需求。")]),t._v(" "),a("h2",{attrs:{id:"切片的-copy"}},[t._v("切片的 copy")]),t._v(" "),a("p",[t._v("copy 是 go 语言的内置函数,全局使用,"),a("code",[t._v("copy(a,b []Type)")]),t._v(",copy 是深度拷贝,它将后者的数据完全拷贝给前者。")]),t._v(" "),a("p",[t._v("要注意的是,将要被复制的元素能复制的量取决于前者的 length")]),t._v(" "),a("p",[t._v("比如下面这种情况,被复制的元素就是 0,但是并不会 panic")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("src "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" d "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// []")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("一般来说,我们会使用相同的 length:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("src "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nd "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("或者直接使用 append 也能做到 copy")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("src "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nd "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"切片未被合理-gc"}},[t._v("切片未被合理 gc")]),t._v(" "),a("p",[t._v("当切片完成自己的使命时,我们希望它可以正常的被 gc 掉,通常来说,我们可以手动使用 "),a("code",[t._v("runtime.GC()")]),t._v(" 来强制系统进行垃圾回收,下面我们看一种 bug,这种 bug 出现以后,我们手动的垃圾回收将会无效")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 此处原本的想法是只取两个数据")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 但是造成了10个数据都不能垃圾回收,8个浪费")]),t._v("\nb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nruntime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GC")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nruntime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("KeepLive")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("本来我们期望 s 底层数组可以被垃圾回收,但是 b 也指向这个相同的底层数组,那么这个垃圾回收就无法执行。")]),t._v(" "),a("p",[t._v("正确的方法是")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" res\n")])])]),a("p",[t._v("当然了,我们深究 gc 的本质就会发现,三色 gc 算法是看某个对象是否还被变量持有,是否可以通过变量的方式追踪到,来作为回收标准的,要么我们像前者一样,不再让变量持有值,要么将值变成 nil 即可:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tv "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 此处原本的想法是只取两个数据")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 但是造成了10个数据都不能垃圾回收,8个浪费")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里是手动的将前八个数据丢弃掉")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nruntime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GC")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nruntime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("KeepLive")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("p",[t._v("这种多切片指向底层数组而造成的无法正常垃圾回收的行为很常见。在工作中还是应该检查好自己的代码,避免这种行为的发生。")]),t._v(" "),a("h2",{attrs:{id:"切片中的-range-注意事项"}},[t._v("切片中的 range 注意事项")]),t._v(" "),a("p",[t._v("range 时,我们直接修改返回的值是不会生效的,因为返回的值并不是原始的数据,而是数据的复制。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tyear "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" student "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" result "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tstudent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 12 13")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("也就是说,这里的 "),a("code",[t._v("student :=")]),t._v(" student 的改变不会影响 result 中的任何数据,除非这里的 "),a("code",[t._v("[]Student")]),t._v(" 是 "),a("code",[t._v("[]*Student")])]),t._v(" "),a("p",[t._v("下面我们演示一下,正确的在 range 时的操作方式:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tyear "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" result "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tresult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 13 14")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("正确的方式就是直接使用 result 本身进行操作,就可以真正的去改变 result 了。")]),t._v(" "),a("p",[t._v("并且,在 range 的时候,range 后面的数据其实也是复制品,也就是说,这里的 "),a("code",[t._v(":= range result")]),t._v(" result 也是复制品,原有的 result 如何变化都不会影响 range 结果。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的 result")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" result "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 跟这里面的result不是一个值,")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//只有里面的result才是跟外面的result是一个值")]),t._v("\n\t\tresult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("下面我们再看一个案例:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// [0 0 0 10 10 10]")]),t._v("\n")])])]),a("p",[t._v("你猜结果是多少呢?是会一直 range 吗?因为数据在一直添加啊,nonono,只会 range 3 次而已,因为 range 后面的 s 是固定不变的,它本身只是原有 s 的复制品而已。")]),t._v(" "),a("p",[t._v("综上:")]),t._v(" "),a("ul",[a("li",[t._v("range 后面的数据是原有数据的复制品")]),t._v(" "),a("li",[t._v("range 前面的 k v 更是后面复制品输出数据的复制品")]),t._v(" "),a("li",[t._v("range 里面的数据才是跟外面的数据保持一致")])]),t._v(" "),a("p",[t._v("第三点很关键,range 后面的数据跟 range 里面的数据并不是一个:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的s")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的s 跟外面保持一致")]),t._v("\n\ts "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("strong",[t._v("不能")]),t._v("把 range 当做 function 来类比:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("如果是函数,函数体的变量 s 和函数内部的 s 就是同一个,显然,range 中,range 后面的 s 和 range 里面的 s 并不是同一个。")]),t._v(" "),a("h2",{attrs:{id:"切片转化为数组"}},[t._v("切片转化为数组")]),t._v(" "),a("p",[t._v("在 go 1.20 版本中,新添加了切片转为数组或者数组指针的操作,具体实现如下:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \na1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[a("code",[t._v("a[0] == s[0]")]),t._v(",也就是说,转化出来的就是底层的那个数组的复制,"),a("strong",[t._v("注意并不是底层数组本身")]),t._v(",不过这里相同切片转化的数组指针是指向这个切片的底层数组的,所以 a2 和 a3,s 是公用一个数组的,如果更改了 a2[0],那么 a3,s 也是会发生改变的,a1 a 已经是数据的复制了,他们有了分别的生活了。")]),t._v(" "),a("p",[t._v("下面我们看一个具体的代码演示:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//[0 0] [0] [0 0] &[0] &[0 0]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//[0 0] [1] [0 0] &[0] &[0 0]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//[12 0] [1] [0 0] &[12] &[12 0]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 可以证明确实是指向同样的底层数据")]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("a2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("a3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 0x1400012a020 0x1400012a020 0x1400012a020")]),t._v("\n")])])]),a("p",[t._v("当一个切片转化为一个数组的时候,数组的长度不能大于切片的长度,而不是容量")]),t._v(" "),a("p",[t._v("那么下面这种代码就会出现 bug")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// panic: cannot convert slice with length 2 to array or pointer to array with length 3")]),t._v("\n")])])]),a("p",[t._v("下面我们看一下转化后的特殊值")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("s"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// []")]),t._v("\na1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// &[]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//将非空切片转为长度为 0 的数组,得到的指针不是 nil,比如 b2")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" j "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\nb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// panic")]),t._v("\nb1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// [] ")]),t._v("\nb2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// <nil>")]),t._v("\nb3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// panic")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//将 nil 切片转为长度为 0 的数组,得到的指针为 nil")]),t._v("\nc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nu "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//&[] ")]),t._v("\nu1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// []")]),t._v("\n")])])]),a("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),a("p",[a("code",[t._v("问题一:")]),t._v(" "),a("em",[a("strong",[t._v("如果有多个切片指向了同一个底层数组,那么你认为应该注意些什么")])])]),t._v(" "),a("p",[t._v("一定要避免 a 切片的更改造成的底层数据的改变,对 b 切片的结果造成影响,因为它们指向同一个数据底层")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\na"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[a("code",[t._v("[1 2 4] [1 2 4]")])]),t._v(" "),a("p",[a("code",[t._v("问题二:")]),t._v(" "),a("em",[a("strong",[t._v("怎样沿用扩容的思想对切片进行 “缩容")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// b = [1,2]")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果确定a的数据多余的没有任何的用途了")]),t._v("\nnb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("nb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("所谓扩容的思想,就是创造一个新的底层数据")]),t._v(" "),a("p",[a("code",[t._v("问题三:")]),t._v(" "),a("em",[a("strong",[t._v("nil 切片和空切片 (比如 []int {}) 的区别")])])]),t._v(" "),a("p",[t._v("最大的区别就是指向的底层数组的地址不一样")]),t._v(" "),a("ul",[a("li",[t._v("nil 压根就没有地址")]),t._v(" "),a("li",[t._v("空切片是有正儿八经的地址的,"),a("strong",[t._v("只不过这个地址指向的数组不占用空间")]),t._v(",这个数组叫做 zero 数组,并且所有的空切片指向同一个数组就是这个 zero 数组,也可以说在 go 里,zero 数组是唯一的存在,它存在的目的就是为了空切片")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sizeof")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 0")]),t._v("\n")])])]),a("p",[t._v("空的数据是不占内存空间的,还有类似的,比如空的 struct 也是一样的")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sizeof")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 0")]),t._v("\n")])])]),a("p",[a("code",[t._v("问题四:")]),t._v(" "),a("em",[a("strong",[t._v("slice 和 array 的不同使用场景是什么")])])]),t._v(" "),a("p",[t._v("如果数据是固定的,可以用数组,否则还是切片更加灵活,实际上绝大多数情况下还是切片更好用")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://www.jianshu.com/p/9ea2fba64f06")]),t._v(" "),a("li",[t._v("https://chai2010.cn/advanced-go-programming-book")]),t._v(" "),a("li",[t._v("https://blog.csdn.net/kevin_tech/article/details/122138489")]),t._v(" "),a("li",[t._v("https://blog.csdn.net/weixin_39927993/article/details/112099007")])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/26.83ccb127.js b/assets/js/26.83ccb127.js new file mode 100644 index 000000000..a12389cf8 --- /dev/null +++ b/assets/js/26.83ccb127.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[26],{453:function(t,s,n){"use strict";n.r(s);var a=n(36),r=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"字符串"}},[t._v("字符串")]),t._v(" "),n("ul",[n("li",[t._v("字符串的基础操作")]),t._v(" "),n("li",[t._v("字符串的基础知识")]),t._v(" "),n("li",[t._v("字符串的底层操作")])]),t._v(" "),n("h2",{attrs:{id:"字符串的基础操作"}},[t._v("字符串的基础操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 声明")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你好"')]),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// s := "你好"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//读取")]),t._v("\nfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 转化为unicode码点存储,单个字符, 例如'你',也是使用的rune来存储的,、")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不过string底层本身是[]byte的方式存储的")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rune")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 转化为字符存储")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 字符的简单拼接")]),t._v("\ns1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你"')]),t._v("\ns2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"好"')]),t._v("\ns "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" s1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" s2\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//多行字符")]),t._v("\ns "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v("`\n你好\n\n世界\n`")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 多行字符也通常用在屏蔽 ""作用的地方')]),t._v("\ns"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('`{"user": "shgopher", "links": ["https://github.com/shgopher"]}`')]),t._v("\n")])])]),n("h2",{attrs:{id:"字符串的基础知识"}},[t._v("字符串的基础知识")]),t._v(" "),n("ul",[n("li",[t._v("字符串的数据是只读数据不可更改")]),t._v(" "),n("li",[t._v("字符串的零值是可用的,"),n("code",[t._v("var s string")]),t._v(" 结果是 "),n("code",[t._v('""')])]),t._v(" "),n("li",[t._v("获取字符串长度的操作时间复杂度是 "),n("code",[t._v("O(1)")]),t._v(" 因为它是不可变的只读数据,所以长度被保存在了字段中,直接读这个字段即可")]),t._v(" "),n("li",[t._v("字符串可以通过 "),n("code",[t._v("+")]),t._v(","),n("code",[t._v("+=")]),t._v(" 进行拼接")]),t._v(" "),n("li",[t._v("字符串可以使用 "),n("code",[t._v("> < >= <= == =!")]),t._v(" 运算符,比较的顺序是:\n"),n("ul",[n("li",[t._v("先比较长度")]),t._v(" "),n("li",[t._v("再比较是否是指向一块内存地址")]),t._v(" "),n("li",[t._v("如果都满足再比较具体数据")])])]),t._v(" "),n("li",[t._v("字符串原生支持 unicode 字符集,并且 go 默认支持 utf-8 的编码算法\n"),n("ul",[n("li",[t._v("rune 存储 unicode 的一个码点")]),t._v(" "),n("li",[t._v("byte 存储真实的底层字符 (比如 utf-8,三个字符来保存一个中文字符,rune 就只显示一个字符,byte 会显示三个)")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"中"')]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rune")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// output: [228 184 173] [20013]")]),t._v("\n")])])])]),t._v(" "),n("li",[t._v("使用``原生支持多行字符")])]),t._v(" "),n("h2",{attrs:{id:"字符串的高效构造"}},[t._v("字符串的高效构造")]),t._v(" "),n("p",[t._v("字符串的构造有以下这么几种")]),t._v(" "),n("ul",[n("li",[t._v("最常规的使用 "),n("code",[t._v("+")]),t._v(" 和 "),n("code",[t._v("+=")])]),t._v(" "),n("li",[t._v("fmt.Sprintf")]),t._v(" "),n("li",[t._v("strings.Join")]),t._v(" "),n("li",[t._v("strings.Builder")]),t._v(" "),n("li",[t._v("bytes.Buffer")])]),t._v(" "),n("p",[t._v("让我们分别给出代码:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//最常规的使用`+`和 `+=`")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"中"')]),t._v("\n\ts2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"国"')]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" s2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//fmt.Sprintf")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"中"')]),t._v("\n\ts2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"国"')]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sprintf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%s%s"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//strings.Join")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"strings"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"中"')]),t._v("\n\ts2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"国"')]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("strings"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Join")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//strings.Builder")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"strings"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b strings"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Builder\n b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Grow")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 给出猜测最终的string长度")]),t._v("\n\ts1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"中"')]),t._v("\n\ts2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"国"')]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//bytes.Buffer")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bytes"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b bytes"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer\n\ts1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"中"')]),t._v("\n\ts2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"国"')]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("根据 benchmark,得出以下结论:")]),t._v(" "),n("ul",[n("li",[t._v("带有预估 string 长度的 strings.Builder 最快")]),t._v(" "),n("li",[t._v("带有预估的 bytes.Buffer 和 strings.Join 性能第二档次")]),t._v(" "),n("li",[t._v("没有预估长度的 strings.Builder 和 bytes.Buffer 以及 + += 第三档次")]),t._v(" "),n("li",[t._v("fmt.Sprintf 最差劲")])]),t._v(" "),n("p",[t._v("那么:")]),t._v(" "),n("ul",[n("li",[t._v("当能给出预估的情况下,优选使用 strings.Builder")]),t._v(" "),n("li",[t._v("strings.Joins 性能最稳,没有预估的情况下,使用这个稳定啊 (实际上这个 join 就是调用了 string.Builder,并且给出了预估长度)")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Join")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("elems "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sep "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里是搞定string长度的")]),t._v("\nn "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sep"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tn "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用了builder")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b Builder\nb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Grow")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" elems"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sep"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WriteString")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("ul",[n("li",[t._v("操作符 + += 最直观,并且在字符短,以及编译器知道连接的字符串个数时,这种方式还能得到编译器的优化")]),t._v(" "),n("li",[t._v("fmt.Sprintf 用在多类型组成字符串的时候是最好的,虽然它效率很差,但是人家能力强啊")])]),t._v(" "),n("p",[n("strong",[t._v("综上所诉")]),t._v(":优先选 "),n("code",[t._v("strings.Join")])]),t._v(" "),n("h2",{attrs:{id:"字符串的底层"}},[t._v("字符串的底层")]),t._v(" "),n("h3",{attrs:{id:"数据结构"}},[t._v("数据结构")]),t._v(" "),n("p",[t._v("一个 string 的底层数据类似一个 slice,只不过这个 slice 是只读数据,它的底层不同于一般的 slice,是一个特别的 struct")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" stringStruct "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tstr unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pointer\n\t"),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("len")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" \n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 注意常规的slice这里是有一个cap的")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//但是string因为是只读的关系只有length的含义")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[n("code",[t._v("runtime/string.go")]),t._v(" 中出现了这么一段代码")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// rawstring allocates storage for a new string. The returned")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// string and byte slice both refer to the same storage.")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// The storage is not zeroed. Callers should use")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// b to set the string contents and then drop b.")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rawstring")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("size "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tp "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("mallocgc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("uintptr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("size"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stringStructOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("str "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" p\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stringStructOf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("len")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" size\n\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("slice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" slice"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" size"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" size"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们仔细看注释的这句话,当一个 string 导入数据的时候,运行时会给定一个辅助的 slice,用来辅助的导入数据,然后当数据导入完毕之后,这个 slice 的描述符,也就是这个代表了这个 slice 的 struct 就会被删除掉,所以说其实 string 不能跟 slice 划上等号,也不能简简单单的说它是一个只读的 slice,实际上它压根就不是 slice,slice 在生成 string 的过程中只是起到了辅助作用")]),t._v(" "),n("h3",{attrs:{id:"类型转换"}},[t._v("类型转换")]),t._v(" "),n("p",[t._v("字符串进行的转化只能是 string 和 "),n("code",[t._v("[]rune")]),t._v(" or "),n("code",[t._v("[]byte")]),t._v(" 互相转换")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"【你好】"')]),t._v("\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rune")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// []byte 是可以直接使用fmt包直接输出为string的,但是[]rune需要显式进行转换。")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"现在我们打印出原始数据%s,打印出[]byte转化后的数据%v,打印出[]rune转化后的数据%v,打印出逆转的数据%s 和 %s,"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("上文我们提到的字符串的构造,例如删除一个字符,追加一个字符,都无一例外需要改变这个 string,那么很明显任何数据的处理都是"),n("strong",[t._v("拷贝")]),t._v("的数据,原数据是不会有任何变化的,所以这就告诫我们字符串的处理要小心非常有可能浪费大量的内存。")]),t._v(" "),n("p",[t._v("我们看一下底层的转换代码:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" tmpStringBufSize "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("32")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" tmpBuf "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("tmpStringBufSize"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stringtoslicebyte")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("tmpBuf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" buf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("buf "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tmpBuf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" buf"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rawbyteslice")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里就发生了拷贝")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" b\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("于此同时我们也能发现 string 的底层的真实存储是 "),n("code",[t._v("[]byte")]),t._v(" 不是 "),n("code",[t._v("[]rune")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"【你好】"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" c "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("rune")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// invalid argument: arguments to copy c (variable of type []rune) ")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// and a (variable of type string) have different element types rune and byte")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("copy")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("go 为某几种特别的情况优化了 string 和 slice 转换必须拷贝的情况,意思就是不需要拷贝就让这个 string 直接使用这个 slice 的底层,但是有个规定,只要是 slice 发生了改变,那么这个 string 立即失效")]),t._v(" "),n("p",[n("code",[t._v("b = []int{1,2}")])]),t._v(" "),n("ul",[n("li",[t._v("string(b) 用在 map 的 key 中 "),n("code",[t._v("ma[string(b)]++")])]),t._v(" "),n("li",[t._v("string(b) 在字符串的拼接句子中 “a” + string(b)")]),t._v(" "),n("li",[t._v("for-range 中的 string 到[]byte 的转换")])]),t._v(" "),n("h2",{attrs:{id:"for-range-字符串"}},[t._v("for-range 字符串")]),t._v(" "),n("p",[t._v("因为对一个字符串使用 range 的时候,go 默认使用 utf8 的编码方式,但是 string 的底层是[]byte 的存储方式,所以直接 range 的时候,将这个时候的字符转化为字符就会发生乱码的情况")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你好"')]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// äå ")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%c"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("k"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("解决方法有两种:")]),t._v(" "),n("ol",[n("li",[t._v("直接获取 value 值")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你好"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的 v 就直接是 rune")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%c"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("ol",{attrs:{start:"2"}},[n("li",[t._v("将 s 转化为 []rune 来获取真正的 unicode 编码:")])]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你好"')]),t._v("\n\tsr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rune")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的 v 就直接是 rune")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" sr "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%c"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/27.d1524f5d.js b/assets/js/27.d1524f5d.js new file mode 100644 index 000000000..1f15382af --- /dev/null +++ b/assets/js/27.d1524f5d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[27],{455:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"作用域"}},[t._v("作用域")]),t._v(" "),a("p",[t._v("先给出两个经典的案例:")]),t._v(" "),a("p",[t._v("if 级变量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("a b c 这三个变量的作用域属于 if 这整个结构,只要前面初始化过,那么后面就可以使用,所以你会发现 print 可以输出三个变量。")]),t._v(" "),a("p",[t._v("loop 级变量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("因为 "),a("strong",[t._v("i 属于 loop 级别")]),t._v(",通常来说 for 执行过程是快于新开辟一个 goroutine 的,所以导致这是个 goroutine 输出的都是最后一个 i,即都输出 10")]),t._v(" "),a("p",[t._v("根据 go 1.20 的表述,以后这个 loop 级别的变量"),a("strong",[t._v("非常有可能")]),t._v("会被修改成局部变量。如果没有被修改,我们可以开辟一个局部变量 (go 1.22 将这个 loop 级变量修改为局部变量)")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" i\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"代码块的类型"}},[t._v("代码块的类型")]),t._v(" "),a("p",[t._v("代码块是代码执行的基本单位,代码执行流总是从一个代码块流转到另一个代码块。")]),t._v(" "),a("ul",[a("li",[t._v("显式代码块\n"),a("ul",[a("li",[t._v("函数体")]),t._v(" "),a("li",[t._v("for 循环体")]),t._v(" "),a("li",[t._v("if 语句")])])]),t._v(" "),a("li",[t._v("隐式代码块\n"),a("ul",[a("li",[t._v("宇宙代码块:所有的 go 源码都属于这个代码块")]),t._v(" "),a("li",[t._v("包代码块:每一个包都有一个代码块,这个代码块包括了整个包的源码")]),t._v(" "),a("li",[t._v("文件代码块:每一个文件都有一个代码块,这个代码块包括了整个文件的源码")])])])]),t._v(" "),a("p",[t._v("预定义的标识符,比如 make new cap len 作用域是宇宙代码块")]),t._v(" "),a("p",[t._v("包级变量,包级常量的作用域是包代码块")]),t._v(" "),a("p",[t._v("go 源代码中导入的包名称作用域是文件代码块")]),t._v(" "),a("p",[t._v("方法接收器,函数参数,返回值,对应的作用域是函数作用域")]),t._v(" "),a("p",[t._v("函数体内部声明的变量和常量作用域仅限于函数体内部的局部作用域")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// A的作用域就仅限于这个大括号里面")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"if"}},[t._v("if")]),t._v(" "),a("p",[t._v("if 包含了一个隐式的代码块:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("其实等于:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v(" c"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("所以,在 if 中的大括号里,是可以输出 a 的值的。")]),t._v(" "),a("h2",{attrs:{id:"for"}},[t._v("for")]),t._v(" "),a("p",[t._v("for 循环的作用域可以使用下面的两种方式展现。for 循环中的变量都属于 loop 级,不属于每次的那个小循环的局部变量,所以在整个的 loop 过程中,变量是唯一的,就是那一个。只不过不同的时间点,这个变量的值有可能是不同的。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等价于")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这里需要注意一下,一旦 go 在后续的版本中修改了 loop 级变量这个设定,这个等价就不成立了。上文有讲。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" slice "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等价于")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" slice "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"switch-select"}},[t._v("switch && select")]),t._v(" "),a("p",[t._v("这两种结构的等价是相同的,都是 case 级。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" expression"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" list1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" list2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\n等价于\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" expression"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" list1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" list2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("select 稍微有点不同,因为 select 中的 case 是可以新建一个变量的,除了我们说的每一个 case 是一个作用域之外,case 上新建的这个变量也只是属于下面这个小的作用域。")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/28.69e5608b.js b/assets/js/28.69e5608b.js new file mode 100644 index 000000000..4827e870b --- /dev/null +++ b/assets/js/28.69e5608b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[28],{456:function(t,s,n){"use strict";n.r(s);var a=n(36),e=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"其他内容"}},[t._v("其他内容")]),t._v(" "),n("h2",{attrs:{id:"指针"}},[t._v("指针")]),t._v(" "),n("p",[t._v("go 语言的指针类型是 unsafe.Pointer,"),n("code",[t._v("uintptr")]),t._v(" 是指针的计算类型,也就是说,地址必须通过 unsafe.Pointer 提取以后,再转为 uintptr 才能进行计算,uintptr 的实质是一个整数类型,并且完全可以容纳所有的指针的数据。")]),t._v(" "),n("p",[t._v("go 语言使用 "),n("code",[t._v("*")]),t._v(" 符号用来表示指针类型,以及取指针类型实际数据这个操作,使用 "),n("code",[t._v("&")]),t._v(" 取变量的指针 (地址),我们看一下操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 内置函数 new() 去取结构体的地址")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("People "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("p "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 取值符号去取得 变量 p 的地址")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("我们看一下如何直接计算指针类型")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a ,string 类型")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\t\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// b ,a变量的地址")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("a\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"打印初始a变量的地址"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// c,转为可计算的指针类型之后的变量")]),t._v("\n\tc "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("uintptr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// uintptr(unsafe.Pointer())")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"打印可计算指针类型c"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tc"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"打印可计算指针类型c++"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将c再转化为 a 的地址")]),t._v("\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (*string)(unsafe.Pointer())")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"打印转换后的a的指针"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("打印初始a的指针地址 "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x14000096230")]),t._v("\n打印可计算指针类型c "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1374390149680")]),t._v("\n打印可计算指针类型c"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1374390149681")]),t._v("\n打印转换后的a的指针 "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x14000096231")]),t._v("\n")])])]),n("h2",{attrs:{id:"go-的引用类型和非引用类型"}},[t._v("go 的引用类型和非引用类型")]),t._v(" "),n("table",[n("thead",[n("tr",[n("th",{staticStyle:{"text-align":"center"}},[t._v("引用类型")]),t._v(" "),n("th",{staticStyle:{"text-align":"center"}},[t._v("非引用类型")])])]),t._v(" "),n("tbody",[n("tr",[n("td",{staticStyle:{"text-align":"center"}},[t._v("slice, interface, chan, map")]),t._v(" "),n("td",{staticStyle:{"text-align":"center"}},[t._v("其余")])])])]),t._v(" "),n("p",[t._v("引用类型的实质其实就是 fat pointer 即:胖指针,整个类型使用 struct 作为底层数据,data 是一个指针地址,它指向的是要使用的数据。")]),t._v(" "),n("h2",{attrs:{id:"全局变量和局部变量"}},[t._v("全局变量和局部变量")]),t._v(" "),n("p",[t._v("全局变量,引用类型分配在堆上,值类型分配在栈上")]),t._v(" "),n("p",[t._v("局部变量,一般分配在栈上,当局部对象过大的时候分配在堆上,如果对局部变量做逃逸分析,发现它逃逸到了堆上,那么就将其分配到堆上")]),t._v(" "),n("h2",{attrs:{id:"go-init-函数的执行顺序"}},[t._v("go init 函数的执行顺序")]),t._v(" "),n("p",[t._v("init 函数在一个包内的执行顺序:对同一个 "),n("code",[t._v("go")]),t._v(" 文件的 "),n("code",[t._v("init()")]),t._v(" 调用顺序是从上到下的,对同一个 "),n("code",[t._v("package")]),t._v(" 中的不同文件,将文件名按字符串进行 “从小到大” 排序 (数字排在前面),之后顺序调用各文件中的 "),n("code",[t._v("init()")]),t._v(" 函数")]),t._v(" "),n("p",[t._v("对于不同的包,如果不相互依赖的话,按照 main 包中 import 的顺序调用其包中的 "),n("code",[t._v("init()")]),t._v(" 函数,如果包存在依赖,例如:导入顺序 main –> A –> B –> C,则执行顺序为 C –> B –> A –> main")]),t._v(" "),n("p",[n("strong",[t._v("go 会先执行全局变量再执行 init")]),t._v(",当然多包全局变量的初始化跟 init 的执行顺序是一致的")]),t._v(" "),n("h2",{attrs:{id:"go-可比较类型"}},[t._v("go 可比较类型")]),t._v(" "),n("blockquote",[n("p",[t._v("https://go.dev/ref/spec#Comparison_operators")])]),t._v(" "),n("p",[t._v("不可以的")]),t._v(" "),n("ul",[n("li",[t._v("切片,map func (这几种都是因为自己本身变来变去,同样的变量,不同时间,内部值就变了,所以他们不可以参与 == 的比较) 变量无法参与一般的比较,但是他们可以和 nil 作对比")])]),t._v(" "),n("p",[t._v("可以的:")]),t._v(" "),n("ul",[n("li",[t._v("数字类型,bool,string 这种常见类型可比较\n"),n("ul",[n("li",[n("code",[t._v("a := make(chan []int)")]),t._v(" 即使是这样的内部含有不可比较的通道变量本身也是可以比较的。")])])]),t._v(" "),n("li",[t._v("chan 当两个 chan 类型的变量进行比较时,只有它们都为 nil 或者指向同一个通道时才返回 true,否则返回 false。")]),t._v(" "),n("li",[t._v("内部字段都必须是可比较类型的数组和结构体可以比较")]),t._v(" "),n("li",[t._v("指针可以比较,指针的实质是一个整数类型")]),t._v(" "),n("li",[t._v("接口类型是可比较类型")])]),t._v(" "),n("p",[t._v("所以,接口变量是可以作为 map 的 key 值的,因为接口可以比较")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Some\n\tb"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Some "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("methods")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"go-可寻址类型"}},[t._v("go 可寻址类型")]),t._v(" "),n("p",[t._v("以下内容是"),n("strong",[t._v("不可寻址")]),t._v("的量")]),t._v(" "),n("blockquote",[n("p",[t._v("字面量的解释 var a int = 12,12 就是字面量,也就是所谓的那个值本身;结果值的解释:就是这个结果这个 value 的值")])]),t._v(" "),n("ul",[n("li",[n("p",[t._v("常量 "),n("code",[t._v("const a = 12")]),t._v(" &a 不可寻址")])]),t._v(" "),n("li",[n("p",[t._v("基本类型值的字面量 "),n("code",[t._v("a := 12")]),t._v(" &12 不可寻址")])]),t._v(" "),n("li",[n("p",[t._v("算术操作的结果值 "),n("code",[t._v("a := 12 b := 12 &(b+a)")])])]),t._v(" "),n("li",[n("p",[t._v("对各种字面量的索引表达式和切片表达式的结果值。不过有一个例外,对切片字面量的索引结果值却是可寻址的")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("a "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("k"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 无法寻址,这个数据属于临时的,可变的数据")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\tb "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" b "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这个可以寻址,每个切片值都会持有一个底层数组,")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 而这个底层数组中的每个元素值都是有一个确切的内存地址")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("b"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("k"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])]),t._v(" "),n("li",[n("p",[t._v("切片字面量的切片结果值为什么却是不可寻址?"),n("code",[t._v("a := []int{1,2}, &(a[:1])")]),t._v(" 原因是切片表达式字面量的切片属于临时值跟字面量的结果值不一样,后者属于结果值有效值")])]),t._v(" "),n("li",[n("p",[t._v("对字符串变量的索引表达式和切片表达式的结果值。"),n("code",[t._v('a := "a" &("a") &a[0]')])])]),t._v(" "),n("li",[n("p",[t._v("对字典变量的索引表达式的结果值。"),n("code",[t._v("a := map[int]int{1:1} &(a[1])")])])]),t._v(" "),n("li",[n("p",[t._v("函数字面量和方法字面量,以及对它们的调用表达式的结果值。"),n("code",[t._v("&(func ())")])])]),t._v(" "),n("li",[n("p",[t._v("结构体字面量,见下面例子")])]),t._v(" "),n("li",[n("p",[t._v("类型转换表达式的结果值")])]),t._v(" "),n("li",[n("p",[t._v("类型断言表达式的结果值")])]),t._v(" "),n("li",[n("p",[t._v("接收表达式的结果值")])])]),t._v(" "),n("p",[t._v("我们看一道"),n("strong",[t._v("面试题")]),t._v(":")]),t._v(" "),n("p",[t._v("这道题就是因为中间变量无法获取地址造成的 bug")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 此处go会自动调用值的指针来运行 SetName 但是因为 return Dog{name} 是一个临时的值,所以无法获取到指针")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nihao"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetName")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"monster"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Dog "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" Dog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Dog "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Dog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetName")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\td"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们可以这么改")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\na "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" \t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"nihao"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\na"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetName")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"monster"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Dog "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" Dog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Dog "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Dog"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetName")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\td"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("另外自增 ++ 自减 -- 左边的表达式都必须是可寻址的类型,否则也是无法操作的。")]),t._v(" "),n("blockquote",[n("p",[t._v("字典字面量和字典变量索引表达式的结果值是个例外例如 ma [“12”] ++")])]),t._v(" "),n("p",[t._v("在赋值语句中,赋值操作符左边的表达式的结果值必须可寻址的,但是对字典的索引结果值也是可以的")]),t._v(" "),n("p",[t._v("总结一下:")]),t._v(" "),n("ul",[n("li",[n("code",[t._v("常量")]),t._v(" + string 这种无法更改的数据无法寻址,函数通常来说也可以算作 “常量”,应该它就是一段代码,不可更改")]),t._v(" "),n("li",[n("code",[t._v("结果值/字面量")]),t._v(" 因为其无法更改所以寻址将没有意义")]),t._v(" "),n("li",[n("code",[t._v("中间值")]),t._v(" 或者 "),n("code",[t._v("临时对象")]),t._v(" 比如说 &(a + b) 这类临时的变量的内存地址没有意义")]),t._v(" "),n("li",[n("code",[t._v("不安全的操作")]),t._v(" 比如 map 中的 k-v 经常要从一个哈希桶迁移到另一个桶,所以你获取地址,它经常会改变,外界还不得而知,所以获取到这个 key-value 的地址是不安全的")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/29.742dd6e8.js b/assets/js/29.742dd6e8.js new file mode 100644 index 000000000..df413f18f --- /dev/null +++ b/assets/js/29.742dd6e8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{457:function(t,s,n){"use strict";n.r(s);var a=n(36),p=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"反转控制"}},[t._v("反转控制")]),t._v(" "),n("p",[t._v("概念:控制逻辑与业务逻辑分享,让业务逻辑依赖控制逻辑。")]),t._v(" "),n("p",[t._v("大概的思路就是***将控制代码剥离,然后在逻辑代码中去调用控制代码即可***,具体实现的时候,就是在逻辑代码中内嵌控制代码的类型,这样即可。")]),t._v(" "),n("p",[t._v("首先需要明确的是 “控制逻辑是什么” 这个问题,我们举一个例子:有一个数据库,数据库的增删改查就是控制逻辑,使用这些基础的动作去将用户的名字存入数据库,删除用户的名字,这叫业务逻辑,我们所说的反转控制,就是将基础的控制剥离出来,下面我们看一个例子:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这是控制代码,我们把控制代码先揪出来。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Undo "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("undo "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("function "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("undo "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" function"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这段代码的作用:恢复")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("undo "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Undo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n functions "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("undo\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("functions"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" errors"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"No functions to undo"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n index "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("functions"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" function "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" functions"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" function "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("function")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// For garbage collection")]),t._v("\n functions"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里是为了规避在调用delelte的时候,又调用了add的情况")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 因为 delete的时候会调用add,add的时候会再次调用delete")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 为了防止这种情况,我们认为的将这个切片减去一个即可。")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("undo "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" functions"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("index"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们将控制逻辑嵌入到业务逻辑中")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" IntSet "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n data "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v("\n undo Undo\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewIntSet")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IntSet "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" IntSet"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("data"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 直接继承")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("set "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("IntSet"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Undo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Undo")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("set "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("IntSet"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Contains")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("set "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("IntSet"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Contains")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 增加一个数据")]),t._v("\n set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果是恢复的话,是需要删除一个数据的")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所以这里的操作就是删除")]),t._v("\n set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Delete")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("set "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("IntSet"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Delete")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Contains")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("data"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n set"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("undo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/3.a22689ce.js b/assets/js/3.a22689ce.js new file mode 100644 index 000000000..3342a33b5 --- /dev/null +++ b/assets/js/3.a22689ce.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{399:function(t,e,n){},432:function(t,e,n){"use strict";n(399)},545:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:function(t,e){var n=e.props,i=e.slots;return t("span",{class:["badge",n.type],style:{verticalAlign:n.vertical}},n.text||i().default)}},r=(n(432),n(36)),p=Object(r.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/30.4aafb94a.js b/assets/js/30.4aafb94a.js new file mode 100644 index 000000000..ea9e70bd6 --- /dev/null +++ b/assets/js/30.4aafb94a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{458:function(t,s,n){"use strict";n.r(s);var a=n(36),r=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"map-filter-reduce"}},[t._v("map-filter-reduce")]),t._v(" "),n("p",[t._v("map filter reduce 这三个操作经常用在数据的处理上,比如数据的统计业务。")]),t._v(" "),n("p",[t._v("下面看一下这三者基本的做法是什么")]),t._v(" "),n("p",[t._v("我们用做饭来进行类比:")]),t._v(" "),n("ul",[n("li",[t._v("map 30 个进,30 个出,类似于洗菜的过程")]),t._v(" "),n("li",[t._v("filter 30 个进,15 个出,类似于摘菜")]),t._v(" "),n("li",[t._v("reduce 15 个进,1 个出,类似于炒菜的过程")])]),t._v(" "),n("p",[t._v("下面这个案例,我们要对于一组 string 进行数据处理。map 的过程,我们对这堆 string 进行全部的修饰,filer 过程我们挑选出合适的 string,reduce 过程我们最终输出要的成品")]),t._v(" "),n("p",[t._v("map 的举例")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("MapStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("f "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" newS "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n newS "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("newS"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" newS\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("filter 的举例")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("FilterStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("f "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" newS "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n newS "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("newS"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" newS\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("reduce 的举例")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ReduceStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("f "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" newS "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n newS "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" newS\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"李明月"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"李月"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"百伯"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"张兰"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"武滴滴"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"叶赫那拉"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"迪丽热巴"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tns "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("MapStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"同学"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ns"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tns "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("FilterStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ns"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("rune")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ns"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tsum "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ReduceStr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ns"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"-"')]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sum"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这段代码的意思就是首先,我们有一堆学生的名字,我们在名字后面先加上同学,然后我们要把名字本身大于两个字的同学挑出来,并且把他们组成一句话。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("李明月同学 李月同学 百伯同学 张兰同学 武滴滴同学 叶赫那拉同学 迪丽热巴同学"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nfilter "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("李明月同学 武滴滴同学 叶赫那拉同学 迪丽热巴同学"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\nreduce "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("李明月同学"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("武滴滴同学"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("叶赫那拉同学"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("迪丽热巴同学"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("\n")])])]),n("p",[t._v("通过这个案例我们发现,map-filter-reduce 本身只是控制逻辑,真正的业务逻辑其实是那个函数类型,所以说 map-filter reduce 也是标准的 "),n("code",[t._v("控制代码-业务代码")]),t._v(" 分离设计")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/31.87baab0b.js b/assets/js/31.87baab0b.js new file mode 100644 index 000000000..b83a9a989 --- /dev/null +++ b/assets/js/31.87baab0b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{459:function(t,e,n){"use strict";n.r(e);var s=n(36),o=Object(s.a)({},(function(){var t=this.$createElement,e=this._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[e("h1",{attrs:{id:"go-generation"}},[this._v("go generation")]),this._v(" "),e("p",[this._v("// go 已经推出了泛型,因此没有写的必要了。")])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/32.1ea926c5.js b/assets/js/32.1ea926c5.js new file mode 100644 index 000000000..5a479ed78 --- /dev/null +++ b/assets/js/32.1ea926c5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{460:function(t,s,n){"use strict";n.r(s);var a=n(36),p=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"修饰器"}},[t._v("修饰器")]),t._v(" "),n("p",[t._v("简单的描述:一个修饰器函数,参数是函数,返回一个运行了这个参数函数的跟参数函数保持相同的函数。")]),t._v(" "),n("p",[t._v("如果是接口,那么就是一个修饰器函数,参数是一个接口,返回值还是这个接口。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"done"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"具体案例"}},[t._v("具体案例")]),t._v(" "),n("p",[t._v("http 处理 cookie 和 header 的案例:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandleFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithHeader")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hello"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandleFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/s"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithCookie")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hello"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ListenAndServe")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":8080"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("hello")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fprintln")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithHeader")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("h http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Header")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Set")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Server"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"HelloServer"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("h")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithCookie")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("h http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ResponseWriter"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Request"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tcookie "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Cookie"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"auth"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Value"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"123456"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Path"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\thttp"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetCookie")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cookie"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("h")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"多修饰器的-pipeline-串型调用"}},[t._v("多修饰器的 pipeline (串型调用)")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Hander "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("DealWith")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("h http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("handlers "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("Hander"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("HandlerFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" handlers "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n d "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" handlers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("handlers"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n h "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("d")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("h"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" h\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("HandleFunc")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("DealWith")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("hello"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("WithCookie"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("WithHeader"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n http"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("ListenAndServe")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":8080"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/33.4d31d0db.js b/assets/js/33.4d31d0db.js new file mode 100644 index 000000000..8db1a67d7 --- /dev/null +++ b/assets/js/33.4d31d0db.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{461:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"pipeline"}},[t._v("pipeline")]),t._v(" "),a("p",[t._v("pipeline 模式,它将一系列的小命令组合成一个大的命令,它可以将***一个大命令拆分为一个一个的高内聚的小命令***,我们可以使用这一系列的小命令组合更多更复杂的命令。")]),t._v(" "),a("p",[t._v("下面给出一个需求,我们将这个需求写成 pipeline 的模式。")]),t._v(" "),a("p",[t._v("需求是:对一个 int 的切片做 “平方”,“过滤奇函数”,“求和” 的操作,并且使用 pipeline 的方式去调用这一系列的高内聚的小函数。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始函数")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("echo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" data "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 平方")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sq")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" in "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" v\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 过滤奇函数")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("odd")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" in "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" v\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 求和")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tsum "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" in "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tsum "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" v\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tout "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" sum\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" out\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" EchoFunction "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" PipeFunction "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// pipeline 处理")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Handle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e EchoFunction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ps "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("PipeFunction"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tch "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("e")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" ps "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tch "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ch\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// main函数")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("9")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tdata "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Handle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" echo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sq"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" odd"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sum"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("data"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/34.7610889f.js b/assets/js/34.7610889f.js new file mode 100644 index 000000000..1df990d6d --- /dev/null +++ b/assets/js/34.7610889f.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{462:function(t,s,n){"use strict";n.r(s);var a=n(36),p=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"k8s-visitor"}},[t._v("k8s visitor")]),t._v(" "),n("p",[t._v("这是一种将算法和数据结构分离的编程模式。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Visitor "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shap Shap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Shap "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Accept")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们创造一个函数类型,它接受一个接口作为参数。")]),t._v(" "),n("p",[t._v("我们定义刚才那个接口,并且在接口中我们定义一个函数,这个函数中的参数是刚才的函数类型。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" result1 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n data "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r result1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Accept")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v Visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" result2 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n data "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r result2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Accept")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v Visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们实现了两个 struct。")]),t._v(" "),n("p",[t._v("接下来,我们定义一些函数,这些函数是 visitor 函数。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("n1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shap Shap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("n2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shap Shap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("shap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("接下来我们在 mian 函数中调用这个 visitor 函数。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n r1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" result1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n r2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" result2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"shgopher"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n result "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Shap"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("r1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" result "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Accept")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Accept")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("数据是 r1,和 r2,算法是 n1 和 n2,这样,我们就可以将算法和数据给分开,互相不会有耦合。")])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/35.32a9ec30.js b/assets/js/35.32a9ec30.js new file mode 100644 index 000000000..c2f7873bf --- /dev/null +++ b/assets/js/35.32a9ec30.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{463:function(t,s,e){"use strict";e.r(s);var n=e(36),r=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"k8s-builder"}},[this._v("k8s builder")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/36.8d562ec5.js b/assets/js/36.8d562ec5.js new file mode 100644 index 000000000..133207e52 --- /dev/null +++ b/assets/js/36.8d562ec5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{464:function(t,s,n){"use strict";n.r(s);var a=n(36),r=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"综合题"}},[t._v("综合题")]),t._v(" "),n("blockquote",[n("p",[t._v("本内容选自 "),n("a",{attrs:{href:"https://github.com/kubernetes/kubernetes/blob/cea1d4e20b4a7886d8ff65f34c6d4f95efcb4742/staging/src/k8s.io/cli-runtime/pkg/resource/visitor.go",target:"_blank",rel:"noopener noreferrer"}},[t._v("k8s"),n("OutboundLink")],1)])]),t._v(" "),n("h2",{attrs:{id:"k8s-visitor-修饰器-pipeline"}},[t._v("k8s visitor + 修饰器 + pipeline")]),t._v(" "),n("p",[t._v("这种写法,以 k8s 的 visitor 作为主要的实现方法,修饰器和 pipeline 作为辅助的实现手法")]),t._v(" "),n("p",[t._v("首先我们实现这段代码的目的是为了将数据结构和算法分离,并且,我们希望每段的算法处理数据结构的一部分。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 行为")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" visitorFunc "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 抽象层")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Visitor "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("visitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 数据")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" info "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tyear "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\taddr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v visitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们基础部分已经写好了,这样就具备了基本的 visitor 的模式,接下来我们来写算法的实现")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 多态")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" OneDeal "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvisitor Visitor\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o OneDeal"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v visitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" o"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\te "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"one deal"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" e\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" twoDeal "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvisitor Visitor\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("o twoDeal"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v visitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" o"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\te "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"two deal"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" e\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("当算法搞定以后,我们在 main 调用一下:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\to "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" v Visitor "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" o\n\tv "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" OneDeal"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tv "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" twoDeal"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tl "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ti"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"liu"')]),t._v("\n\t\ti"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2020")]),t._v("\n\t\ti"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"beijing"')]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("l"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("可以看到,visitor,pipline,以及修饰器的模式都运用了")]),t._v(" "),n("ul",[n("li",[t._v("visitor:上面一个 type func,下面的 interface,连在一起就是 visitor 模式")]),t._v(" "),n("li",[t._v("pipline:可以看到 visitor 的变量在不停的传递,然后调用的时候肯定会一直的调用不同的 visit func 函数,这就是 pipline")]),t._v(" "),n("li",[t._v("修饰器:不同的 function,在不停的增加内容,并且输出的还是这个 function,这就是修饰器模式")])]),t._v(" "),n("p",[t._v("可以看到,这个模式下,visitor 是主要的模式,其他的模式都是因这个模式而附带的效果,所以也可以说,visitor 自带 pipline 和修饰器模式,所以这种写法就单单的只是 visitor 而已。")]),t._v(" "),n("p",[t._v("接下来,我们将修饰器模式作为主要的模式,另外加上 visitor 和 pipline")]),t._v(" "),n("h2",{attrs:{id:"修饰器-k8s-visitor-pipeline"}},[t._v("修饰器 + k8s visitor + pipeline")]),t._v(" "),n("p",[t._v("同样的我们需要先构造一个 visitor 系统")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" VisitorFunc "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Visitor "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("VisitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Info "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tyear "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\taddr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v VisitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("接下来我们创建一个修饰器系统")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" VisitorBox "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvisitor Visitor "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 行为")]),t._v("\n\tvisitorFucs "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("VisitorFunc "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 代表数据的桥梁")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewVisitorBox")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v Visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fn "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("VisitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Visitor "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fn"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" v\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" VisitorBox"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("visitorFucs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" fn"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("vi VisitorBox"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v VisitorFunc"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" vi"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("visitor"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" e "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" e\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("v")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" vi"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("visitorFucs "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" vi"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("visitorFucs"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("k"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("接下来让我们调用一下")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\tloadFile "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tinfo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"li"')]),t._v("\n\t\tinfo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n\t\tinfo"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bj"')]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfunc1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfunc2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfunc3 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\tinfo "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Info"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" v Visitor "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" info\n\tv "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewVisitorBox")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" func1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" func2"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" func3"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Visit")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("loadFile"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这种写法跟上面的写法改变之处在于创建了一个修饰器的 struct,并且装在了一个 pipline 的切片,然后我们就不用依次调用不同的算法结构体了,我们只需要在 new box 的时候将要执行的函数放入进去即可。")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/37.18cb13d8.js b/assets/js/37.18cb13d8.js new file mode 100644 index 000000000..295849e7c --- /dev/null +++ b/assets/js/37.18cb13d8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{465:function(t,s,a){"use strict";a.r(s);var n=a(36),r=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"变量声明"}},[t._v("变量声明")]),t._v(" "),a("h2",{attrs:{id:"变量声明符号-var-和"}},[t._v("变量声明符号 "),a("code",[t._v("var")]),t._v(" 和 "),a("code",[t._v(":=")])]),t._v(" "),a("p",[t._v("在 go 语言中,我们使用 "),a("code",[t._v("var")]),t._v(" 来表示声明一个变量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),t._v("\n")])])]),a("p",[t._v("这就是一个标准的变量声明方式,var 符号在最前面,接着就是变量 a,变量后面紧跟着是变量的类型,这里是 string 类型,也就是字符串类型,"),a("code",[t._v("=")]),t._v(" 后面是要赋值的具体值")]),t._v(" "),a("p",[t._v("我们也可以直接声明不赋予初始值,go 语言默认,声明即赋予初始值,那么这里的字符串类型初始值就是一个空字符串 "),a("code",[t._v('""')])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n")])])]),a("p",[t._v("go 语言具有类型推断能力,所以我们可以省略类型,让 go 语言的编译器去推断类型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),t._v("\n")])])]),a("p",[t._v("编译器会自动推断 a 为 string 类型")]),t._v(" "),a("p",[t._v("在函数体内部 (这是一个先决条件) 我们"),a("strong",[t._v("也")]),t._v("可以使用省略的写法,就是使用一个符号 "),a("code",[t._v(":=")]),t._v(" 来充当 "),a("code",[t._v("var")]),t._v(" 的角色,也就是初始化的工作,比如说")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("可以看到,整个的用法是 "),a("code",[t._v("[变量] [:=] [初始值]")]),t._v(" 这三者缺一不可,而且还不能多,不能在 a 后面带有类型,不能省略初始值,且仅限于函数/方法内部使用")]),t._v(" "),a("p",[t._v("go 语言支持多变量同时赋值")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" d "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),t._v("\n\na"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n")])])]),a("p",[t._v("其中,使用 var 进行声明的时候,如果是多个变量同时声明,必须是相同类型;使用 "),a("code",[t._v(":=")]),t._v(" 进行多变量赋值时,多个变量可以不同类型,因为全靠编译器推断")]),t._v(" "),a("h2",{attrs:{id:"常见的变量声明方式"}},[t._v("常见的变量声明方式")]),t._v(" "),a("p",[t._v("从广义上来说,go 语言只有两种变量,包一级的变量和函数一级的变量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" DefaultValue "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewMethod")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("其中 "),a("code",[t._v("DefaultValue")]),t._v(" 就是包级变量,"),a("code",[t._v("n")]),t._v(" 就是函数级变量 (也是形式变量)")]),t._v(" "),a("p",[t._v("下面我列举一些常见的声明方式")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//包级变量")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n d "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//仅限函数内部使用,变量后面不能有类型")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数级变量")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello world"')]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//自动推断变量类型")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("可以说声明的方式很多,不过呢,在一个项目中应该尽量保证声明方式的一致性,因为可以加强代码的统一性,减少理解代码的难度。")]),t._v(" "),a("h2",{attrs:{id:"go-语言可导出变量"}},[t._v("go 语言可导出变量")]),t._v(" "),a("p",[t._v("go 语言跟一般的语言不同,它使用变量"),a("strong",[t._v("首")]),t._v("字母的大小写来区分变量的可导出性质,大写 (如果使用中文作为变量名称,默认是可导出的) 代表可导出,小写代表仅限包内部使用 (包这一级,多个文件只要是同一个包就可以使用)")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" Example\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" OutPutName "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0o77")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" inName "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x99")]),t._v("\n")])])]),a("p",[t._v("其中 "),a("code",[t._v("OutPutName")]),t._v(" 是一个可导出的变量,"),a("code",[t._v("inName")]),t._v(" 是不可导出变量")]),t._v(" "),a("p",[t._v("go 语言还拥有比如函数,方法,结构体,接口,等等各类型的组件,这里你可以先不懂到底是什么,你先有一个印象,但凡首字母是大写的都是可以导出的,小写就是包内使用,没错,go 语言就是这么简单")]),t._v(" "),a("h2",{attrs:{id:"包级变量"}},[t._v("包级变量")]),t._v(" "),a("p",[a("code",[t._v("第一种声明形式")]),t._v(":"),a("strong",[t._v("声明的同时,显式初始化")])]),t._v(" "),a("ul",[a("li",[a("code",[t._v('var a = method("t")')]),t._v(" go 编译器根据右侧的返回值自动确定左侧变量的类型")]),t._v(" "),a("li",[a("code",[t._v("var a = 3.14")]),t._v(" 在没有具体返回值,没有具体类型的情况下,go 赋予它默认类型,比如 float 的默认类型就是 float64,int 类型的默认类型就是 int")]),t._v(" "),a("li",[t._v("如果要显式的赋予类型,并且保证命名的一致性 "),a("code",[t._v("var a int = 12")]),t._v(" 的行为应该避免,应该写成 "),a("code",[t._v("var a = int(12)")]),t._v(" 用来保证一致性"),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.14")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"EOF"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])])])]),t._v(" "),a("p",[a("code",[t._v("第二种声明形式")]),t._v(":"),a("strong",[t._v("声明但是延迟初始化")])]),t._v(" "),a("p",[t._v("只有 "),a("code",[t._v("var a int64")]),t._v(" 这一种方式,不过呢,go 语言的声明是直接赋予零值的,比如说这里的 a 默认就是 "),a("code",[t._v("0")])]),t._v(" "),a("p",[t._v("go 语言变量声明的聚集和就近原则:将同一类型的放在一个 var() 内部;或者另一种分类方法:将有初始值的放在一个 var 里,将延迟初始化的放在另一个 var 里。")]),t._v(" "),a("p",[t._v("分类一")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\na "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\nb "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\nc "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\nd "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\ne "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\nf "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("分类二")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),t._v("\n c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"string"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n d "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n c "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n f "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("接下来谈一谈就近原则,变量的声明和变量的使用尽量的近,不要都声明在头部,如果一个变量被全局大量使用,那么可以放在头部,如果就是仅仅使用少量的次数,还是应该在使用的前面就进进行声明")]),t._v(" "),a("h2",{attrs:{id:"函数级变量"}},[t._v("函数级变量")]),t._v(" "),a("p",[a("code",[t._v("第一种声明形式")]),t._v(":"),a("strong",[t._v("延迟初始化")])]),t._v(" "),a("p",[t._v("在函数体内使用 var")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("如果变量特别多,也可以使用 "),a("code",[t._v("var()")]),t._v(" 的方法在函数内部使用")]),t._v(" "),a("p",[a("code",[t._v("第二种声明形式")]),t._v(":"),a("strong",[t._v("声明且显式初始化的局部变量")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("method1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("int32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 改变默认类型")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"小心-shadow-的变量"}},[t._v("小心 shadow 的变量")]),t._v(" "),a("p",[t._v("我们知道,当有两个两个以上的变量在赋值时,如果其中有一个未被提前声明,那么就需要使用 "),a("code",[t._v(":=")]),t._v(",这个时候系统会自动判断有哪些未提前声明,然而有一种场景下系统会发生误判,准确的来说这是一种歧义,系统的判断会跟程序员的心理不一致,出现了变量 shadow 的行为,让我们看一下代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// tracing 为 bool 类型")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("在外层,a 已经提前声明,但是在 if 这个作用域中,由于 err 并未提前声明,所以使用了 "),a("code",[t._v(":=")]),t._v(",由于系统"),a("strong",[t._v("无法获知")]),t._v("这里的 a 是否需要再次声明,所以 go 语言默认 a 是一个新的变量,这样外层的 a 就无法得到新的值,外层 a 也就被内层的 a 给 shadow 了。")]),t._v(" "),a("p",[t._v("如果想改变这种 bug,我们可以将 err 也提前声明:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// tracing 为 bool 类型")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("或者也可以改变内部的变量名称,来改变这种 shadow:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// tracing 为 bool 类型")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" tracing"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ai"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ai\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n ai"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Method1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" ai\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://juejin.cn/post/7241452578125824061")])])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/38.53670642.js b/assets/js/38.53670642.js new file mode 100644 index 000000000..0f2d9c03d --- /dev/null +++ b/assets/js/38.53670642.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{467:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"复合字面量作为构造器"}},[t._v("复合字面量作为构造器")]),t._v(" "),a("p",[t._v("go 的复杂类型经常采用复合字面量的方式进行初始化,例如 struct,数组,slice map,比如:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi there"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\narr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nsl "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nm "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当 struct 需要使用 "),a("code",[t._v("{key :value}")]),t._v(" 来构建时,即使可以按照顺序省略掉 key,也千万不要这么做,加上 key 就可以将结构体的"),a("strong",[t._v("使用和设计解耦")]),t._v(",可以乱序进行 struct 的赋值,即使某些字段没有赋值,那么系统也会自动的赋予它的初始值。")]),t._v(" "),a("p",[t._v("当获取 struct 的指针时,最好是在字面量上取 "),a("code",[t._v("&")]),t._v(",比取变量的指针地址更加符合具体的含义,即:获取结构体的指针类型并且复制给一个变量。比如 "),a("code",[t._v("a := &Some{}")]),t._v(" 就比 "),a("code",[t._v("a := Some{} , &a")]),t._v(" 更好,另外当我们要获取一个结构体的初始值的时候使用 "),a("code",[t._v("a := Some{}")]),t._v(" 比 "),a("code",[t._v("a = new(Some)")]),t._v(" 更加常用。")]),t._v(" "),a("p",[t._v("数组和切片的复合体跟 struct 不同,它使用下标来作为 key,它们几乎不会使用 key:value 的形式,不过下面两种情况还是会出现的:")]),t._v(" "),a("ul",[a("li",[t._v("为了省略中间元素")]),t._v(" "),a("li",[t._v("为了显著的体现下标")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//为了省略中间元素")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token char"}},[t._v("'a'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token char"}},[t._v("'b'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里 '' 代表了 rune类型")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//为了显著的体现下标")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" data "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当 slice 和 array 含有复合类型的时候,可以直接省略复合类型的类型名称,直接用 "),a("code",[t._v("{}")]),t._v(" 即可")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Some"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tname"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"12"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里尽量不要省略字段名称,方便解除跟结构体设计时的耦合")]),t._v("\n\t\t\tyear"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tname"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"12"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t\tyear"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Some "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tyear "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tp "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("map 字面量作为初始值的时候,非常自然的就会使用 key-value 的方式,需要注意两点")]),t._v(" "),a("ul",[a("li",[t._v("当 value 或者 key 是复合类型的时候 (key 必须是"),a("RouterLink",{attrs:{to:"/基础/其他内容/#go可比较类型"}},[t._v("可比较的")]),t._v(") 可以省略复合类型的类型名称")],1),t._v(" "),a("li",[t._v("如果是指针类型,那么连指针也可以省略")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/39.9c8315fb.js b/assets/js/39.9c8315fb.js new file mode 100644 index 000000000..5f2dbf6e5 --- /dev/null +++ b/assets/js/39.9c8315fb.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{468:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"go-语言常量"}},[t._v("go 语言常量")]),t._v(" "),a("p",[t._v("go 使用 const 来声明常量,常量表达式的运算在编译期就可以完成了,并且 go 常量是类型安全的,编译器优化友好的元素。")]),t._v(" "),a("p",[t._v("常量中的数据类型只可以是布尔、数字 (整数、浮点和复数) 以及字符串型。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n startOne "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n startTwo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),t._v("\n startThree "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.14")]),t._v("\n isTrue "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n hi "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("go 推崇无类型常量,这主要是因为 go 不支持隐式的类型转化,只能显式转换,所以一旦常量给定类型,那么它跟变量之间或许就要将常量转化类型才能进行运算。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tPI "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.14")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\t\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" PI\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" PI\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("可以看到,如果是没有类型的常量,可以非常灵活的赋予 float32 或者 float64 都可以。")]),t._v(" "),a("h2",{attrs:{id:"局部常量"}},[t._v("局部常量")]),t._v(" "),a("p",[t._v("在 Go 中,局部常量在编译期常量折叠 (compile-time constant folding) 时会被编译器处理成字面值,因此局部常量在编译时会被编译。")]),t._v(" "),a("p",[t._v("例如,下面的代码定义了一个局部常量 x,并使用它来初始化一个变量 y:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("42")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("y"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("在编译时,x 将被处理成字面值 42,因此编译器将 y 初始化为 84,如下所示:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("84")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("y"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("可见,局部常量在编译期已经被折叠成了字面值,因此在运行时不会再进行计算了。")]),t._v(" "),a("h2",{attrs:{id:"常量不可包含计算"}},[t._v("常量不可包含计算")]),t._v(" "),a("p",[t._v("在 Go 中,常量必须在编译时就可以确定其值。因此,常量的值必须是一个编译时的常量表达式,不能包含运行时的计算。")]),t._v(" "),a("p",[t._v("不过,常量表达式可以包含一些简单的运算,例如加、减、乘、除、取模等算术运算,以及位运算、逻辑运算等。例如:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 常量表达式,结果为 5")]),t._v("\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("%")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 常量表达式,结果为 0")]),t._v("\n z "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 常量表达式,结果为 true")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("常量表达式还可以使用一些内置函数,例如 "),a("code",[t._v("len")]),t._v("、"),a("code",[t._v("cap")]),t._v("、"),a("code",[t._v("make")]),t._v("、"),a("code",[t._v("new")]),t._v(" 等,以及可以在编译期计算的一些标准库函数,例如 "),a("code",[t._v("math.Sin")]),t._v("、"),a("code",[t._v("math.Pi")]),t._v(" 等。")]),t._v(" "),a("p",[t._v("总之,常量必须在编译期就可以确定其值,因此不能包含运行时的计算,但可以包含一些简单的算术、位运算、逻辑运算等。")]),t._v(" "),a("h2",{attrs:{id:"枚举常量-iota"}},[t._v("枚举常量 iota")]),t._v(" "),a("p",[t._v("go 语言提供隐式重复前一个非空表达式的机制")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\tPI "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.14")]),t._v("\n\ta\n\tb\n\tc\n\td\n\te\n\tf\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("PI"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码将会全部输出 3.14")]),t._v(" "),a("p",[t._v("iota 是 go 语言的一个预定义标识符,它表示 const 声明块中,每一个常量所处位置的偏移量,它本身也是一个无类型的常量,它的初始值是 0,意思是说此处的 iota 跟第一行比偏移了 0 个位置")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<<")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n b\n c\n d\n e\n f\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("同一行的常量 iota 值是一样的,可以理解为偏移量相同")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("d\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("如果要让 iota 的初始值是 1,那么可以这么做")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n a\n b\n c\n d\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("iota 只需要在一个 const 群中出现一次即可,出现多次跟出现一次的效果一样")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 一样")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n b\n c\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("当 iota 群中出现异类该如何处理")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n d\n e\n f\n g\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("答案就是异类输出自己的,其它的常量不受影响,比如这里的输出就是 "),a("code",[t._v("0 12 2 3 4 5 6")]),t._v(",只要记住 iota 是偏移位置就可以理解为什么是这么输出的了。")]),t._v(" "),a("p",[t._v("如果不考虑常量的灵活性,极致追求安全性,那么也可以给 iota 常量加上类型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("iota")]),t._v("\n b\n c\n d\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("这种就要求变量类型必须是 int 才能被这些枚举类型接纳,但是一般常量还是用无类型的较为常见。")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/4.a73c4d70.js b/assets/js/4.a73c4d70.js new file mode 100644 index 000000000..e3725fc52 --- /dev/null +++ b/assets/js/4.a73c4d70.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{400:function(t,e,a){},433:function(t,e,a){"use strict";a(400)},437:function(t,e,a){"use strict";a.r(e);var n={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted:function(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(433),a(36)),s=Object(i.a)(n,(function(){var t=this.$createElement;return(this._self._c||t)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/40.3bf1fd84.js b/assets/js/40.3bf1fd84.js new file mode 100644 index 000000000..ac8b8f423 --- /dev/null +++ b/assets/js/40.3bf1fd84.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{469:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"求值顺序"}},[t._v("求值顺序")]),t._v(" "),a("h2",{attrs:{id:"包级变量声明语句中的表达式求值顺序"}},[t._v("包级变量声明语句中的表达式求值顺序")]),t._v(" "),a("ul",[a("li",[t._v("按照变量的声明顺序,"),a("strong",[t._v("从上到下,从左到右")]),t._v(",进行求值")]),t._v(" "),a("li",[t._v("如果 a 求值时有依赖项 b,或者是间接的依赖项 b,那么先求值 b")]),t._v(" "),a("li",[t._v("在求值的过程中会一直对于变量是否拥有依赖项进行查找,直到查询到没有依赖项的变量将其求值,然后重复这个查找,最后全部求值。")]),t._v(" "),a("li",[t._v("同一个包不同文件的处理,原则上如果 a 文件在 b 文件前面,那么 a 文件中的所有变量求值比 b 文件中的更早,除非 a 文件变量依赖了 b 中的变量。")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" b\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n c "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n d "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n d "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" d\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("ol",[a("li",[t._v("查找没有依赖项的变量将其求值,这一轮中是 d,此时只有 [d=3]")]),t._v(" "),a("li",[t._v("查找没有依赖项的变量进行求值,这一轮中 a 还是不符合,但是 b 符合了,所以现在是 [b=4,d=4]")]),t._v(" "),a("li",[t._v("查找没有依赖项的变量进行求值,这一轮中是 _,此时 [b=4,d=5]")]),t._v(" "),a("li",[t._v("查找没有依赖项的变量进行求值,这一轮中是 c,此时 [b=4,c=6,d=6]")]),t._v(" "),a("li",[t._v("查找没有依赖项的变量进行求值,这一轮中是 a,此时 [a=10,b=4,c=6,d=6]")])]),t._v(" "),a("p",[t._v("输出 10 4 6 6")]),t._v(" "),a("h2",{attrs:{id:"普通求值顺序"}},[t._v("普通求值顺序")]),t._v(" "),a("p",[t._v("这包括了,函数,方法,channel 中的求值顺序。")]),t._v(" "),a("ul",[a("li",[t._v("规定是从左到右")])]),t._v(" "),a("p",[t._v("y[f()],ok = g(h(),i()+x[j()], <-c),k()")]),t._v(" "),a("p",[t._v("这个语句的求值顺序就是 f() h() i() j() x[] <-c g() k()")]),t._v(" "),a("p",[t._v("普通值求值顺序和包级变量求值依赖顺序一起使用的时候,包级变量优先级更高,并且它在导入包的时候就已经求值了,而普通的求值顺序只有调用的时候才会求值。")]),t._v(" "),a("h2",{attrs:{id:"赋值语句中的求值顺序"}},[t._v("赋值语句中的求值顺序")]),t._v(" "),a("p",[t._v("赋值语句求值有两个阶段 --- “先算后赋”")]),t._v(" "),a("ul",[a("li",[t._v("对等号左边的下标表达式,指针解引用表达式,以及等号右边的表达式,从左到右的依次求值")]),t._v(" "),a("li",[t._v("按照从左到右的顺序将变量进行赋值")])]),t._v(" "),a("p",[t._v("例如")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("n0 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\nn1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\nn0"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("n1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" n0"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("n1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("n0\n")])])]),a("ol",[a("li",[t._v("左边没有要处理的表达式,右侧有,那么第一个位置就是 n0+n1,因为 n0 和 n1 已经存在了初始化的内容了,所以这里直接就是 3,no = 1,这时 n0 和 n1 还是 1 2,因为还没有赋值呢。")]),t._v(" "),a("li",[t._v("开始赋值:右侧一个是 3 一个是 1,那么最新的 no 和 n1 就是 3 1")])]),t._v(" "),a("h2",{attrs:{id:"switch-select-中的表达式的求值顺序"}},[t._v("switch select 中的表达式的求值顺序")]),t._v(" "),a("p",[t._v("这里主要想说一下惰性求值:就是只有需求的时候才会进行求值")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"--"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("首先先求值的是 switch 后面的 f (2)")]),t._v(" "),a("p",[t._v("然后对 f(1) f(2) 求值;f(3) 不会求值,因为 f (2) 已经满足了要求。")]),t._v(" "),a("p",[t._v("在 select case 中,如果 case 中存在表达式,最开始会依次计算所有的表达式,只有一种除外,收 case 中,位于左侧的表达式,它会在接受数据之前才会计算,然后赋值。")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://go.dev/ref/spec#Order_of_evaluation")]),t._v(" "),a("li",[t._v("https://book.douban.com/subject/35720728/ 132 页 - 142 页")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/41.73deb46e.js b/assets/js/41.73deb46e.js new file mode 100644 index 000000000..09914f803 --- /dev/null +++ b/assets/js/41.73deb46e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{471:function(t,s,a){"use strict";a.r(s);var n=a(36),p=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"泛型"}},[t._v("泛型")]),t._v(" "),a("p",[a("strong",[t._v("导读:")])]),t._v(" "),a("ul",[a("li",[t._v("约束")]),t._v(" "),a("li",[t._v("使用方法")]),t._v(" "),a("li",[t._v("实现原理")]),t._v(" "),a("li",[t._v("跟其它语言的泛型进行对比")]),t._v(" "),a("li",[t._v("用例子学泛型")]),t._v(" "),a("li",[t._v("issues")])]),t._v(" "),a("blockquote",[a("p",[t._v("泛型需满足 "),a("code",[t._v("go1.18+")])])]),t._v(" "),a("h2",{attrs:{id:"约束"}},[t._v("约束")]),t._v(" "),a("p",[t._v("go 使用 interface 作为约束,约束的意思是约束了这个泛型都具有哪些实际类型。所以可以理解为,go 将 interface 的职责给扩展了,让接口不仅仅作为接口 --- 解耦的,抽象化的结构体,还具有了约束,对于类型的约束作用。")]),t._v(" "),a("p",[t._v("go 可以将所有的接口 (包括经典接口,和泛型以后的接口) 都用作约束,但是可以不代表应该,要有选择的去使用约束,但是约束并不是都可以作为传统的接口来使用的,例如传统的接口只能存在方法,并不能存在类型,"),a("strong",[t._v("只要存在类型就自动归纳为约束")])]),t._v(" "),a("p",[t._v("综上所述,第一,约束的概念大于接口,只有传统接口可以作为抽象类型去使用,约束只能存在于函数方法或者类型之中,不能单独使用。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 不能在类型约束之外使用类型 a:接口包含类型约束")]),t._v("\ncannot use "),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("type")]),t._v(" a outside a "),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("type")]),t._v(" constraint: interface contains "),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("type")]),t._v(" constraints\n\n")])])]),a("p",[t._v("第二,不要把传统接口用在约束的地方,这种用法是不合适的,通常来说传统接口的模式就用作抽象类型的解耦即可 (用了也不错,只是不建议)。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不建议")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Writer "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Get"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T Writer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"泛型是类型-约束是类型的约束"}},[t._v("泛型是类型,约束是类型的约束")]),t._v(" "),a("p",[t._v("请认识到,泛型是一种类型,约束是一种类型的约束,请不要把约束当作泛型。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" st "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这里 st 约束拥有 int 和 string,请注意这里的 st 是约束,不是泛型类型")]),t._v(" "),a("p",[t._v("go 内置了很多约束,比如说 any 和 comparable,意思是任何类型和可以比较的类型。以后***应该***会有一个新的内置约束的包叫做 "),a("code",[t._v("package constraints")]),t._v(" 例如 any comparable,Ordered 等等约束都会内置到标准库中")]),t._v(" "),a("p",[t._v("约束不仅仅可以单独写出来,还可以内置于函数内部。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" B "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("j B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这种形式下,T 和 B 的约束就是仅限此函数使用")]),t._v(" "),a("p",[t._v("下面我们看一种形式,这种情况下约束的不仅仅是 string 和 int,而是包含了底层是他们的所有数据,比如说 "),a("code",[t._v("type DD int")]),t._v(" 也符合这个约束,请记住只能使用在底层类型上,如果使用 "),a("code",[t._v("~DD")]),t._v(" 是不被允许的")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" st "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"约束的嵌套"}},[t._v("约束的嵌套")]),t._v(" "),a("p",[t._v("约束跟接口是一样的也是可以嵌套的")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ComparableHasher "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tcomparable\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Hash")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ImpossibleConstraint "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tcomparable\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这里的意义就是 "),a("strong",[t._v("and")]),t._v(" 的意思就是说这个约束是可以比较的还是必须得支持 "),a("code",[t._v("hash()uintptr")])]),t._v(" "),a("p",[t._v("下面这种方式也是可以的")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" NumericAbs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("complex64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("complex128")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Abs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("上面的类型意思是满足数字类型,下面的意思是满足这个方法,所以最终实现这个约束的对象就是一个数字类型,并且实现了这个接口的 "),a("code",[t._v("Abs()T")]),t._v(" 方法。")]),t._v(" "),a("h2",{attrs:{id:"泛型-2"}},[t._v("泛型")]),t._v(" "),a("p",[t._v("当结构体中使用泛型的时候,泛型不能直接作为嵌入使用")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Lockable"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tT "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 正确的方法应该是 t T ; 将 T 作为类型参数,不可直接嵌入")]),t._v("\n\tmu sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("错误提示:"),a("code",[t._v("embedded field type cannot be a (pointer to a) type parameter")]),t._v(";"),a("code",[t._v("嵌入式字段类型不能是(指向)类型参数")])]),t._v(" "),a("p",[t._v("我们再看一下当泛型结构体嵌入到其它结构体中如何使用")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tT T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里使用 A[T] 输入了实际类型,")]),t._v("\n\tA"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tT T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("可以看出关键点,泛型结构体被嵌入其它结构体的时候,泛型要给实际的类型才可以")]),t._v(" "),a("p",[t._v("结构体泛型和方法中的泛型做对比:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("方法里的泛型是可以直接从 struct 定义的地方继承这个泛型 T 的,当这个结构体使用时,指定实际的类型即可。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" d1 d\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\td1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只要没有类型就不是约束,是接口,在go语言中,接口可以充当一个一般类型")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" d "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tT T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("约束里的泛型同样不能直接嵌入使用")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tT\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("错误提示:"),a("code",[t._v("cannot embed a type parameter")])]),t._v(" "),a("p",[t._v("泛型只能充当类型:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" EmbeddedParameter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),t._v(" \n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("me")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T \n")])])]),a("p",[t._v("使用约束中的泛型还是需要注意一下的,稍微有些复杂:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Abs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T EmbeddedParameter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("解释一下,中括号里面泛型的两个 T 表达的意思是不一样的,后面的 T 表达的是"),a("strong",[t._v("约束里的泛型")]),t._v(",表示 any,前面的 T 表示的是满足后面的这个约束的类型 T,但是这里注意,后面 T 虽然之前定义的时候是 any 但是这里被赋予为 T 之后,改变了,改变为了必须满足约束 "),a("code",[t._v("EmbeddedParameter")]),t._v(" 的类型,如果说的通俗点,从 any 变成了,满足 "),a("code",[t._v("int | uint and 实现 me()T方法")]),t._v(" 后文会有代码进行解释。")]),t._v(" "),a("p",[t._v("当然了,后面的 T 没有也行,如果没有后面的 T 就是相当于不改变后面的 T 的约束类型了")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Differ"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T1 any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Diff")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" IsClose"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T2 Differ"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Diff")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("当使用了泛型之后,是无法使用断言的,这是非法的,那么如果一定要在运行时的时候去判断类型怎么办呢?答案就是转变成 "),a("code",[t._v("any")]),t._v(" (type any = interface {}) 即可,因为我们知道任何对象都已经实现了空接口,那么就可以被空接口去转化")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" GeneralAbsDifference"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T Numeric"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int16")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint16")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OrderedAbsDifference")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("complex64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("complex128")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ComplexAbsDifference")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("下面看一下别名的真实类型是泛型的情况")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" AliasA "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 错误 ❌")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" AliasA "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 正确")]),t._v("\n")])])]),a("p",[t._v("其中错误的问题是别名不能直接使用泛型类型 "),a("code",[t._v("cannot use generic type A[T any] without instantiation")]),t._v(",它需要泛型实际赋值")]),t._v(" "),a("h2",{attrs:{id:"使用方法"}},[t._v("使用方法")]),t._v(" "),a("p",[t._v("下面展示一下 go 泛型的基本使用方法")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%v"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" t\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这是函数使用泛型的写法,当函数使用泛型的时候,需要在变量前使用中括号标注泛型的具体约束,然后后面才能使用这个泛型类型,使用泛型函数的时候,中括号是可以省略的 "),a("code",[t._v("Age(12)")]),t._v(" 系统会自动推算泛型的具体实现。顺便说一下,泛型类型使用 "),a("code",[t._v("%v")]),t._v(" 作为占位符,也就是默认的类型,泛型类型无法进行断言。")]),t._v(" "),a("p",[t._v("当然了,我么也可以不用 any,自定义一个约束")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tAge"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" st "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T st"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("看完了在函数内的泛型,我们在看一下在方法中如何使用泛型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" dd DD"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tdd"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("TT")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tI T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("I"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" DD"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dd "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("DD"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("TT")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("dd"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("在 age 结构体声明的时候,声明了一个泛型 T,在 struct 体内就可以使用这个 T,方法内部仅可以使用定义在这个结构体对象上的泛型")]),t._v(" "),a("p",[t._v("下面是一个"),a("strong",[t._v("错误案例")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Post"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("B any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b B"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("I"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" \n")])])]),a("p",[a("code",[t._v("syntax error: method must have no type parameters")])]),t._v(" "),a("p",[t._v("接下来我们看一下,如何使用有类型也有方法的泛型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" d DDD\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" i DDD\n\td "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\tio "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" AbsDifference"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("DDD"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" DDD "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ddd DDD"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Abs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" DDD "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ddd "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" ddd\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" NumericAbs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("complex64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("complex128")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Abs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// AbsDifference computes the absolute value of the difference of")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a and b, where the absolute value is determined by the Abs method.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" AbsDifference"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T NumericAbs"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\td "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" b\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" d"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Abs")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"实现原理"}},[t._v("实现原理")]),t._v(" "),a("p",[t._v("泛型的第一种方法是在编译这个泛型时,使用一个字典,里面包含了这个泛型函数的全部类型信息,然后当运行时,使用函数实例化的时候从这个字典中取出信息进行实例化即可,这种方法会导致执行性能下降,一个实例化类型 "),a("code",[t._v("int, x=y")]),t._v(" 可能通过寄存器复制就可以了,但是泛型必须通过内存了 (因为需要字典进行运行时赋值),不过好处就是不浪费空间")]),t._v(" "),a("p",[t._v("还有一种方法就是把这个泛型的所有类型全部提前生成,这种方法也有一个巨大的缺点就是代码量直线上升,如果是一个包的情况下还能根据具体的函数调用去实现该实现的类型,如果是包输出的的情况下,那么就得不得不生成所有的类型。")]),t._v(" "),a("p",[t._v("所以将两者结合在一起或许是最好的选择。")]),t._v(" "),a("p",[t._v("这种方法是这样的,如果类型的内存分配器/垃圾回收器呈现的方式一致的情况下,只给它生成一份代码,然后给它一个字典来区分不同的具体行为,可以最大限度的平衡速度和体积")]),t._v(" "),a("h2",{attrs:{id:"跟其它语言的泛型进行对比"}},[t._v("跟其它语言的泛型进行对比")]),t._v(" "),a("ul",[a("li",[t._v("c 语言:本身不具有泛型,需要程序员去实现一个泛型,实现复杂,但是不增加语言的复杂度 (换言之只增加了程序员的)")]),t._v(" "),a("li",[t._v("c++和 rust:跟 go 基本保持一种方式,就是增加编译器的工作量")]),t._v(" "),a("li",[t._v("Java:将泛型装箱为 object,在装箱和拆箱擦除类型的过程中,程序执行效率会变低")])]),t._v(" "),a("h3",{attrs:{id:"为什么-java-编译器不在编译期就完成泛型的装箱操作呢"}},[t._v("为什么 Java 编译器不在编译期就完成泛型的装箱操作呢?")]),t._v(" "),a("p",[t._v("主要有以下几个原因:")]),t._v(" "),a("ol",[a("li",[a("p",[t._v("编译期装箱需要编译器对代码细节有完整信息。但是泛型类型信息可能来自其他模块或第三方库,编译器难以完整获取。")])]),t._v(" "),a("li",[a("p",[t._v("即使编译器可以提前装箱,也需要代码里有大量反射样板代码来还原原始泛型类型,违背泛型设计初衷。")])]),t._v(" "),a("li",[a("p",[t._v("编译期装箱也无法很好处理运行期检查和转换的各种边界情况。")])])]),t._v(" "),a("h2",{attrs:{id:"用例子学泛型"}},[t._v("用例子学泛型")]),t._v(" "),a("p",[t._v("理论学习完了,不使用例子进行复习的话会忘的很快的。跟着我看几个例子吧")]),t._v(" "),a("h3",{attrs:{id:"函数泛型-map-filter-reduce"}},[t._v("函数泛型 "),a("code",[t._v("map-filter-reduce")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvM "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" i\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"map的结果是:%v"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vM"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tvF "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" Filter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" t "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"filter的结果是:%v"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vF"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tvR "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" Reduce"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tt"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bb"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"7i"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"8i"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"u4i"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"uei"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"uwi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"uti"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" year"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v Value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Result "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" r\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"reduce的结果是:"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vR"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Map:类似于洗菜,进去的菜和出来的菜不一样了所以需要两种种类")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Map"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" T2 any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T2 "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tresult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Filter:类似于摘菜,进去的菜和出来的菜是一种,不过量减少了")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Filter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" result "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Reduce:类似于做菜,将菜做成一道料理,所以需要两种类型")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Reduce"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" T2 any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" zero T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T2 "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" zero\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" result\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Value "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tyear "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Result "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tvalue "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("code",[t._v("map的结果是:[2 4 6 8 10] filter的结果是:[3 4 5] reduce的结果是: 36")])]),t._v(" "),a("h3",{attrs:{id:"例子二-方法上的泛型-sets"}},[t._v("例子二:方法上的泛型 "),a("code",[t._v("sets")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里 Sets的具体类型和Make的具体类型都是int,所以可以正常赋值")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Contains")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Iterate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sets 一个key 存储对象")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T comparable"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Make 实例化一个map")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Make"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("D comparable"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("D"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 泛型就像一个管道一样,只要实例化的时候管子里的东西一致,那么就是一根管子")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("D"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Add 向这个sets添加内容")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// delete ,从这个sets中删除内容")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Contains 播报t是否属于这个sets")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Contains")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ok\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//Len sets拥有的长度")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Iterate 迭代器,并且给予每个元素功能")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Sets"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Iterate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("code",[t._v("map[1:{} 2:{}] false 2 1 2 map[1:{} 2:{}] map[1:{}]")])]),t._v(" "),a("h3",{attrs:{id:"例子三-外部定义的约束-实现一个sort接口类型"}},[t._v("例子三:外部定义的约束 "),a("code",[t._v("实现一个sort接口类型")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello, 世界"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ~ 代表只要底层满足这些类型也可以算满足约束")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Ordered "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("\n\t\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" orderedSlice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T Ordered"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s orderedSlice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s orderedSlice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Less")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" j "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s orderedSlice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Swap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" j "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" OrderedSlice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T Ordered"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tsort"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sort")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("orderedSlice"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),a("h3",{attrs:{id:"关于泛型中的零值"}},[t._v("关于泛型中的零值")]),t._v(" "),a("p",[t._v("在 go 里面对泛型的零值并没有一个所谓的泛型零值可以使用,需要根据不同的实践去实现,比如")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Aget"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tt "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("T\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 根据实际判断,如果a的t不等于nil再返回,如果是nil就返回一个T类型的nil(意思就是只声明)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Aget"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Approach")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("t "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("t\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" r T\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" r\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("实际上目前,还没一个确切的泛型的零值,那么我们要做的只能是按照实际来具体分析,按照提案,以后有可能使用 "),a("code",[t._v("return ...")]),t._v(" "),a("code",[t._v("return _")]),t._v(" "),a("code",[t._v("return")]),t._v(" "),a("code",[t._v("return nil")]),t._v(" "),a("code",[t._v("return T{}")]),t._v(" 这些都是可能的结果,我个人比较喜欢 "),a("code",[t._v("return T{}")]),t._v(" 来表示泛型的零值,拭目以待吧。")]),t._v(" "),a("h3",{attrs:{id:"无法识别使用了底层数据的其它类型"}},[t._v("无法识别使用了底层数据的其它类型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Float "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" ~"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" NewtonSqrt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T Float"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v T"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" T "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" iterations "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\titerations "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\titerations "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sprintf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"unexpected type %T"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Code omitted.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" MyFloat "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("float32")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" G "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewtonSqrt")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("MyFloat")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("64")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("这里约束 Float 拥有的约束类型是 "),a("code",[t._v("~float32")]),t._v(" 和 "),a("code",[t._v("float64")]),t._v(" 当在 switch 中定义了 float32 和 flaot64 时,无法识别下面的新类型 MyFloat 即使它的底层时 float32,go 的提议是以后在 switch 中使用 "),a("code",[t._v("case ~float32:")]),t._v(" 来解决这个问题,目前尚未解决这个问题")]),t._v(" "),a("h3",{attrs:{id:"即便约束一致-类型也是不同的"}},[t._v("即便约束一致,类型也是不同的")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" Copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" T2 any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dst "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" src "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("T2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" src "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tdst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("T1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// x 是 T2类型 不能直接转化为 T1类型")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("T1,和 T2 虽然都是 any 的约束,但是啊,它不是一个类型啊!")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("Copy"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这种情况下,你能说可以直接转化吗???")]),t._v("\n")])])]),a("p",[t._v("这种代码可以更改一下")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("T1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("确认是一种类型以后才能转化")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://coolshell.cn/articles/21615.html")]),t._v(" "),a("li",[t._v("https://go.dev/doc/tutorial/generics")]),t._v(" "),a("li",[t._v("https://colobu.com/2021/08/30/how-is-go-generic-implemented/")]),t._v(" "),a("li",[t._v("https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md")]),t._v(" "),a("li",[t._v("https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/generics")]),t._v(" "),a("li",[t._v("https://mp.weixin.qq.com/s/zKnh_iPm8skxWv3rxaOscw")]),t._v(" "),a("li",[t._v("https://mp.weixin.qq.com/s/BFsoQPvrog_sMKMTEofZyQ")])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/42.85cfacd9.js b/assets/js/42.85cfacd9.js new file mode 100644 index 000000000..45b9b0625 --- /dev/null +++ b/assets/js/42.85cfacd9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{473:function(t,s,n){"use strict";n.r(s);var a=n(36),e=Object(a.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"结构体"}},[t._v("结构体")]),t._v(" "),n("h2",{attrs:{id:"简单介绍-struct"}},[t._v("简单介绍 struct")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("ul",[n("li",[t._v("Peopel 首字母大写,根据我们所学的首字母大写可导出的知识,它是包级可导出结构")]),t._v(" "),n("li",[t._v("Addr 首字母大写,所以它是可导出字段,name 和 year 都是小写,所以他们俩不可导出")])]),t._v(" "),n("p",[t._v("下面看一下结构体的使用")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 初始化")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p People\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),t._v("\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),t._v("\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2000")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p2 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 结构体的调用")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2000")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里是语法糖,p虽然是people的指针,")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 但是它却可以直接调用 Addr")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 实际上就是 (*p).Addr 的省略")]),t._v("\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"上海"')]),t._v("\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小红"')]),t._v("\n p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2001")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" p"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 我们还可以使用new来代替&")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这种写法跟上文中的 var p = &People{} ")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 一个意思")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"解耦结构体声明和调用"}},[t._v("解耦结构体声明和调用")]),t._v(" "),n("p",[t._v("当我们实现结构体的时候,如果显示写出结构体的字段变量名称,就可以不按照顺序,以及可以不完全实现全部字段,这样的话,结构体的声明和实现就可以完全解耦,当然可以隐藏实现的结构体变量,那么你不得不要按照顺序,以及实现全部字段,满足这两者才可以。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 显式实现")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" p "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2000")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" a\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("上述代码就是显示的写出了字段的变量名称,你看,name 并没有被写上,这种情况下,name 就会被命名为一个初始值,即 “”")]),t._v(" "),n("p",[t._v("这样,即使结构体本身有什么增加字段的行为,实现结构体的逻辑代码也不用改变了。")]),t._v(" "),n("p",[t._v("如果是隐式的话,那么必须按照顺序,以及数量进行实现,建议在字段不变以及字段数量非常少的时候使用。")]),t._v(" "),n("h2",{attrs:{id:"匿名-struct"}},[t._v("匿名 struct")]),t._v(" "),n("p",[t._v("我们使用匿名 struct,可以完全将另一个结构体嵌入到这个结构体中。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People\n score "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("使用匿名函数,等于将这个匿名函数的字段完全给予了这个新的结构体,这跟使用这个结构体当作一个字段的类型是不同的,我们看一个例子")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People People\n score "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("这段代码跟上文看起来很像,但是一个是将 people 直接嵌入,一个是当成了它的一个字段类型。让我们看一下这两者使用起来的区别")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student1 "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People People\n score "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People\n score "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s1 "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2000"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("score "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("score"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小红"')]),t._v("\n s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2001"')]),t._v("\n s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"上海"')]),t._v("\n s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("score "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("200")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s1"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("score"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("我们发现匿名函数的字段直接赋予了新的结构体,它不再需要显式的调用 "),n("code",[t._v("s1.People.name")])]),t._v(" "),n("p",[t._v("实际上,不止一个 struct 可以当作匿名函数,内置类型也是可以的")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n People\n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n score "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("People "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n year"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2000"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n addr"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"12"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("score "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v("\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("函数也可以将指针类型当作类型以及直接嵌入,与非指针相比,我们不能直接调用嵌入的结构体的字段,因为它目前还是 nil,这个时候我们必须先将结构体初始化,然后再进行操作,下文的代码有演示。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Name\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("People\n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n score "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fist "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n last "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("People "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("first "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("last "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小红"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"小明"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("year "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2000"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("addr "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"北京"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"12"')]),t._v("\n s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("score "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v("\n\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("通过这个演示我们发现,其实嵌入更像是一种语法糖,它就跟将结构体当作类型,前面的结构体字段变量跟这个类型保持一致这种操作是同样的作用,只不过直接嵌入可以将嵌入的字段当作自己的字段,省略了中间的变量罢了,它有下面的等于关系")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//People *People")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等于 ")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// *People")]),t._v("\n\n\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// People People")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 等于 ")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// People")]),t._v("\n \n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n addr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("当一个结构体拥有了其它嵌入的时,也一起拥有了在他们身上的方法,不过,非嵌入的那种,还是需要带上中间的字段变量名称比如:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tName Name\n\t"),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("People\n\t"),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tscore "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Name "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfirst "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tlast "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tyear "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\taddr "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("S")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"stuend-s"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果这里不是定义在指针上的方法,这段代码将报错")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 原因是 people嵌入的时候还是nil,如果这里不是指针上的方法,是值上的方法")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 底层是需要 *People (取值) 操作的,但是这时候是nil,所以就会报错。")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("People"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetS")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"people-setS"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里注意,因为不是嵌入的操作,所以它必须带上中间的 Name")]),t._v("\n\ts"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("S")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ts"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("SetS")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("h2",{attrs:{id:"空结构体"}},[t._v("空结构体")]),t._v(" "),n("p",[t._v("通常,当我们需要一个临时的变量时,我们可以会想到设置一个 bool 类型,因为我们潜意识中感觉一个 bool 类型是比较小的,但是一个空的变量才是最小的,下面让我们看一个例子,这个例子发生在使用 channel 传递信息这个场景。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sig "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n sig "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" sig\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"任务已经完成"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("没错,这段代码中,使用一个 bool 类型的 channel 是没什么问题的,你甚至也可以使用 int string 都可以,因为只是传递一个信息,信息的内容不重要,但是当我们站在优化的角度来考虑,这里的 bool 就不完美了,我们改成空的结构体即可:")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sig "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n sig "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" sig\n fmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"任务已经完成"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("需要注意的是,一个空的结构体,表示它类型的方式是 "),n("code",[t._v("struct{}")]),t._v(",而使用这个空结构体的方式就是 "),n("code",[t._v("struct{}{}")]),t._v(",前面的大括号是跟 struct 一起的整体表示空结构体,后面的大括号表示一个空结构体类型的结构体调用")]),t._v(" "),n("h2",{attrs:{id:"直接嵌套还是作为字段"}},[t._v("直接嵌套还是作为字段")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Pool "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n wg sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n JobQueue "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Job\n dispatcher "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("dispatcher\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Pool "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sync"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("WaitGroup\n \n JobQueue "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" Job\n dispatcher "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("dispatcher\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("结构体嵌套可能带来的问题:")]),t._v(" "),n("ul",[n("li",[n("p",[t._v("名称冲突\n如果 Pool 结构体中还定义了 Add/Done/Wait 方法,和嵌套的 WaitGroup 中的方法就会产生冲突。")])]),t._v(" "),n("li",[n("p",[t._v("不必要的方法\n嵌套整个 WaitGroup 会让 Pool 结构体拥有 Add/Done/Wait 等方法,但 Pool 可能只需要 Wait 就够了。")])]),t._v(" "),n("li",[n("p",[t._v("使结构体臃肿\n嵌套整个 WaitGroup 会让 Pool 结构体看起来很臃肿,包含许多其实用不到的方法。")])]),t._v(" "),n("li",[n("p",[t._v("继承关系不清晰\nPool 并不是 WaitGroup 的一种,嵌套整个 WaitGroup 让人可能误以为它是在继承 WaitGroup。")])])]),t._v(" "),n("p",[t._v("所以,作为一个字段,可以避免上述问题,又可以保持必要的功能。")]),t._v(" "),n("p",[t._v("总结一下,嵌套要慎用,只有当:")]),t._v(" "),n("ul",[n("li",[t._v("被嵌套的类型方法不会与现有方法冲突")]),t._v(" "),n("li",[t._v("被嵌套的所有方法都会被用到")]),t._v(" "),n("li",[t._v("两者之间有逻辑上的继承关系")])]),t._v(" "),n("p",[t._v("时,才更适合使用嵌套 (组合) 的方式。")]),t._v(" "),n("p",[t._v("否则,使用字段的方式可以获得必要的功能,而不引入嵌套的潜在问题。")])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/43.1b441a63.js b/assets/js/43.1b441a63.js new file mode 100644 index 000000000..33473a109 --- /dev/null +++ b/assets/js/43.1b441a63.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{472:function(t,s,a){"use strict";a.r(s);var n=a(36),r=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"逻辑和判断语句"}},[t._v("逻辑和判断语句")]),t._v(" "),a("p",[t._v("go 语言基本上继承了 c 语言的逻辑判断语句,但是仍有些不同,比如:")]),t._v(" "),a("ul",[a("li",[t._v("在循环语句中,仅保留了 "),a("code",[t._v("for")]),t._v(" 语句,do-while,while 均不支持,这也是满足了 go 小而美的原则 -- 单一功能仅保留一种方式。")]),t._v(" "),a("li",[t._v("break continue 后面添加 label 功能")]),t._v(" "),a("li",[t._v("switch 中 case 语句不会自动执行下一个 case,需要显示的使用 "),a("code",[t._v("fallthrough")]),t._v(",当然了在 select 中的 case,并没有 fallthrough 功能")]),t._v(" "),a("li",[t._v("switch 中 case 支持表达式列表")]),t._v(" "),a("li",[t._v("switch 增加 type 模式,让类型也可以作为选择的条件")]),t._v(" "),a("li",[t._v("跟 c 语言最大的不同,增加了 select - case 功能。")])]),t._v(" "),a("h2",{attrs:{id:"if"}},[t._v("if")]),t._v(" "),a("p",[t._v("go 语言中的控制语句基础语法:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" conditon "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" condition"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 比如:")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a > 0"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a > 0 并且 < 12"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a > 12 或者是非正数"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("go 语言推崇的控制语句是 “快乐路径”:")]),t._v(" "),a("ul",[a("li",[t._v("当出现错误时,直接返回")]),t._v(" "),a("li",[t._v("成功的逻辑不要放在 if 语句中")]),t._v(" "),a("li",[t._v("返回值通常在此函数的最后一行")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("handle")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" value\n")])])]),a("h2",{attrs:{id:"for"}},[t._v("for")]),t._v(" "),a("p",[t._v("for 循环的基础语言和 c 类似,for range 语句中,range 后面接数组,指向数组的指针,切片,字符串,和拥有读权限的 channel")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" sliceValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("其中普通循环语句中,i 值属于整个 loop 所有,这一点需要好好注意,我们在作用域那一章节中也提到过。")]),t._v(" "),a("p",[t._v("for-range 语句中,有两点需要注意,首先跟普通循环一样,变量属于整个 loop 所有。")]),t._v(" "),a("p",[t._v("其次,k,v 变量是切片或者 map 的 index 和 value 复制体,当遇到比如 slice 更改数据的时候,切勿直接更改 k v,可使用 "),a("code",[t._v("arr[k] = v+1")]),t._v(" 这种方式直接改变切片本身,另外,当使用 for-range 语句时,如果第二个变量没有使用的价值,可以不写,并且无需使用占位符 "),a("code",[t._v("_")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" sliceValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 如果是省略第一个,那么还是需要占位符的")]),t._v("\n\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" sliceValue"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("切片在运行时,len 是会变化的,因为确定切片的 len 是 runtime 的责任,而数组的 len 是在编译期确定的,for - range 后面的数组或者切片,真正处理的其实是这个数据的复制,下面看一个 bug")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" number "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tnumber"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("number"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 5")]),t._v("\n")])])]),a("p",[t._v("这里 number 输出的是 5,因为我们 append 添加的长度是原切片的长度,但是循环体中存储的 len,还是最初的长度 5,所以只能循环 5 次。")]),t._v(" "),a("p",[t._v("for-range 中还有一个容易出 bug 的事情,比如 range 后面跟一个数组,因为 range 的时候实际上是数组的复制品,看下面这段代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" r "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\ta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t\t\ta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("13")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\tr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" v\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("本来期望的 r 值是 1 12 13 4 5,因为在 i == 0 时就更改了数组 a 的值,但是最终输出的却是 1 2 3 4 5,原因很简单,因为 v 读取的是 a 这个数组的复制品,也就是说,实际上这个代码的隐藏含义是 "),a("code",[t._v("range a'")]),t._v(" 这里的 "),a("code",[t._v("a'")]),t._v(" 就是 a 的复制品,所以更改了 a,a 的复制品也不会被改变,解决方法就是取这个数组的切片就可以了,这样即便是复制了,也只是复制了一份儿指针而已。")]),t._v(" "),a("h3",{attrs:{id:"string"}},[t._v("string")]),t._v(" "),a("p",[t._v("如果 for-range 中后面接的是 string,每次迭代不是按照 byte 来进行的,而是按照 rune 来进行,比如 "),a("code",[t._v('"你好"')]),t._v(" 每次的迭代输出的就是你和好,而不是 byte")]),t._v(" "),a("h3",{attrs:{id:"map"}},[t._v("map")]),t._v(" "),a("p",[t._v("for range 后面是 map 时,无法保证 map 的输出顺序,但是 map 和 slice 一样都是胖指针,所以时可以对 map 进行直接操作的。如果在循环体中新创建一个 map 项,那么这个项目在 range 时有可能会被输出,不能保证一定。")]),t._v(" "),a("h3",{attrs:{id:"channel"}},[t._v("channel")]),t._v(" "),a("p",[t._v("channel 的本质也是一个胖指针,所以它也可以直接被操作本体,channel 在 range 时是阻塞式的读取,如果不关闭 channel,这个 range 会一直阻塞。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码就会造成一直阻塞,进而触发系统的 Panic")]),t._v(" "),a("h2",{attrs:{id:"switch-select"}},[t._v("switch && select")]),t._v(" "),a("p",[t._v("在 go 语言的 switch 和 select 的 case 中,我们经常会使用 break 来跳出循环,默认跳出的就是最小的那个循环单位,比如下面这个例子")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码是有 bug 的,因为它无法跳出 for 这层循环,只能跳出 select 这里。那么我们该怎么做呢?这个时候应该使用 label 了,所谓 label 就是标签的意思,意思就是指定好了 break 的位置,它的作用就是这个。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Now"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v(" time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v(" Now\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这个时候就可以 break 到 Now 指定的层级了。")]),t._v(" "),a("p",[t._v("我们应避免使用 fallthrough 来执行多条件表达式,比如这样的代码")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fallthrough")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fallthrough")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"yes"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这种代码也很烂,我们可以直接使用多个 case 并列的方式:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int16")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"yes"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"no"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码使用的就是判断 type 的断言模式,固定用法就是 "),a("code",[t._v("value.(type)")]),t._v(" 前面是要判断的 value,后面是固定用法 type,必须是这个单词才行。")]),t._v(" "),a("p",[t._v("我再带你回忆一下普通的断言,"),a("code",[t._v("a.(int)")]),t._v(" 除了在 switch 中的断言方式,普通的断言就跟这段代码是一致的,一个 any 类型 (interface {}) 后面跟具体的类型。")]),t._v(" "),a("p",[t._v("经过上面的初步介绍,接下来,我们深入看一下 for range 的一些底层原理")]),t._v(" "),a("h2",{attrs:{id:"汇总一下-for-和-for-range-中最容易迷惑的几段代码"}},[t._v("汇总一下 for 和 for range 中最容易迷惑的几段代码")]),t._v(" "),a("p",[t._v("第一段代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n arr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n arr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码 for 循环不会一直循环,原因是,arr 会在 range 一个复制一份儿,这个复制体的 len 在最初的 range 中的开头已经确定是 3,后面继续追加的 arr,并不会改变这个最初读取的 "),a("code",[t._v("len == 3")]),t._v(" 这个结果。")]),t._v(" "),a("p",[t._v("不过,如果你使用的是传统的循环,那么这种写法就会出现 bug:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tn "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tn"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"i"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("使用这种传统的 for 循环,因为 n 在循环体和循环内部都是同一个,所以循环不会结束")]),t._v(" "),a("p",[t._v("因此你应该将这种代码改写为 for - range 模式:")]),t._v(" "),a("blockquote",[a("p",[t._v("go 1.22 增加了对于整数的 for range,之前只有 chan slice map,不过整数的 for range 前面只有一个变量,并且跟其他 for range 一致,n 为复制值,并且 for i := range n,i 也是复制值。这跟其他的 for range 保持一致")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tn "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tn"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"i"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("第二段代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("arr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\nresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码是存在 bug 的,&v,首先,根据作用域可知道,这个 v 是 loop 级作用域,那么这个 result 中存在的&v 就是同一个值,所以这个代码是错误的。")]),t._v(" "),a("p",[t._v("改正的方式就是放入正确的切片中数据的指针即可:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("arr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arr "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\nresult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("arr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("第三段代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" result "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n result"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这是一段对 int 切片进行归零的方法,很多人会觉得这要循环一次会非常浪费时间,其实不会,因为在编译器中,它不会真的循环,编译器会优化这个操作,直接给它内存清零。")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/44.5dc33e34.js b/assets/js/44.5dc33e34.js new file mode 100644 index 000000000..a1feeb92f --- /dev/null +++ b/assets/js/44.5dc33e34.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{474:function(t,s,a){"use strict";a.r(s);var n=a(36),r=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"错误处理"}},[t._v("错误处理")]),t._v(" "),a("h2",{attrs:{id:"错误处理的基本认识"}},[t._v("错误处理的基本认识")]),t._v(" "),a("p",[t._v("在 go 语言中,没有传统编程语言的 "),a("code",[t._v("try - catch")]),t._v(" 操作,go 语言中一切错误都需要显式处理:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./x"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("通常,我们规定函数返回的最后一个数据是错误接口:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"错误x"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们直接返回一个 err 是一种简单的做法,如果错误比较初级也可以这么做,但是如果想要带有更精确的提示信息,可以在返回的时候 wrap 一层信息:")]),t._v(" "),a("p",[t._v("就以上文的读取数据为例")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"在读取数据的时候发生了错误,错误信息是:%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("wrap 一层信息,对于错误的定位更加高效")]),t._v(" "),a("h2",{attrs:{id:"error-的本质是什么"}},[t._v("Error 的本质是什么?")]),t._v(" "),a("p",[t._v("错误处理的核心就是下面这一个 error 的接口")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("所以只要我们的自建类型实现了这个接口,就可以使用很多的错误处理的方法。")]),t._v(" "),a("h3",{attrs:{id:"自定义-error"}},[t._v("自定义 error")]),t._v(" "),a("p",[t._v("我们使用 errors.New() 的时候其实就是返回了一个 go 自建的,叫做 errorString 的实现了 error 接口的结构体。\n这就是自建 error 的方法")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\te "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// (0x47fd48,0xc00003e730)")]),t._v("\n")])])]),a("p",[t._v("为了防止在比较错误的时候发生错误一致的情况,所以自建 error,返回的实际上是一个指针。")]),t._v(" "),a("blockquote",[a("p",[t._v("下文会提用什么方法进行比较 err,实际上就是 “两个接口类型是否相等 --- 类型一致,值一致”,如果返回的值是指针,那么值肯定就不可能一样了。")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// go 源代码")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("errorString"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当我们使用 fmt.Errorf() 的时候,其实也是使用的上述方法。")]),t._v(" "),a("p",[t._v("不过,如果我们使用了占位符 "),a("code",[t._v("%w")]),t._v(" 时,将不会使用上述方法,而是使用了 wrapError:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" wrapError "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tmsg "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("wrapError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("msg\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("wrapError"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unwrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("使用这种方式主要是为了错误链,那就让我们看一下如何使用错误链的相关操作。")]),t._v(" "),a("h3",{attrs:{id:"errors-is"}},[t._v("errors.Is()")]),t._v(" "),a("p",[t._v("上文我们说到,错误可以使用 wrap 的方式进行封装,那么如果我们想判断封装的这么多层的错误中,有没有哪一层错误等于我们要的值,可以使用这个函数进行判断:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err is now"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\terr1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1:%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\terr2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1:%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Is")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"是一个错误"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"errors-as"}},[t._v("errors.As()")]),t._v(" "),a("p",[t._v("这个方法跟上文的 Is() 类似,只不过它判断的是类型是否一致。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" errS "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("errS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("a\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\nerr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("errS"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"typical error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\nerr1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wrap err: %w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nerr2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wrap err1: %w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("errS\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的 target 必须使用指针")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("As")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"TypicalErr is not on the chain of err2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"TypicalErr is on the chain of err2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"errors-join"}},[t._v("errors.Join()")]),t._v(" "),a("p",[t._v("这个方法是将几个错误结合在一起的方法:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\terr1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1:%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\terr2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err1:%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Join")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"当错误处理遇到了-defer"}},[t._v("当错误处理遇到了 defer")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" xx "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("close")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段伪代码的意思是说,当有条件之后,返回一个错误,但是 defer 的内容发生在这个 err 被固定之后,所以 defer 中如果再有错误将不会被处理。")]),t._v(" "),a("p",[t._v("那么我们该怎么更改呢?")]),t._v(" "),a("p",[t._v("我想你一定想到了前文我们说过,使用带有变量的返回值是可以将 defer 的值进行返回的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" xx "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\te "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xx\n\t\t\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xx\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("close")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("那么这种写法,defer 中如果发生了错误就会覆盖掉了程序执行中的 err,所以这种方法也是不行的,即使它能照顾到了 defer 中的错误处理。")]),t._v(" "),a("p",[t._v("我们可以将错误处理都放在 defer 中处理就可以了")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" xx "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xx\n\t\te "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xx\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\te1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" e1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\terr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" e1\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这样,两种错误都能处理到了")]),t._v(" "),a("h2",{attrs:{id:"错误处理实战的五种方式"}},[t._v("错误处理实战的五种方式")]),t._v(" "),a("h3",{attrs:{id:"经典的错误处理方式"}},[t._v("经典的错误处理方式")]),t._v(" "),a("p",[t._v("每一个步骤分别直接处理错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" age "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("putAge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("allAge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("D")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ag age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" ag"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" ag"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("putAge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" ag"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("allAge")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"屏蔽过程中的错误处理"}},[t._v("屏蔽过程中的错误处理")]),t._v(" "),a("p",[t._v("将错误放置在对象的内部进行处理:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" FileCopier "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tw "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File\n\tr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File\n\terr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("FileCopier"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\th"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" err\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" h"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("FileCopier"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OpenSrc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("FileCopier"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("CopyFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" dst "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("r "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("w"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("w "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\tos"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Remove")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\n\tf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("opensrc")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createDst")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("err\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码并不是特别完整,但是从中我们还是可以理解这种将错误放在对象中的写法的技巧。")]),t._v(" "),a("p",[t._v("首先,错误直接放置在对象自身,在方法中首先去调用这个字段来看是否拥有错误,如果有,直接退出即可")]),t._v(" "),a("p",[t._v("如果没有错误继续往下走,如果本次方法发生错误就继续将这个错误赋值给这个字段,")]),t._v(" "),a("p",[t._v("当最后处理的方法时,这里也就是 copyfile 方法,我们在 defer 中要对于各个子方法进行判断,到底是哪个方法有错误,然后逐一进行判定。相当于处理错误的逻辑集中放置到了最后一个函数进行执行了。")]),t._v(" "),a("p",[t._v("也就是说,将错误放置在对象本身的时候,通常应该为顺序调用的方法,一旦前者出现错误,后者即可退出")]),t._v(" "),a("p",[t._v("如果不是顺序的执行过程,那么有些的错误就可能被湮没,导致错误无法被感知。")]),t._v(" "),a("h3",{attrs:{id:"分层架构中的错误处理方法"}},[t._v("分层架构中的错误处理方法")]),t._v(" "),a("p",[t._v("常见的分层架构")]),t._v(" "),a("ul",[a("li",[t._v("controller 控制层")]),t._v(" "),a("li",[t._v("service 服务层")]),t._v(" "),a("li",[t._v("dao 数据访问层")])]),t._v(" "),a("p",[t._v("dao 层生产错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("service 追加错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Dao"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"getname err: %w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("controller 打印错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"pkg-errors"}},[t._v("pkg/errors")]),t._v(" "),a("p",[t._v("如果感觉标准库提供的错误处理不够丰富,也可以使用 github.com/pkg/errors 来处理错误")]),t._v(" "),a("p",[t._v("此包常用的方法有")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 生成新的错误,同样会附加堆栈信息")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只附加新的消息")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithMessage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("message "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 只附加堆栈信息")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithStack")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 附加信息 + 堆栈信息(就是一大堆的各种文件的堆栈调用过程的详细信息)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wrapf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("format "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("args"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 获取最根本的错误(错误链的最底层)")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cause")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n")])])]),a("p",[t._v("例如:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// %+v 是 pkg/errors 包提供的格式化输出格式,输出错误堆栈")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Printf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%+v"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"open error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("在使用这个 pkg/errors 包的时候要注意一件事,因为 wrap 可以包装堆栈向上输出,如果你调用的第三方库使用了 wrap,你再次使用 wrap,那么就会出现两堆相同的堆栈信息,这造成了极大的冗余。")]),t._v(" "),a("p",[t._v("所以,")]),t._v(" "),a("ul",[a("li",[t._v("在提供多人使用的三方库的时候不要使用 wrap,只有逻辑代码的时候使用 wrap 的功能")]),t._v(" "),a("li",[t._v("遇到一个错误不打算处理,那么要带上足够多的信息再向上抛出")]),t._v(" "),a("li",[t._v("一旦错误处理完成之后就没有错误了,不再需要把错误继续网上抛,返回 nil 即可")])]),t._v(" "),a("p",[t._v("所以我们使用 pkg/errors 包将上面的分层写法做一个更完善的改进:")]),t._v(" "),a("p",[t._v("dao 层生产错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// a")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回此处的错误堆栈")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"error:"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("service 追加错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不返回堆栈了,仅仅添加错误")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithMessage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"getName error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("controller 打印错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 添加日志")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"errgroup-的使用技巧"}},[t._v("errgroup 的使用技巧")]),t._v(" "),a("p",[t._v("errgroup 的使用方法是 golang.org/x/sync/errgroup")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"golang.org/x/sync/errgroup"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ctx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errgroup"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithContext")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 启动一个 goroutine去处理错误")]),t._v("\n\tg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"error1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"error2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 类似 waitgroup 的 wait 方法")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" g"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wait")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"错误处理相关技巧"}},[t._v("错误处理相关技巧")]),t._v(" "),a("p",[t._v("这里会介绍在实战过程中用到的诸多技巧")]),t._v(" "),a("h3",{attrs:{id:"使用-errors-new-时要写清楚包名"}},[t._v("使用 errors.New() 时要写清楚包名")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" age\n\nErrMyAge "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age: ErrMyAge is error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nErrMyAddress "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age: ErrMyAddress is error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"使用-error-处理一般错误-使用-panic-处理严重错误-异常"}},[t._v("使用 error 处理一般错误,使用 panic 处理严重错误 (异常)")]),t._v(" "),a("p",[t._v("使用这种模型就避免了类似 Java 那种所有错误都一样的行为,Java 的使用 try-catch 的方式导致任何错误都是一个方式去处理,非常有可能让程序员忽略错误的处理")]),t._v(" "),a("p",[t._v("然而 go 不同,"),a("strong",[t._v("错误")]),t._v("使用 error,"),a("strong",[t._v("异常")]),t._v("使用 panic 的方式去处理。")]),t._v(" "),a("ul",[a("li",[t._v("错误:error")]),t._v(" "),a("li",[t._v("异常:panic")])]),t._v(" "),a("p",[t._v("假设我们在代码中使用了 panic,通常来说,为了代码的健壮性还是会使用 defer 函数去运行一个 recover() 的,程序的存活比啥都重要。")]),t._v(" "),a("h3",{attrs:{id:"基础库-应该避免使用-error-types"}},[t._v("基础库,应该避免使用 error types")]),t._v(" "),a("p",[t._v("因为这种写法容易造成代码的耦合,尤其是在我们写的基础库中,非常容易造成改动代码来引入的不健壮性。")]),t._v(" "),a("p",[t._v("使用自定义的 error type")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 为了额外增加更多的错误信息,字段需大写")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ErrMyAge "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tEV "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tMErr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ErrMyAge"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sprintf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age: %s"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("EV"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("ErrMyAge"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err age is hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("使用 errors.New() 哨兵错误模式:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 我方代码")]),t._v("\nErrAge "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age: ErrAge is error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nErrAddress "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age: ErrAddress is error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("--")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用者")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/shgopher/age"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 带来了耦合")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Is")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ErrAge"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 处理")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("实际上他们都是 error types,只不过前者比后者增加了很多额外的信息,但是相同点是,他们都造成了耦合")]),t._v(" "),a("p",[t._v("如果别人使用了这个基础库,那么势必这些错误就会跟使用者的代码耦合,我们改动了代码,第三方的代码就会因此受到影响。")]),t._v(" "),a("p",[t._v("因此,在对外暴露的基础包中,我们应尽量减少定义哨兵错误 (上述定义方法被称之为哨兵模式的错误)")]),t._v(" "),a("p",[t._v("上述提供的哨兵模式是透明的错误导出机制,所以容易造成耦合")]),t._v(" "),a("p",[t._v("我们可以提供不透明的机制,不导出透明的错误类型,仅仅让用户判断是否等于 nil,就可以防止耦合的存在")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/shgopher/age"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" age"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Bar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这也是大多数程序应该提供的模式,不对外暴露,避免了耦合")]),t._v(" "),a("p",[t._v("那么这种方法的缺陷也很明显了,就是无法获取更多的错误信息,理论上来说,我们也没必要获取那么多错误信息,但是如果真的要获取错误信息了,该如何去做呢?")]),t._v(" "),a("p",[t._v("我们可以向外暴露一些动作,只暴露行为:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" mage "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 通过一个对外暴露的函数可以对外输出行为")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 并且还不用暴露出具体的对象")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("IsMage")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"优化不必要的代码让程序变得更简洁"}},[t._v("优化不必要的代码让程序变得更简洁")]),t._v(" "),a("p",[t._v("方法一将大函数变小函数,通过封装函数的方法从视觉上降低 if err 的影响。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 改造之前")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OpenFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("dst "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cloase")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Copy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将前面两个操作封装成一个函数")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OpenD")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src dst "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" r "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("w "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File \n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 主函数就只有一个 if err 了")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OpenFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("dst "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" w "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("File\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("OpenD")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("dst"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tw"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Copy")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("w"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("方法二将代码中不必要的成分删除,来保证代码的简洁")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 改造前")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("AuthticateRequest")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("authticate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 实际上 authticate 只返回一个 error 类型的接口,根本不需要判断")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("AuthticateRequest")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Request"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("authticate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("User"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("方法三使用更加合适的方法")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 我们要逐行去读取数据")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 改造前")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Countlines")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Reader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t\tbr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" bufio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewReader")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tline "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t\terr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" br"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readline")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token char"}},[t._v("'\\n'")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tline "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v(" \n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("break")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("EOF "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" lines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n\t\t\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 代码看起来也是很合理的样子,也很简洁,但是,我们其实用的函数不是特别的合适")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//其实这里使用 scan 更加合适,代码量更加精简,并且结构异常舒服")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Countlines")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Reader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\t\n\tsc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" bufio"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewScanner")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tlines "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" sc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Scan")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tlines"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" lines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" sc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Err")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("h3",{attrs:{id:"错误应该只处理一次"}},[t._v("错误应该只处理一次")]),t._v(" "),a("p",[t._v("我们有日志系统,有些时候我们发现一个错误,然后打了一个日志,然后又把错误给 return 了,实际上这与 go 语言哲学中说的错误只处理一次相违背")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tlog"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Prinln")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ✅")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("age")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"./a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Wrap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"open error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("正确的处理方法是错误只处理一次,那么在什么时候处理呢?")]),t._v(" "),a("p",[t._v("上文提到了多层的架构设计,我们在底层 (带有堆栈的错误向上抛出) 和中层 (仅仅附加信息再次向上抛出) 仅仅是向上抛出,并不需要将错误记录在日志中,在应用层才需要去使用日志记录错误,日志记录完错误以后,也不需要再向上抛出错误了 (最顶端了) 完全满足 “只处理一次错误” 的要求。")]),t._v(" "),a("h2",{attrs:{id:"业务-code-码的设置"}},[t._v("业务 code 码的设置")]),t._v(" "),a("p",[t._v("常见的 http 错误码数量较少,比如常见的只有例如 404 301 302 200 503 等,绝对数量还是较少,无法去表达业务上的错误,因此我们需要设置一套能表达具体生产业务的 code 码。")]),t._v(" "),a("p",[t._v("为了保证服务端的安全,我们设置的 code 码应该设置两套数据,一套显示给客户端,一套自用,以此来保证服务端的绝对安全。")]),t._v(" "),a("p",[t._v("有三种设计业务 code 码的方式:")]),t._v(" "),a("h3",{attrs:{id:"一律返回-http-status-200-具体-code-码单独设置"}},[t._v("一律返回 http status 200,具体 code 码单独设置")]),t._v(" "),a("p",[t._v("例如")]),t._v(" "),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"error"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Syntax error \\"Field picture specified more than once. This is only possible before version 2.1\\" at character 23: id,name,picture,picture"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"type"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"OAuthException"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"code"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2500")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"fbtrace_id"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"xxxxxxxxxxx"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("ul",[a("li",[t._v("http status code 通通 200")]),t._v(" "),a("li",[t._v("code 2500,才是真实的面向客户端的 code 码")])]),t._v(" "),a("p",[t._v("使用这种方法的一大缺陷就是必须解析 body 内容才能发现具体的错误业务码,很多场景我们仅仅需要知道返回的是成功或者错误,并不需要知晓具体的业务码,这是这种方式的一大弊端。")]),t._v(" "),a("h3",{attrs:{id:"使用合适的-http-status-code-简单的信息以及业务错误代码"}},[t._v("使用合适的 http status code + 简单的信息以及业务错误代码")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("HTTP/1.1 "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("400")]),t._v(" Bad Request\nx-connection-hash: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nset-cookie: "),a("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("guest_id")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nDate: Thu, 01 Jun "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2017")]),t._v(" 03:04:23 GMT\nContent-Length: "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("62")]),t._v("\nx-response-time: "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),t._v("\nstrict-transport-security: max-age"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("631138519")]),t._v("\nConnection: keep-alive\nContent-Type: application/json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("charset")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("utf-8\nServer: tsa_b\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 注意这里:仅仅返回简单的错误信息")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"errors"')]),t._v(":"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"code"')]),t._v(":215,"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"message"')]),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Bad Authentication data."')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这种方案也是大多数公司采纳的方案,使用具体的 http status code 可以知晓大概的业务类型,是错误还是正常运行,然后使用简单的错误信息和业务错误代码去定位具体的错误")]),t._v(" "),a("p",[t._v("如果业务不是特别复杂,使用这种方式即可")]),t._v(" "),a("h3",{attrs:{id:"使用合适的-http-status-code-非常详细的业务错误代码以及信息"}},[t._v("使用合适的 http status code + 非常详细的业务错误代码以及信息")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("HTTP/1.1 "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("400")]),t._v("\nDate: Thu, 01 Jun "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2017")]),t._v(" 03:40:55 GMT\nContent-Length: "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("276")]),t._v("\nConnection: keep-alive\nContent-Type: application/json"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("charset")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("utf-8\nServer: Microsoft-IIS/10.0\nX-Content-Type-Options: nosniff\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SearchResponse"')]),t._v(":"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Version"')]),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.2"')]),t._v(","),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Query"')]),t._v(":"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SearchTerms"')]),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"api error codes"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(","),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Errors"')]),t._v(":"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Code"')]),t._v(":1001,"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Message"')]),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Required parameter is missing."')]),t._v(","),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Parameter"')]),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"SearchRequest.AppId"')]),t._v(","),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"HelpUrl"')]),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http'),a("span",{pre:!0,attrs:{class:"token entity",title:"\\u003a"}},[t._v("\\u003a")]),a("span",{pre:!0,attrs:{class:"token entity",title:"\\u002f"}},[t._v("\\u002f")]),a("span",{pre:!0,attrs:{class:"token entity",title:"\\u002f"}},[t._v("\\u002f")]),t._v("msdn.microsoft.com"),a("span",{pre:!0,attrs:{class:"token entity",title:"\\u002f"}},[t._v("\\u002f")]),t._v("en-us"),a("span",{pre:!0,attrs:{class:"token entity",title:"\\u002f"}},[t._v("\\u002f")]),t._v("library"),a("span",{pre:!0,attrs:{class:"token entity",title:"\\u002f"}},[t._v("\\u002f")]),t._v('dd251042.aspx"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当业务逻辑稍微复杂一些,并且需要极其精准和快速的定位错误时,就需要在返回的 body 中去设置非常详细的错误信息")]),t._v(" "),a("p",[a("strong",[t._v("综上所述:")])]),t._v(" "),a("ul",[a("li",[t._v("使用正确的 http status code 让业务的第一步变得更加直观")]),t._v(" "),a("li",[t._v("区别于 http status code,具体业务的 code 码会更加丰富")]),t._v(" "),a("li",[t._v("返回尽可能详细的错误,有助于复杂逻辑的快速错误定位")]),t._v(" "),a("li",[t._v("直接返回给客户的错误代码不应该包括敏感信息,敏感信息的 code 码仅供内部使用")]),t._v(" "),a("li",[t._v("错误信息要求规范,简洁以及有用")])]),t._v(" "),a("h3",{attrs:{id:"业务-code-码的具体设计"}},[t._v("业务 code 码的具体设计")]),t._v(" "),a("p",[t._v("引入业务 code 码的核心原因就是 http status code 太少,以及他们并不能跟具体业务挂钩。")]),t._v(" "),a("p",[t._v("当我们设置好良好又详细的 code 码时,我们就可以快速定位业务代码,以及可以快速知晓发生错误的等级模块,具体信息等")]),t._v(" "),a("p",[t._v("下面给出具体的设计思路:"),a("strong",[t._v("纯数字表达,不同的数字段表达不同的模块不同的业务")])]),t._v(" "),a("p",[t._v("例如 100101")]),t._v(" "),a("ul",[a("li",[t._v("10:表示某个服务")]),t._v(" "),a("li",[t._v("01:表示某个服务下的模块")]),t._v(" "),a("li",[t._v("01:模块下的错误码")])]),t._v(" "),a("p",[t._v("10 服务 01 模块 01 错误,--- 服务 10 数据库模块未找到记录错误")]),t._v(" "),a("p",[t._v("一共最多有 100 个服务,每个服务最多有 100 个模块,每个模块最多有 100 个错误,如果某些模块 100 个都不够用,那怎么这个模块有必要去拆分一下了。")]),t._v(" "),a("h3",{attrs:{id:"如何设置-http-status-code"}},[t._v("如何设置 http status code")]),t._v(" "),a("ul",[a("li",[a("code",[t._v("1xx")]),t._v(":请求已接收,继续处理")]),t._v(" "),a("li",[a("code",[t._v("2xx")]),t._v(":成功处理了请求")]),t._v(" "),a("li",[a("code",[t._v("3xx")]),t._v(":请求被重定向")]),t._v(" "),a("li",[a("code",[t._v("4xx")]),t._v(":请求错误")]),t._v(" "),a("li",[a("code",[t._v("5xx")]),t._v(":服务器错误")])]),t._v(" "),a("p",[t._v("由于 http status code 相对数量也不算太少,如果每一个都利用上,难免会增加复杂度,建议仅使用基本的几个即可")]),t._v(" "),a("ul",[a("li",[t._v("200 - 表示请求成功执行。")]),t._v(" "),a("li",[t._v("400 - 表示客户端出问题。")]),t._v(" "),a("li",[t._v("500 - 表示服务端出问题。")])]),t._v(" "),a("p",[t._v("如果上述的感觉太少,再增加下面几个也可以")]),t._v(" "),a("ul",[a("li",[t._v("401 - 表示认证失败。")]),t._v(" "),a("li",[t._v("403 - 表示授权失败。")]),t._v(" "),a("li",[t._v("404 - 表示资源找不到,这里的资源可以是 URL 或者 RESTful 资源。")])]),t._v(" "),a("p",[t._v("将 http status code 控制在"),a("strong",[t._v("个位数")]),t._v(",有利于后端的逻辑代码简洁性,比如 301 302 确实是代表不同的含义,"),a("strong",[t._v("前端或许可以设置丰富的 http status code,因为浏览器会进行相关的具体操作,但是后端返回给前端的 http status code 并没有任何的操作,使用过多只会增加复杂度。")])]),t._v(" "),a("h2",{attrs:{id:"设计一个生产级的错误包"}},[t._v("设计一个生产级的错误包")]),t._v(" "),a("h3",{attrs:{id:"生产级的错误包需要的功能"}},[t._v("生产级的错误包需要的功能")]),t._v(" "),a("ol",[a("li",[t._v("支持错误堆栈")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2021")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("07")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("02")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("14")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("17")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("03")]),t._v(" call "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" got failed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" called "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\nmain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("funcB "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("home"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("colin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("workspace"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golang"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("marmotedu"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("gopractise"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("demo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("errors"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("good"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("27")]),t._v("\nmain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("funcA "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("home"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("colin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("workspace"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golang"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("marmotedu"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("gopractise"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("demo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("errors"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("good"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("19")]),t._v("\nmain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("main "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("home"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("colin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("workspace"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golang"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("marmotedu"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("gopractise"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("demo"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("errors"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("good"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\nruntime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("main "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("home"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("colin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("go1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("16.2")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("runtime"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("proc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("225runtime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("goexit "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("home"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("colin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("go1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("16.2")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("runtime"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("asm_amd64"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1371")]),t._v("\nexit status "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n")])])]),a("p",[t._v("拥有错误的堆栈,我们才能定位错误的根源。")]),t._v(" "),a("ol",{attrs:{start:"2"}},[a("li",[a("p",[t._v("支持打印不同的格式比如 %s %w %d")])]),t._v(" "),a("li",[a("p",[t._v("支持 Wrap() Unwrap() 的功能,就是错误的嵌套和反嵌套")])]),t._v(" "),a("li",[a("p",[t._v("错误包要支持 Is() 和 As() 方法,这主要是因为有错误的嵌套,所以无法再使用接口相比较的方式进行判断接口类型是否相等 (类型相同,值相同)")])]),t._v(" "),a("li",[a("p",[t._v("要支持格式化和非格式化的创建方式")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("errors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("New")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"err"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%w"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h3",{attrs:{id:"具体实现"}},[t._v("具体实现")]),t._v(" "),a("p",[t._v("从 github.com/pkg/errors 包中改造即可。")]),t._v(" "),a("p",[t._v("增加以下字段的结构体就可以满足上面的需求")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" withCode "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\terr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\tcode "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tcause "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("stack\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),a("p",[a("code",[t._v("问题一:")]),t._v(" "),a("strong",[t._v("请说出下列代码的执行输出")]),t._v("*")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"oops"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的defer将不会进栈,所以也就不会执行了。")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"x"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("答案是")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("hi1\n"),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v("\noops\n"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" oops\n\ngoroutine "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("running"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\nmain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("tmp"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sandbox1932632082"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("prog"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("18")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0xa7")]),t._v("\n\nProgram exited"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n")])])]),a("p",[t._v("解释:Panic,意味着恐慌,意思等于 return,所以 panic 下面的数据是无法执行的,defer 不同,他们是顺序的将这些 defer 函数装入函数内置的 defer 栈的,所以在 return 之后,defer 栈会执行,所以这里的 defer 1 2 3 可以执行,Panic 前面的 hi1 可以执行,但是 Panic 之后,相当于 return 后面的 hi2 就无法执行了。")]),t._v(" "),a("p",[a("code",[t._v("问题二:")]),t._v(" "),a("strong",[t._v("看一段代码,分析答案")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" r "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("recover")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" r "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Recovered in f"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" r"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"starting f"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"behind g"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//会终止执行")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Defer in g"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Panicking!"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sprintf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%v"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Printing in g"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//终止执行")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("答案是")]),t._v(" "),a("div",{staticClass:"language-js extra-class"},[a("pre",{pre:!0,attrs:{class:"language-js"}},[a("code",[t._v("starting f\npanicking\nDefer "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" g "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\nrecoverd "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" f\n")])])]),a("p",[t._v("解释一下,首先执行的是 f 函数的代码,然后开始执行 g,在 g 中遇到了 Panic,所以 panic 后面的 parinting in g 就无法执行了,所以执行了 defer in g\n这个时候 f 中的 g(2) 后面的数据也无法执行了,因为整个 f 也陷入了恐慌,所以它只能 return 进入 defer 了,defer 中刚好有 recover,所以执行了 recover 信息后,就退出了函数。")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://mp.weixin.qq.com/s/EvkMQCPwg-B0ffZonpwXodg")]),t._v(" "),a("li",[t._v("https://mp.weixin.qq.com/s/D_CVrPzjP3O81EpFqLoynQ")]),t._v(" "),a("li",[t._v("https://time.geekbang.org/column/article/391895")]),t._v(" "),a("li",[t._v("极客时间《go 进阶训练营》")])])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/45.b2f02d30.js b/assets/js/45.b2f02d30.js new file mode 100644 index 000000000..dc7b95625 --- /dev/null +++ b/assets/js/45.b2f02d30.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{476:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"go-语言零值"}},[t._v("go 语言零值")]),t._v(" "),a("p",[t._v("go 在声明时期就会为变量提供默认值。")]),t._v(" "),a("p",[t._v("下面是所有的原生 go 类型的零值:")]),t._v(" "),a("ul",[a("li",[t._v("整数类型:0")]),t._v(" "),a("li",[t._v("浮点数:0.0")]),t._v(" "),a("li",[t._v("布尔类型:false")]),t._v(" "),a("li",[t._v("字符串类型:“”")]),t._v(" "),a("li",[t._v("指针,接口,切片,channel,map,function:nil")])]),t._v(" "),a("p",[t._v("至于复合类型,比如数组,和结构体的声明过程,就是 "),a("code",[t._v("递归的,针对于它所有的子元素的初始化")])]),t._v(" "),a("h2",{attrs:{id:"零值可用"}},[t._v("零值可用")]),t._v(" "),a("p",[t._v("go 奉行零值可用,最经典的案例是切片的 append 过程,即是你最初的切片变量只是声明,并未 make 赋予底层数组,那么 go 系统仍然处理的结果是可用,并非 Panic")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("下吗再看一个例子")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("code",[t._v("fmt.Println(b)")]),t._v(" 是调用的 "),a("code",[t._v("b.String()")]),t._v(",那么为什么这里输出的是 "),a("code",[t._v("<nil>")]),t._v(" 不是 Panic 呢?")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Buffer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Special case, useful in debugging.")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"<nil>"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("buf"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("off"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这就是答案,它在实现的 String 中实现了零值可用,"),a("code",[t._v("原因一:")]),t._v(" "),a("strong",[t._v("nil 的对象是完全可以调用属于它身上的方法的")]),t._v(","),a("code",[t._v("原因二:")]),t._v(" 这个方法内部实现的时候又是直接 return 一个 "),a("code",[t._v("<nil>")]),t._v(" 避免了取 nil 索引值的情况。所以说基于这两点,它零值可用。")]),t._v(" "),a("p",[t._v("再看一个经典的 buffer 例子:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bytes"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a bytes"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Buffer\n\ta"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"12"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("为什么只是声明了 buffer 就可以直接往里面写值呢?")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 结构体")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Buffer "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tbuf "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// contents are the bytes buf[off : len(buf)]")]),t._v("\n\toff "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// read at &buf[off], write at &buf[len(buf)]")]),t._v("\n\tlastRead readOp "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// last read operation, so that Unread* can work correctly.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 取自 Write() 相关的代码 这段代码保证了即便是初始化的buf是nil也可以零值可用。")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("buf "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<=")]),t._v(" smallBufferSize "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("buf "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" smallBufferSize"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("另外,当切片是 nil 的时候,也是完全可以取它的 "),a("code",[t._v("[:]")]),t._v(" 切片的,只要不超过 index 都没问题,这也是满足零值可用的一个小 tips")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\ns "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 或者 s = s[:0] or s = s[0:] or s= s[0:0]")]),t._v("\n")])])]),a("h2",{attrs:{id:"零值不可用"}},[t._v("零值不可用")]),t._v(" "),a("ul",[a("li",[t._v("slice 零值赋值")]),t._v(" "),a("li",[t._v("map 零值赋值")]),t._v(" "),a("li",[t._v("互斥锁的值复制")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s slice\ns"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 错误 ❌")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" m "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\nm"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 错误 ❌")]),t._v("\n")])])]),a("p",[t._v("再看互斥锁的案例")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\nmu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nmu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("这段代码是可以正常使用的")]),t._v(" "),a("p",[t._v("但是,如果队 mu 进行值的复制就不能使用了")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sync"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" mu sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex\n\tmu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tmu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("foo")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mu sync"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Mutex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tmu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Lock")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tmu"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Unlock")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("这个问题的解释是这样的:互斥锁是带有状态的,就是说,当你复制的时候本来是 a 的状态,然后复制过去还是 a 的状态,但是这是一个新的对象了按道理应该是初始状态,所以就会出现错误,这也是传说中的重入锁 (go 不支持),因为 go 的互斥锁是带有状态的,所以这种复制的方法就会出现错误。")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://github.com/golang/go/blob/037b209ae3e0453004a4d57e152aa522c56f79e4/src/bytes/buffer.go#L117")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/46.7fef4e9d.js b/assets/js/46.7fef4e9d.js new file mode 100644 index 000000000..f209b30a3 --- /dev/null +++ b/assets/js/46.7fef4e9d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{475:function(t,E,r){"use strict";r.r(E);var a=r(36),v=Object(a.a)({},(function(){var t=this,E=t.$createElement,r=t._self._c||E;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"工程"}},[t._v("工程")]),t._v(" "),r("ul",[r("li",[r("a",{attrs:{href:"./log"}},[t._v("log 包")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E6%B5%8B%E8%AF%95"}},[t._v("测试")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E6%80%A7%E8%83%BD%E5%89%96%E6%9E%90"}},[t._v("性能剖析")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%8C%85%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7"}},[t._v("包管理工具")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95"}},[t._v("动态调试")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86"}},[t._v("错误处理")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./cgo"}},[t._v("cgo")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./golint"}},[t._v("go lint")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%8F%8D%E5%B0%84"}},[t._v("反射")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./web"}},[t._v("web")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./wasm"}},[t._v("wasm")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E5%91%BD%E4%BB%A4"}},[t._v("命令")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85"}},[t._v("优秀第三方包")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./go%E6%A0%87%E5%87%86%E5%BA%93"}},[t._v("go 标准库")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F"}},[t._v("go 项目组织形式")])]),t._v(" "),r("li",[r("a",{attrs:{href:"./go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B"}},[t._v("go 命名惯例")])])])])}),[],!1,null,null,null);E.default=v.exports}}]); \ No newline at end of file diff --git a/assets/js/47.6dd9b6a9.js b/assets/js/47.6dd9b6a9.js new file mode 100644 index 000000000..f15157596 --- /dev/null +++ b/assets/js/47.6dd9b6a9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{477:function(t,s,i){"use strict";i.r(s);var e=i(36),n=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"cgo"}},[this._v("cgo")]),this._v(" "),s("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),s("ul",[s("li",[this._v("https://mp.weixin.qq.com/s/Xs5Ngi9444z6SyVVu0byUg")])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/48.e525f69a.js b/assets/js/48.e525f69a.js new file mode 100644 index 000000000..9f5ef4fdb --- /dev/null +++ b/assets/js/48.e525f69a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{478:function(t,s,i){"use strict";i.r(s);var e=i(36),n=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"github-copilot"}},[this._v("Github Copilot")]),this._v(" "),s("p",[this._v("自动补全代码")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/49.565c30a8.js b/assets/js/49.565c30a8.js new file mode 100644 index 000000000..5357ff3ec --- /dev/null +++ b/assets/js/49.565c30a8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{479:function(t,e,n){"use strict";n.r(e);var s=n(36),o=Object(s.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"web-开发"}},[t._v("web 开发")]),t._v(" "),n("p",[t._v("这里主要讲述 go 的 web 开发的用法。基本涉及到的包有 "),n("code",[t._v("net")]),t._v(","),n("code",[t._v("net/http")])]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://mp.weixin.qq.com/s/NQSgECerdR2rM06ugp4qjQ")]),t._v(" "),n("li",[t._v("https://mp.weixin.qq.com/s/jGrPM0UgqjZ10cXafoC0wQ")])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/5.864fc44c.js b/assets/js/5.864fc44c.js new file mode 100644 index 000000000..e3d72b559 --- /dev/null +++ b/assets/js/5.864fc44c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{401:function(e,t,a){},434:function(e,t,a){"use strict";a(401)},438:function(e,t,a){"use strict";a.r(t);a(96),a(45),a(10),a(99),a(100);var o={name:"CodeGroup",data:function(){return{codeTabs:[],activeCodeTabIndex:-1}},watch:{activeCodeTabIndex:function(e){this.activateCodeTab(e)}},mounted:function(){this.loadTabs()},methods:{changeCodeTab:function(e){this.activeCodeTabIndex=e},loadTabs:function(){var e=this;this.codeTabs=(this.$slots.default||[]).filter((function(e){return Boolean(e.componentOptions)})).map((function(t,a){return""===t.componentOptions.propsData.active&&(e.activeCodeTabIndex=a),{title:t.componentOptions.propsData.title,elm:t.elm}})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab:function(e){this.codeTabs.forEach((function(e){e.elm&&e.elm.classList.remove("theme-code-block__active")})),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},n=(a(434),a(36)),c=Object(n.a)(o,(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ClientOnly",[a("div",{staticClass:"theme-code-group"},[a("div",{staticClass:"theme-code-group__nav"},[a("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(t,o){return a("li",{key:t.title,staticClass:"theme-code-group__li"},[a("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(t.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?a("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]); \ No newline at end of file diff --git a/assets/js/50.249734db.js b/assets/js/50.249734db.js new file mode 100644 index 000000000..74f5624cd --- /dev/null +++ b/assets/js/50.249734db.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[50],{481:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"go-命名惯例"}},[t._v("go 命名惯例")]),t._v(" "),a("p",[t._v("go 语言的命名哲学就是"),a("strong",[t._v("尽可能的简单化")]),t._v("。")]),t._v(" "),a("p",[t._v("go 要求的简单,不仅仅是简单化,还要关注上下文的连贯性,go 喜欢一个简洁明了的命名+对字段的注释")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// userTypeInfo stores the information associated with a type the user has handed")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// to the package. It's computed once and stored in a map keyed by reflection")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// type.")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" userTypeInfo "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tuser reflect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Type "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the type the user handed us")]),t._v("\n\tbase reflect"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Type "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// the base type after all indirections")]),t._v("\n\tindir "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// number of indirections to reach the base type")]),t._v("\n\texternalEnc "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// xGob, xBinary, or xText")]),t._v("\n\texternalDec "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// xGob, xBinary or xText")]),t._v("\n\tencIndir "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// number of indirections to reach the receiver type; may be negative")]),t._v("\n\tdecIndir "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// number of indirections to reach the receiver type; may be negative")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("比如这段代码,对于字段和结构体都进行了注释,但是结构体内部的字段都相对简洁")]),t._v(" "),a("h2",{attrs:{id:"包"}},[t._v("包")]),t._v(" "),a("p",[t._v("包名称一般使用小写单词进行命名,例如说:"),a("code",[t._v("context")]),t._v(","),a("code",[t._v("http")]),t._v(","),a("code",[t._v("net")]),t._v(",无需考虑包名称的重复化,因为在 go 引入包的过程中,实际上是引入的路径,并且 go 的包在引入过程中还可以进行包的重命名")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"example.com/hey/log"')]),t._v("\n\n blog "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"example.net/bob/log"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("包的路径名称最后一位尽量和包的名称保持一致性,不过不一致也是有不少情况的,比如说,现在有一个适应不同语言的 log,那么命名的时候就变成了 "),a("code",[t._v("github.com/shgopher/golog")]),t._v(","),a("code",[t._v("github.com/shgopher/javalog")]),t._v(",但是他们实际上的包都叫 log,并不是 golog 和 javalog,那么使用的时候就需要对其中一个包进行重命名了。")]),t._v(" "),a("h2",{attrs:{id:"变量-类型-函数-方法"}},[t._v("变量,类型,函数,方法")]),t._v(" "),a("p",[t._v("因为 go 语言使用导出的变量时需要带上包的名称 (除了。省略包名称的方式,一般不提倡),所以命名的时候变量不需要再加上包的称呼,比如说 string 包的 Reader 就不需要写成 "),a("code",[t._v("string.StringReader")]),t._v(",写成 "),a("code",[t._v("string.Reader")]),t._v(" 即可")]),t._v(" "),a("p",[t._v("go 变量的命名使用驼峰的命名方式,go 的文件名称使用下划线连接的方式,比如说 "),a("code",[t._v("UpperName")]),t._v(","),a("code",[t._v("lowName")]),t._v(" 区别就是前者是大驼峰,导出的变量,后者是小驼峰,不可导出变量,缩略词如果首字母大写那么全部大写,比如 "),a("code",[t._v("HTTP")]),t._v(",不能写成 "),a("code",[t._v("Http")])]),t._v(" "),a("p",[t._v("go 代码里使用了大量单字母或者短字母的命名方式。")]),t._v(" "),a("p",[t._v("for 循环中以及 if 条件语句中使用单字母")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("method1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("函数和方法的参数或者返回值,常见单字母或单个单词的方式出现。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("method1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("方法调用的时候会绑定类型信息,可以尽量使用单个单词的命名方法")]),t._v(" "),a("p",[t._v("函数和类型多以多单词驼峰的方法组合,比如 "),a("code",[t._v("func MakeFile(){}")]),t._v(","),a("code",[t._v("type gobEncoderType struct {}")])]),t._v(" "),a("p",[t._v("在命名变量的时候,不要带上类型信息,比如说 "),a("code",[t._v("names")]),t._v(" 比 "),a("code",[t._v("nameSlice")]),t._v(" 要好,因为 go 强调命名和使用越近越好,没必要在字段上加上类型的名称。")]),t._v(" "),a("p",[t._v("go 使用一致性来强调单字母或者单个单词的意义,意思就是说使用的单个字母在任何地方表示的意思都是一样的。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" names"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" users"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("从 k v i 这三个字母就可以观察到,绝大多数情况下,在 go 语言中 kv 就是表示的 key 和 value,i 表示的就是 index,那么即便是单个字母也不会造成识别障碍")]),t._v(" "),a("p",[t._v("另外 "),a("code",[t._v("t")]),t._v(" "),a("code",[t._v("b")]),t._v(" "),a("code",[t._v("n")]),t._v(" 也很常见,他们通常表示 time 和 byte 以及数量")]),t._v(" "),a("h2",{attrs:{id:"常量"}},[t._v("常量")]),t._v(" "),a("ul",[a("li",[t._v("go 语言的常量并不要求全大写,通常只有本身是全大写的常量才是全大写,比如 "),a("code",[t._v("PI")])]),t._v(" "),a("li",[t._v("常量不需要赋予类型,系统会根据根据使用时期左变量的类型,以及运算操作进行自动推断")])]),t._v(" "),a("p",[t._v("一般常量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n keepHostHeader "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("全大写常量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" PI "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.14")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" SIGABRT "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Signal")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0x6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"接口"}},[t._v("接口")]),t._v(" "),a("p",[t._v("拥有唯一方法的接口,或者内嵌多个拥有唯一方法的接口一律使用 "),a("code",[t._v("单词+er")]),t._v(" 结尾,比如 "),a("code",[t._v("Reader")]),t._v(" 或者 "),a("code",[t._v("WriteReadCloser")])]),t._v(" "),a("p",[t._v("go 语言推崇简单接口,和内嵌多个简单接口的接口,所以你会看到 go 语言标准库很多带有 er 结尾的接口")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Reader "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Reade")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Writer "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Write")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" WriteReadeCloser "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Writer\n Reader\n Closer\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"两种命名的对比"}},[t._v("两种命名的对比")]),t._v(" "),a("p",[t._v("简洁的并且考虑上下文一致性的代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RuneCount")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n count "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" RuneSelf "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("DecodeRune")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v("n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n count"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" count\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("见名知意的 java 式的代码:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RuneCount")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n runeCount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" buffer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v(" runeSelf "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n index"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" size "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("DecodeRune")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("buffer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("index"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n index "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" size\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n runeCount"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" runeCount\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("图书:go 语言精进之路")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/51.9dd5ff4a.js b/assets/js/51.9dd5ff4a.js new file mode 100644 index 000000000..9a988411b --- /dev/null +++ b/assets/js/51.9dd5ff4a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{480:function(t,s,a){"use strict";a.r(s);var e=a(36),r=Object(e.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"go-标准库的简单介绍"}},[t._v("go 标准库的简单介绍")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/std")]),t._v(" "),a("h2",{attrs:{id:"archive"}},[t._v("archive")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/archive")]),t._v(" "),a("p",[t._v("目前不存在 archive 包本身,存在其子包,这个包,包含的内容是对于档案文件的处理,比如 tar,zip 这种文档文件。")]),t._v(" "),a("h3",{attrs:{id:"archive-tar"}},[t._v("archive/tar")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/archive/tar")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"archive/tar"')]),t._v("\n")])])]),a("p",[a("code",[t._v("archive/tar")]),t._v(" 包,实现了对 tar 文件的处理")]),t._v(" "),a("ul",[a("li",[t._v("tar 文件头的设置")]),t._v(" "),a("li",[t._v("tar 文件的读写")])]),t._v(" "),a("h3",{attrs:{id:"archive-zip"}},[t._v("archive/zip")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/archive/zip")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"archive/zip"')]),t._v("\n")])])]),a("p",[a("code",[t._v("archive/zip")]),t._v(" 包,实现了对 zip 文件的处理")]),t._v(" "),a("ul",[a("li",[t._v("zip 文件头的设置")]),t._v(" "),a("li",[t._v("zip 文件的读写")])]),t._v(" "),a("h2",{attrs:{id:"bufio"}},[t._v("bufio")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/bufio")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bufio"')]),t._v("\n")])])]),a("p",[a("code",[t._v("bufio")]),t._v(" 包,提供了有缓冲的 i/o,比 io 包封装程度更高。使用缓冲区来一次读取多个字节,从而减少系统调用的次数。")]),t._v(" "),a("ul",[a("li",[t._v("提供了基本的读写功能")]),t._v(" "),a("li",[t._v("提供了逐行读取的功能")])]),t._v(" "),a("h2",{attrs:{id:"builtin"}},[t._v("builtin")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/builtin")]),t._v(" "),a("p",[t._v("注意,此包无法使用 import 的方式引入,因为它只是内部包和内部类型的一个存放位置而已")]),t._v(" "),a("p",[t._v("比如有 append() clear() max() min() int float64 等等")]),t._v(" "),a("h2",{attrs:{id:"bytes"}},[t._v("bytes")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/bytes")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bytes"')]),t._v("\n")])])]),a("p",[t._v("bytes 包,包含了很多处理 bytes 类型的操作。")]),t._v(" "),a("p",[t._v("跟字符串的基本操作类型")]),t._v(" "),a("h2",{attrs:{id:"cmp"}},[t._v("cmp")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/cmp")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cmp"')]),t._v("\n")])])]),a("p",[t._v("cmp 包提供了有关比较的相关内容。")]),t._v(" "),a("ul",[a("li",[t._v("cmp.Ordered 表示可比较的类型约束")]),t._v(" "),a("li",[t._v("提供了比较函数")])]),t._v(" "),a("h2",{attrs:{id:"compress"}},[t._v("compress")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/compress")]),t._v(" "),a("p",[t._v("不直接提供 compress 包,提供了众多子包,所有的内容都是关于压缩算法")]),t._v(" "),a("h3",{attrs:{id:"compress-bzip2"}},[t._v("compress/bzip2")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/compress/bzip2")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"compress/bzip2"')]),t._v("\n")])])]),a("p",[t._v("提供了 bzip2 的解压功能,然而并没有提供压缩的功能")]),t._v(" "),a("h3",{attrs:{id:"compress-flate"}},[t._v("compress/flate")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/compress/flate")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"compress/flate"')]),t._v("\n")])])]),a("p",[t._v("flate 实现了 RFC1951 中描述的 DEFLATE 压缩数据格式。")]),t._v(" "),a("h3",{attrs:{id:"compress-gzip"}},[t._v("compress/gzip")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/compress/gzip")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"compress/gzip"')]),t._v("\n")])])]),a("p",[t._v("gzip 实现了对 gzip 格式压缩文件的解压 (读取) 和压缩 (写入)")]),t._v(" "),a("h3",{attrs:{id:"compress-lzw"}},[t._v("compress/lzw")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/compress/lzw")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"compress/lzw"')]),t._v("\n")])])]),a("p",[t._v("lzw 实现了 lzw 文件 (Lempel-Ziv-Welch) 的解压缩操作。")]),t._v(" "),a("h3",{attrs:{id:"compress-zlib"}},[t._v("compress/zlib")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/compress/zlib")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"compress/zlib"')]),t._v("\n")])])]),a("p",[t._v("zlib 实现了对 zlib 格式文件的解压和压缩操作。")]),t._v(" "),a("h2",{attrs:{id:"container"}},[t._v("container")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/container")]),t._v(" "),a("p",[t._v("container 没有提供本包,提供了众多子包,这个目录下的内容都是关于容器的,这也是 go 提供的内置容器")]),t._v(" "),a("h3",{attrs:{id:"container-heap"}},[t._v("container/heap")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/container/heap")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"container/heap"')]),t._v("\n")])])]),a("p",[t._v("go 内置的堆,值得注意的是,go 语言仅提供了接口以及接口的相关函数,并没有具体的实现,使用时还需要自行实现接口。")]),t._v(" "),a("h3",{attrs:{id:"container-list"}},[t._v("container/list")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/container/list")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(' "container'),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("list\n")])])]),a("p",[t._v("go 内置的双向链表,这里不是接口了,是已经实现好了的双向链表")]),t._v(" "),a("h3",{attrs:{id:"container-ring"}},[t._v("container/ring")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/container/ring")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"container/ring"')]),t._v("\n")])])]),a("p",[t._v("go 内置的循环链表,非接口,已经实现好了")]),t._v(" "),a("h2",{attrs:{id:"context"}},[a("a",{attrs:{href:"../%E5%B9%B6%E5%8F%91/context"}},[t._v("context")])]),t._v(" "),a("p",[t._v("https://pkg.go.dev/context")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"context"')]),t._v("\n")])])]),a("p",[t._v("context 提供了在 “多线程” 的场景下的线程控制功能,简单的说就是 context 这个上下文可以统一取消所有的上下文环境中的 goroutine")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// cal的调用,以及计时器的到达均可调用 ctx.Done() 的发生。")]),t._v("\n\tctx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" cal "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithTimeout")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Background")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("cal")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("select")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("After")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),t._v("ctx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Done")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ttime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"crypto"}},[t._v("crypto")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto"')]),t._v("\n")])])]),a("p",[t._v("crypto 包,包含了很多加密算法")]),t._v(" "),a("h3",{attrs:{id:"crypto-aes"}},[t._v("crypto/aes")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/aes")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/aes"')]),t._v("\n")])])]),a("p",[t._v("提供了 aes 加密算法的加密过程。此算法为对称加密算法")]),t._v(" "),a("ul",[a("li",[t._v("创建一个密钥")])]),t._v(" "),a("h3",{attrs:{id:"crypto-cipher"}},[t._v("crypto/cipher")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/cipher")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/cipher"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-des"}},[t._v("crypto/des")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/des")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/des"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-dsa"}},[t._v("crypto/dsa")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/dsa")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/dsa"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-ecdh"}},[t._v("crypto/ecdh")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/ecdh")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/ecdh"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-ecdsa"}},[t._v("crypto/ecdsa")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/ecdsa")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/ecdsa"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-ed25519"}},[t._v("crypto/ed25519")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/ed25519")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/ed25519"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-elliptic"}},[t._v("crypto/elliptic")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/elliptic")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/elliptic"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-hmac"}},[t._v("crypto/hmac")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/hmac")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/hmac"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-md5"}},[t._v("crypto/md5")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/md5")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/md5"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-rand"}},[t._v("crypto/rand")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/rand")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/rand"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-rc4"}},[t._v("crypto/rc4")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/rc4")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/rc4"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-rsa"}},[t._v("crypto/rsa")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/rsa")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/rsa"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-sha1"}},[t._v("crypto/sha1")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/sha1")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/sha1"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-sha256"}},[t._v("crypto/sha256")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/sha256")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/sha256"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-sha512"}},[t._v("crypto/sha512")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/sha512")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/sha512"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-subtle"}},[t._v("crypto/subtle")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/subtle")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/subtle"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-tls"}},[t._v("crypto/tls")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/tls")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/tls"')]),t._v("\n")])])]),a("h3",{attrs:{id:"crypto-x509"}},[t._v("crypto/x509")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/x509")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/x509"')]),t._v("\n")])])]),a("h4",{attrs:{id:"crypto-x509-pkix"}},[t._v("crypto/x509/pkix")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/crypto/x509/pkix")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"crypto/x509/pkix"')]),t._v("\n")])])]),a("h2",{attrs:{id:"database"}},[t._v("database")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/database\n此包不可直接使用,它包含了子包,这个子包是处理 sql 的统一接口,并不提供实际的实现")]),t._v(" "),a("h3",{attrs:{id:"database-sql"}},[t._v("database/sql")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/database/sql")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"database/sql"')]),t._v("\n")])])]),a("p",[t._v("当我们使用 MySQL,Redis 等数据库的时候,通常要使用上述的方式引入这个包,此包提供了 SQL 操作的接口。")]),t._v(" "),a("p",[t._v("使用此包必须跟第三方的数据库驱动结合,比如下面这种操作:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"database/sql"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"xx/mysql"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),a("h3",{attrs:{id:"database-sql-driver"}},[t._v("database/sql/driver")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/database/sql/driver")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"database/sql/driver"')]),t._v("\n")])])]),a("p",[t._v("driver 包,包含了数据库 driver 的接口,要想实现某个数据库的驱动 (driver) 就必须引入此包,实现此包定义接口的具体内容。")]),t._v(" "),a("p",[t._v("在被用户使用的时候,引入第三方数据库驱动,加上引入 database/sql 这个 SQL 操作包,就可以实现正常的 SQL 操作。")]),t._v(" "),a("h2",{attrs:{id:"debug"}},[t._v("debug")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug")]),t._v(" "),a("p",[t._v("不提供 debug 包本身,debug 包含了众多子包,都是跟调试相关。")]),t._v(" "),a("h3",{attrs:{id:"debug-buildinfo"}},[t._v("debug/buildinfo")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/buildinfo\n不直接使用此包,此包提供二进制的功能,由 runtime/debug 来调用。")]),t._v(" "),a("h3",{attrs:{id:"debug-dwarf"}},[t._v("debug/dwarf")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/dwarf")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug/dwarf"')]),t._v("\n")])])]),a("p",[t._v("用于解析 DWARF 调试信息,DWARF 调试信息包含了程序的源代码、变量、函数、类型等相关信息,可以帮助调试器进行源代码级别的调试。")]),t._v(" "),a("h3",{attrs:{id:"debug-elf"}},[t._v("debug/elf")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/elf")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug/elf"')]),t._v("\n")])])]),a("p",[t._v("用于解析 ELF 可执行文件格式,")]),t._v(" "),a("h3",{attrs:{id:"debug-gosym"}},[t._v("debug/gosym")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/gosym")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug/gosym"')]),t._v("\n")])])]),a("p",[t._v("debug/gosym 用于解析 Go 语言程序的符号表信息。")]),t._v(" "),a("h3",{attrs:{id:"debug-macho"}},[t._v("debug/macho")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/macho")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug/macho"')]),t._v("\n")])])]),a("p",[t._v("debug/macho 用于解析 Mach-O 格式的可执行文件")]),t._v(" "),a("h3",{attrs:{id:"debug-pe"}},[t._v("debug/pe")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/pe")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug/pe"')]),t._v("\n")])])]),a("p",[t._v("debug/pe 用于解析 PE 格式的可执行文件")]),t._v(" "),a("h3",{attrs:{id:"debug-plan9obj"}},[t._v("debug/plan9obj")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/debug/plan9obj")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"debug/plan9obj"')]),t._v("\n")])])]),a("p",[t._v("debug/plan9obj 用于解析 Plan 9 object 文件格式。")]),t._v(" "),a("h2",{attrs:{id:"embed"}},[t._v("embed")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/embed")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"embed"')]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//go:embed hello.text")]),t._v("\n")])])]),a("p",[t._v("mbed 是 Go 语言自 1.16 版本引入的一个标准库,用于将静态文件嵌入到 Go 代码中。")]),t._v(" "),a("p",[t._v("通过 embed 包,我们可以将静态文件 (如文本文件、JSON 文件、HTML 文件、图像文件等) 直接嵌入到 Go 代码中,而无需将文件作为独立的资源文件放在磁盘上。这样做的好处是,可以将所有的资源文件打包到可执行文件中,方便分发和部署。")]),t._v(" "),a("p",[t._v("将一个文件嵌入到一个 string 中")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"embed"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里的注释开头没有空格,这是 go 的自有命令注释;//go:xx ")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//go:embed hello.txt")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("将一个文件嵌入到文件系统中")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"embed"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//go:embed hello.txt")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" helloFile embed"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("FS\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tcontent"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" helloFile"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("ReadFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello.txt"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"无法读取文件:"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("content"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"encoding"}},[t._v("encoding")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding\n使用时,不直接使用 encoding,除非你想亲自实现某个编码的加解码")]),t._v(" "),a("p",[t._v("encoding 是 Go 语言标准库中的一个包,用于处理数据的编码和解码。")]),t._v(" "),a("p",[t._v("encoding 包提供了许多子包,每个子包都专门用于处理特定的数据编码格式")]),t._v(" "),a("ul",[a("li",[t._v("encoding/json:用于处理 JSON 数据的编码和解码。")]),t._v(" "),a("li",[t._v("encoding/xml:用于处理 XML 数据的编码和解码。")]),t._v(" "),a("li",[t._v("encoding/csv:用于处理 CSV (逗号分隔值) 数据的编码和解码。")]),t._v(" "),a("li",[t._v("encoding/base64:用于进行 base64 编码和解码。")]),t._v(" "),a("li",[t._v("encoding/hex:用于进行十六进制编码和解码。")]),t._v(" "),a("li",[t._v("encoding/gob:用于进行 Go 对象的编码和解码。")])]),t._v(" "),a("h3",{attrs:{id:"encoding-ascii85"}},[t._v("encoding/ascii85")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/ascii85")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/ascii85"')]),t._v("\n")])])]),a("p",[t._v("encoding/ascii85 用于进行 ASCII85 编码和解码")]),t._v(" "),a("h3",{attrs:{id:"encoding-asn1"}},[t._v("encoding/asn1")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/asn1")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/asn1"')]),t._v("\n")])])]),a("p",[t._v("encoding/asn1 用于进行 ASN.1 (Abstract Syntax Notation One) 编码和解码。")]),t._v(" "),a("h3",{attrs:{id:"encoding-base32"}},[t._v("encoding/base32")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/base32")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/base32"')]),t._v("\n")])])]),a("h3",{attrs:{id:"encoding-base64"}},[t._v("encoding/base64")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/base64")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/base64"')]),t._v("\n")])])]),a("p",[t._v("encoding/base32 用于进行 Base32 编码和解码")]),t._v(" "),a("h3",{attrs:{id:"encoding-binary"}},[t._v("encoding/binary")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/binary")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/binary"')]),t._v("\n")])])]),a("p",[t._v("encoding/base64 用于进行 Base64 编码和解码。")]),t._v(" "),a("h3",{attrs:{id:"encoding-csv"}},[t._v("encoding/csv")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/csv")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/csv"')]),t._v("\n")])])]),a("p",[t._v("encoding/csv 用于处理 CSV (逗号分隔值) 格式的数据。")]),t._v(" "),a("h3",{attrs:{id:"encoding-gob"}},[t._v("encoding/gob")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/gob")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/gob"')]),t._v("\n")])])]),a("p",[t._v("encoding/gob 用于将 Go 的值编码为二进制格式,并进行序列化和反序列化。")]),t._v(" "),a("h3",{attrs:{id:"encoding-hex"}},[t._v("encoding/hex")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/hex")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/hex"')]),t._v("\n")])])]),a("p",[t._v("十六进制编码将二进制数据编码为十六进制字符串,每个字节对应两个十六进制字符。十六进制编码通常用于将二进制数据转换为可打印的 ASCII 字符串,例如在 URL 参数中传递二进制数据或在文本文件中嵌入二进制数据。")]),t._v(" "),a("p",[t._v("encoding/hex 包提供了一组函数和类型,用于进行十六进制编码和解码。主要有两个函数:EncodeToString 和 DecodeString。")]),t._v(" "),a("h3",{attrs:{id:"encoding-json"}},[t._v("encoding/json")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/json")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/json"')]),t._v("\n")])])]),a("p",[t._v("encoding/json 用于对 JSON (JavaScript Object Notation) 格式的数据进行编码和解码操作。")]),t._v(" "),a("p",[t._v("JSON 是一种常用的数据交换格式,用于在不同平台和编程语言之间传输和存储数据。JSON 数据由键值对组成,可以表示复杂的数据结构和层次关系。")]),t._v(" "),a("h3",{attrs:{id:"encoding-pem"}},[t._v("encoding/pem")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/pem")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/pem"')]),t._v("\n")])])]),a("p",[t._v("encoding/pem 用于对 PEM (Privacy-Enhanced Mail) 格式的数据进行编码和解码操作。")]),t._v(" "),a("p",[t._v("PEM 是一种常用的文本格式,用于在非文本环境中传输和存储密钥、证书等数据。PEM 格式使用 ASCII 字符表示二进制数据,通常以 “-----BEGIN…” 和 “-----END…” 标记来标识不同类型的数据。")]),t._v(" "),a("h3",{attrs:{id:"encoding-xml"}},[t._v("encoding/xml")]),t._v(" "),a("p",[t._v("https://pkg.go.dev/encoding/xml")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"encoding/xml"')]),t._v("\n")])])]),a("p",[t._v("encoding/xml 用于对 XML (eXtensible Markup Language) 格式的数据进行编码和解码操作。")]),t._v(" "),a("p",[t._v("XML 是一种常用的文本格式,用于存储和传输结构化的数据。XML 数据由标签、属性和文本内容组成,可以表示复杂的数据结构和层次关系。")]),t._v(" "),a("h2",{attrs:{id:"errors"}},[t._v("errors")]),t._v(" "),a("h2",{attrs:{id:"expvar"}},[t._v("expvar")]),t._v(" "),a("h2",{attrs:{id:"flag"}},[t._v("flag")]),t._v(" "),a("h2",{attrs:{id:"fmt"}},[t._v("fmt")]),t._v(" "),a("h2",{attrs:{id:"go"}},[t._v("go")]),t._v(" "),a("h3",{attrs:{id:"go-ast"}},[t._v("go/ast")]),t._v(" "),a("h3",{attrs:{id:"go-build"}},[t._v("go/build")]),t._v(" "),a("h4",{attrs:{id:"go-build-constraint"}},[t._v("go/build/constraint")]),t._v(" "),a("h3",{attrs:{id:"go-constant"}},[t._v("go/constant")]),t._v(" "),a("h3",{attrs:{id:"go-doc"}},[t._v("go/doc")]),t._v(" "),a("h4",{attrs:{id:"go-doc-comment"}},[t._v("go/doc/comment")]),t._v(" "),a("h3",{attrs:{id:"go-format"}},[t._v("go/format")]),t._v(" "),a("h3",{attrs:{id:"go-importer"}},[t._v("go/importer")]),t._v(" "),a("h3",{attrs:{id:"go-parser"}},[t._v("go/parser")]),t._v(" "),a("h3",{attrs:{id:"go-printer"}},[t._v("go/printer")]),t._v(" "),a("h3",{attrs:{id:"go-scanner"}},[t._v("go/scanner")]),t._v(" "),a("h3",{attrs:{id:"go-token"}},[t._v("go/token")]),t._v(" "),a("h3",{attrs:{id:"go-types"}},[t._v("go/types")]),t._v(" "),a("h2",{attrs:{id:"hash"}},[t._v("hash")]),t._v(" "),a("h3",{attrs:{id:"hash-adler32"}},[t._v("hash/adler32")]),t._v(" "),a("h3",{attrs:{id:"hash-crc32"}},[t._v("hash/crc32")]),t._v(" "),a("h3",{attrs:{id:"hash-crc64"}},[t._v("hash/crc64")]),t._v(" "),a("h3",{attrs:{id:"hash-fnv"}},[t._v("hash/fnv")]),t._v(" "),a("h3",{attrs:{id:"hash-maphash"}},[t._v("hash/maphash")]),t._v(" "),a("h2",{attrs:{id:"html"}},[t._v("html")]),t._v(" "),a("h3",{attrs:{id:"html-template"}},[t._v("html/template")]),t._v(" "),a("h2",{attrs:{id:"image"}},[t._v("image")]),t._v(" "),a("h3",{attrs:{id:"image-color"}},[t._v("image/color")]),t._v(" "),a("h4",{attrs:{id:"image-color-palette"}},[t._v("image/color/palette")]),t._v(" "),a("h3",{attrs:{id:"image-draw"}},[t._v("image/draw")]),t._v(" "),a("h3",{attrs:{id:"image-gif"}},[t._v("image/gif")]),t._v(" "),a("h3",{attrs:{id:"image-jpeg"}},[t._v("image/jpeg")]),t._v(" "),a("h3",{attrs:{id:"png"}},[t._v("png")]),t._v(" "),a("h2",{attrs:{id:"index"}},[t._v("index")]),t._v(" "),a("h3",{attrs:{id:"index-suffixarray"}},[t._v("index/suffixarray")]),t._v(" "),a("h2",{attrs:{id:"io"}},[t._v("io")]),t._v(" "),a("h3",{attrs:{id:"io-fs"}},[t._v("io/fs")]),t._v(" "),a("h3",{attrs:{id:"io-ioutil"}},[t._v("io/ioutil")]),t._v(" "),a("h2",{attrs:{id:"log"}},[t._v("log")]),t._v(" "),a("h3",{attrs:{id:"log-slog"}},[t._v("log/slog")]),t._v(" "),a("h3",{attrs:{id:"log-syslog"}},[t._v("log/syslog")]),t._v(" "),a("h2",{attrs:{id:"maps"}},[t._v("maps")]),t._v(" "),a("h2",{attrs:{id:"math"}},[t._v("math")]),t._v(" "),a("h3",{attrs:{id:"math-big"}},[t._v("math/big")]),t._v(" "),a("h3",{attrs:{id:"math-bits"}},[t._v("math/bits")]),t._v(" "),a("h3",{attrs:{id:"math-cmplx"}},[t._v("math/cmplx")]),t._v(" "),a("h3",{attrs:{id:"math-rand"}},[t._v("math/rand")]),t._v(" "),a("h2",{attrs:{id:"mime"}},[t._v("mime")]),t._v(" "),a("h3",{attrs:{id:"mime-multipart"}},[t._v("mime/multipart")]),t._v(" "),a("h3",{attrs:{id:"mime-quotedprintable"}},[t._v("mime/quotedprintable")]),t._v(" "),a("h2",{attrs:{id:"net"}},[t._v("net")]),t._v(" "),a("h3",{attrs:{id:"net-http"}},[t._v("net/http")]),t._v(" "),a("h4",{attrs:{id:"net-http-cgi"}},[t._v("net/http/cgi")]),t._v(" "),a("h4",{attrs:{id:"net-http-cookiejar"}},[t._v("net/http/cookiejar")]),t._v(" "),a("h4",{attrs:{id:"net-http-fcgi"}},[t._v("net/http/fcgi")]),t._v(" "),a("h4",{attrs:{id:"net-http-httptest"}},[t._v("net/http/httptest")]),t._v(" "),a("h4",{attrs:{id:"net-http-httptrace"}},[t._v("net/http/httptrace")]),t._v(" "),a("h4",{attrs:{id:"net-http-httputil"}},[t._v("net/http/httputil")]),t._v(" "),a("h4",{attrs:{id:"net-http-pprof"}},[t._v("net/http/pprof")]),t._v(" "),a("h3",{attrs:{id:"net-mail"}},[t._v("net/mail")]),t._v(" "),a("h3",{attrs:{id:"net-netip"}},[t._v("net/netip")]),t._v(" "),a("h3",{attrs:{id:"net-rpc"}},[t._v("net/rpc")]),t._v(" "),a("h4",{attrs:{id:"net-rpc-jsonrpc"}},[t._v("net/rpc/jsonrpc")]),t._v(" "),a("h3",{attrs:{id:"net-smtp"}},[t._v("net/smtp")]),t._v(" "),a("h3",{attrs:{id:"net-textproto"}},[t._v("net/textproto")]),t._v(" "),a("h3",{attrs:{id:"net-url"}},[t._v("net/url")]),t._v(" "),a("h2",{attrs:{id:"os"}},[t._v("os")]),t._v(" "),a("h3",{attrs:{id:"os-exec"}},[t._v("os/exec")]),t._v(" "),a("h3",{attrs:{id:"os-signal"}},[t._v("os/signal")]),t._v(" "),a("h3",{attrs:{id:"os-user"}},[t._v("os/user")]),t._v(" "),a("h2",{attrs:{id:"path"}},[t._v("path")]),t._v(" "),a("h3",{attrs:{id:"path-filepath"}},[t._v("path/filepath")]),t._v(" "),a("h2",{attrs:{id:"plugin"}},[t._v("plugin")]),t._v(" "),a("h2",{attrs:{id:"reflect"}},[t._v("reflect")]),t._v(" "),a("h2",{attrs:{id:"regexp"}},[t._v("regexp")]),t._v(" "),a("h3",{attrs:{id:"regexp-syntax"}},[t._v("regexp/syntax")]),t._v(" "),a("h2",{attrs:{id:"runtime"}},[t._v("runtime")]),t._v(" "),a("h3",{attrs:{id:"runtime-cgo"}},[t._v("runtime/cgo")]),t._v(" "),a("h3",{attrs:{id:"runtime-coverage"}},[t._v("runtime/coverage")]),t._v(" "),a("h3",{attrs:{id:"runtime-debug"}},[t._v("runtime/debug")]),t._v(" "),a("h3",{attrs:{id:"runtime-metrics"}},[t._v("runtime/metrics")]),t._v(" "),a("h3",{attrs:{id:"runtime-pprof"}},[t._v("runtime/pprof")]),t._v(" "),a("h3",{attrs:{id:"runtime-race"}},[t._v("runtime/race")]),t._v(" "),a("h3",{attrs:{id:"runtime-trace"}},[t._v("runtime/trace")]),t._v(" "),a("h2",{attrs:{id:"slices"}},[t._v("slices")]),t._v(" "),a("h2",{attrs:{id:"sort"}},[t._v("sort")]),t._v(" "),a("h2",{attrs:{id:"strconv"}},[t._v("strconv")]),t._v(" "),a("h2",{attrs:{id:"strings"}},[t._v("strings")]),t._v(" "),a("h2",{attrs:{id:"sync"}},[t._v("sync")]),t._v(" "),a("h3",{attrs:{id:"sync-atomic"}},[t._v("sync/atomic")]),t._v(" "),a("h2",{attrs:{id:"syscall"}},[t._v("syscall")]),t._v(" "),a("h3",{attrs:{id:"sync-js"}},[t._v("sync/js")]),t._v(" "),a("h2",{attrs:{id:"testing"}},[t._v("testing")]),t._v(" "),a("h3",{attrs:{id:"testing-fstest"}},[t._v("testing/fstest")]),t._v(" "),a("h3",{attrs:{id:"testing-iotest"}},[t._v("testing/iotest")]),t._v(" "),a("h3",{attrs:{id:"testing-quick"}},[t._v("testing/quick")]),t._v(" "),a("h3",{attrs:{id:"testing-slogtest"}},[t._v("testing/slogtest")]),t._v(" "),a("h2",{attrs:{id:"text"}},[t._v("text")]),t._v(" "),a("h3",{attrs:{id:"text-scanner"}},[t._v("text/scanner")]),t._v(" "),a("h3",{attrs:{id:"text-tabwriter"}},[t._v("text/tabwriter")]),t._v(" "),a("h3",{attrs:{id:"text-template"}},[t._v("text/template")]),t._v(" "),a("h4",{attrs:{id:"template-parse"}},[t._v("template/parse")]),t._v(" "),a("h2",{attrs:{id:"time"}},[t._v("time")]),t._v(" "),a("h3",{attrs:{id:"time-tzdata"}},[t._v("time/tzdata")]),t._v(" "),a("h2",{attrs:{id:"unicode"}},[t._v("unicode")]),t._v(" "),a("h3",{attrs:{id:"unicode-utf16"}},[t._v("unicode/utf16")]),t._v(" "),a("h3",{attrs:{id:"unicode-utf8"}},[t._v("unicode/utf8")]),t._v(" "),a("h2",{attrs:{id:"unsafe"}},[t._v("unsafe")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/52.9dfffd13.js b/assets/js/52.9dfffd13.js new file mode 100644 index 000000000..820472b8b --- /dev/null +++ b/assets/js/52.9dfffd13.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{483:function(t,e,n){"use strict";n.r(e);var s=n(36),i=Object(s.a)({},(function(){var t=this.$createElement,e=this._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[e("h1",{attrs:{id:"encoding-hex"}},[this._v("encoding/hex")]),this._v(" "),e("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),e("ul",[e("li",[this._v("https://pkg.go.dev/encoding/hex@go1.17.8#DecodeString")])])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/53.c98436b4.js b/assets/js/53.c98436b4.js new file mode 100644 index 000000000..4d3846803 --- /dev/null +++ b/assets/js/53.c98436b4.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[53],{482:function(t,s,i){"use strict";i.r(s);var n=i(36),e=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"fmt"}},[this._v("fmt")]),this._v(" "),s("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),s("ul",[s("li",[this._v("https://studygolang.com/topics/2594/comment/7252")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/54.ee26f0f5.js b/assets/js/54.ee26f0f5.js new file mode 100644 index 000000000..908dfe19b --- /dev/null +++ b/assets/js/54.ee26f0f5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[54],{484:function(t,a,s){"use strict";s.r(a);var n=s(36),r=Object(n.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"sync"}},[t._v("sync")]),t._v(" "),s("h2",{attrs:{id:"sync-map"}},[t._v("sync.Map")]),t._v(" "),s("h3",{attrs:{id:"sync-map-的底层数据"}},[t._v("sync.Map 的底层数据")]),t._v(" "),s("p",[t._v("sync.Map 适合在读多写少的场景下使用,sync.Map 的核心思想是读写分离,以及用空间换时间。")]),t._v(" "),s("p",[t._v("有两个数据结构:")]),t._v(" "),s("p",[s("code",[t._v("dirty")]),t._v(" 数据结构")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Map "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 互斥锁")]),t._v("\n mu Mutex\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 原子操作")]),t._v("\n read atomic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Value\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// dirty数据 ")]),t._v("\n dirty "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("entry\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 标记tag 表示数据每次从diry中往read中迁移一个就+1")]),t._v("\n misses "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[s("code",[t._v("read")]),t._v(" 数据结构")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" readOnly "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n m "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("entry\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 标记:false 证明数据不只是read中有,dirty也有")]),t._v("\n amended "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("bool")]),t._v(" \n")])])]),s("p",[t._v("读数据是优先从 read 中读 (注意,read 是只读的数据结构,所以不加锁),如果 read 不包含这个数据,会从 dirty 中读取 (注意,从 dirty 查找的时候会加锁),并 misses+1,直到 misses 大于 dirty,开始迁移数据,数据一次性从 dirty 传到 read 中。")]),t._v(" "),s("p",[t._v("因为 read 没有锁,所以才说,sync.Map 读的时候效率高。")]),t._v(" "),s("p",[t._v("当新增的时候,从 read 和 dirty 中查找是否用数据,在 read 有数据且没有被标记为清除就无锁覆盖原来的值。这个时候开始加锁了,如果在 read 中虽然有数据,但是被标记为清除了,并且 dirty 没有数据,就加入到 diry 中,如果这个时候 read 有数据,虽然被被标记为删除了,dirty 也有数据,那么直接原子更新数据即可。如果数据不在 read,在 dirty 中,直接在 dirty 中更新即可,如果数据不在 read 中也不再 dirty 中,如果这个时候 read.amended 是 false (意思就是 dirty 空了),"),s("strong",[t._v("那么就必须将数据一点一点从 read 中复制到 dirty 中")]),t._v(",如果是 true 就不用复制了,在完成这个工序后,再把数据放置在 dirty 中。")]),t._v(" "),s("p",[t._v("删除的时候,就先从 read 中查找,有了就原子性质的将其标记为 nil,并不是真的删,没有就加锁从 dirty 中找,有了就删。这个时候是真删,如果都没有就返回。")]),t._v(" "),s("p",[t._v("在写多读少的时候,涉及到 read 中无数据就会频繁的加锁去 dirty 中查找、read 和 dirty 交换等开销,比常规的 map 加锁性能更差。因为普通的只是加锁,sync.Map 不仅仅是加锁,还得复制数据,这花销就更大了。")]),t._v(" "),s("p",[t._v("总结:"),s("strong",[t._v("高并发,读多写少可以使用 sync.Map,如果读少写多,不要使用 sync.Map,比常规锁+map 更慢")])]),t._v(" "),s("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),s("ul",[s("li",[t._v("https://zhuanlan.zhihu.com/p/353440086")])])])}),[],!1,null,null,null);a.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/55.7b5dc58d.js b/assets/js/55.7b5dc58d.js new file mode 100644 index 000000000..29eab4571 --- /dev/null +++ b/assets/js/55.7b5dc58d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[55],{485:function(t,o,i){"use strict";i.r(o);var _=i(36),v=Object(_.a)({},(function(){var t=this,o=t.$createElement,i=t._self._c||o;return i("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[i("h1",{attrs:{id:"go-编程范式"}},[t._v("go 编程范式")]),t._v(" "),i("h2",{attrs:{id:"创建模式"}},[t._v("创建模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/创建者/"}},[t._v("创建者")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/工厂方法/"}},[t._v("工厂方法")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/对象池/"}},[t._v("对象池")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/单例/"}},[t._v("单例")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/原型/"}},[t._v("原型")])],1)]),t._v(" "),i("h2",{attrs:{id:"结构模式"}},[t._v("结构模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/装饰器/"}},[t._v("装饰器")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/代理/"}},[t._v("代理")])],1)]),t._v(" "),i("h2",{attrs:{id:"行为模式"}},[t._v("行为模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/观察者/"}},[t._v("观察者")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/策略/"}},[t._v("策略")])],1)]),t._v(" "),i("h2",{attrs:{id:"同步模式"}},[t._v("同步模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/信号量/"}},[t._v("信号量")])],1)]),t._v(" "),i("h2",{attrs:{id:"并发模式"}},[t._v("并发模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/有界并行/"}},[t._v("有界并行")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/生成器/"}},[t._v("生成器")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/并行/"}},[t._v("并行")])],1)]),t._v(" "),i("h2",{attrs:{id:"消息传递模式"}},[t._v("消息传递模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/扇入/"}},[t._v("扇入")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/扇出/"}},[t._v("扇出")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/发布者订阅者/"}},[t._v("发布者订阅者")])],1)]),t._v(" "),i("h2",{attrs:{id:"稳定性模式"}},[t._v("稳定性模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/断路器/"}},[t._v("断路器")])],1)]),t._v(" "),i("h2",{attrs:{id:"分析模式"}},[t._v("分析模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/定时函数/"}},[t._v("定时函数")])],1)]),t._v(" "),i("h2",{attrs:{id:"函数式编程模式"}},[t._v("函数式编程模式")]),t._v(" "),i("ul",[i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/功能选项/"}},[t._v("功能选项")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/k8s_visitor/"}},[t._v("k8s visitor")])],1),t._v(" "),i("li",[i("RouterLink",{attrs:{to:"/工程/go编程范式/pipeline/"}},[t._v("pipeline")])],1)]),t._v(" "),i("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),i("ul",[i("li",[t._v("https://github.com/shgopher/go-patterns")]),t._v(" "),i("li",[t._v("https://time.geekbang.org/column/article/386238")]),t._v(" "),i("li",[t._v("https://mp.weixin.qq.com/s/Sv-SXDYxea_K_TtiI_CjTw")]),t._v(" "),i("li",[t._v("https://mp.weixin.qq.com/s/KRgNwJt1C7q2ckeqCu9pCQ")])])])}),[],!1,null,null,null);o.default=v.exports}}]); \ No newline at end of file diff --git a/assets/js/56.e3024720.js b/assets/js/56.e3024720.js new file mode 100644 index 000000000..416c1179e --- /dev/null +++ b/assets/js/56.e3024720.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[56],{486:function(t,s,e){"use strict";e.r(s);var i=e(36),n=Object(i.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"k8s-visitor"}},[this._v("k8s visitor")])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/57.ba1b4c58.js b/assets/js/57.ba1b4c58.js new file mode 100644 index 000000000..0041bf3a3 --- /dev/null +++ b/assets/js/57.ba1b4c58.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[57],{487:function(t,e,n){"use strict";n.r(e);var s=n(36),i=Object(s.a)({},(function(){var t=this.$createElement,e=this._self._c||t;return e("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[e("h1",{attrs:{id:"pipeline"}},[this._v("pipeline")])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/58.d6c32d73.js b/assets/js/58.d6c32d73.js new file mode 100644 index 000000000..b5c2b5d6c --- /dev/null +++ b/assets/js/58.d6c32d73.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[58],{488:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/59.a733d97b.js b/assets/js/59.a733d97b.js new file mode 100644 index 000000000..679024ca0 --- /dev/null +++ b/assets/js/59.a733d97b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[59],{489:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/6.5f593451.js b/assets/js/6.5f593451.js new file mode 100644 index 000000000..0fd6d8b35 --- /dev/null +++ b/assets/js/6.5f593451.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{426:function(t,r,e){t.exports=e.p+"assets/img/wechat.4a3030a4.png"},440:function(t,r,e){"use strict";e.r(r);var a=e(36),E=Object(a.a)({},(function(){var t=this,r=t.$createElement,a=t._self._c||r;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("p",{attrs:{align:"left"}},[t._v("\nhey~,我是科科,目前就职于国内一家互联网公司,你们可以加我"),a("a",{attrs:{href:"#wechat.png"}},[t._v("微信")]),t._v(",交个朋友吧~\n")]),t._v(" "),a("br"),t._v(" "),a("p",{attrs:{align:"center"}},[a("a",{attrs:{href:"#wechat.png",target:"_blank"}},[a("img",{attrs:{src:"https://img.shields.io/static/v1?label=%E7%A7%91%E7%A7%91%E4%BA%BA%E7%A5%9E&message=%E5%85%AC%E4%BC%97%E5%8F%B7&color="}})]),t._v(" "),a("a",{attrs:{href:"https://space.bilibili.com/478621088",target:"_blank"}},[a("img",{attrs:{src:"https://img.shields.io/static/v1?label=bilibili&message=b%E7%AB%99&color=blue"}})]),t._v(" "),a("a",{attrs:{href:"https://www.zhihu.com/people/shgopher",target:"_blank"}},[a("img",{attrs:{src:"https://img.shields.io/static/v1?label=zhihu&message=%E7%9F%A5%E4%B9%8E&color=blue"}})]),t._v(" "),a("a",{attrs:{href:"https://blog.csdn.net/zyfljxzby",target:"_blank"}},[a("img",{attrs:{src:"https://img.shields.io/static/v1?label=csdn&message=CSDN&color=red"}})]),t._v(" "),a("a",{attrs:{href:"https://www.toutiao.com/c/user/token/MS4wLjABAAAAIGeO1-kCUelF-G8GW3AvJlrEL7tiO24WHJmnX4nV1bs",target:"_blank"}},[a("img",{attrs:{src:"https://img.shields.io/static/v1?label=toutiao&message=%E5%A4%B4%E6%9D%A1&color=red"}})])]),t._v(" "),a("p",[t._v("添加微信公众号:"),a("a",{attrs:{href:"#wechat.png"}},[t._v("科科人神")]),t._v(",回复:")]),t._v(" "),a("ul",[a("li",[a("p",[a("code",[t._v("面试题")]),t._v(",获取经典 go 面试大全 (巨全,强推,不仅有 go 面试题还有大厂的算法和系统设计原题以及面试技巧等等内容)")])]),t._v(" "),a("li",[a("p",[a("code",[t._v("好友")]),t._v(",可以添加作者的微信好友")])])]),t._v(" "),a("h2",{attrs:{id:"基础"}},[t._v("基础")]),t._v(" "),a("ul",[a("li",[a("RouterLink",{attrs:{to:"/基础/helloWorld/"}},[t._v("hello world")])],1),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E"}},[t._v("变量声明")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E"}},[t._v("常量声明")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC"}},[t._v("零值")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F"}},[t._v("复合字面量")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B"}},[t._v("数字类型")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93"}},[t._v("结构体")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/slice"}},[t._v("slice")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/string"}},[t._v("string")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/map"}},[t._v("map")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F"}},[t._v("求值顺序")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F"}},[t._v("作用域")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95"}},[t._v("函数方法")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/interface"}},[t._v("接口")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5"}},[t._v("逻辑和判断语句")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B"}},[t._v("泛型")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86"}},[t._v("错误处理")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9"}},[t._v("其他内容")])])]),t._v(" "),a("h2",{attrs:{id:"并发"}},[t._v("并发")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B"}},[t._v("内存模型")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B"}},[t._v("并发模型")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD"}},[t._v("同步原语")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91/channel"}},[t._v("channel")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91/context"}},[t._v("context")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B9%B6%E5%8F%91/atomic"}},[t._v("atomic")])])]),t._v(" "),a("h2",{attrs:{id:"runtime"}},[t._v("runtime")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"./runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95"}},[t._v("三色 gc 算法")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./runtime/gmp"}},[t._v("G:M:P")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D"}},[t._v("堆内存分配")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86"}},[t._v("栈内存管理")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7"}},[t._v("系统监控")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./runtime/netpool"}},[t._v("netpool")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./runtime/%E5%AE%9A%E6%97%B6%E5%99%A8"}},[t._v("定时器")])])]),t._v(" "),a("h2",{attrs:{id:"编译器"}},[t._v("编译器")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"./%E7%BC%96%E8%AF%91%E5%99%A8/gc"}},[t._v("gc")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E7%BC%96%E8%AF%91%E5%99%A8/llvm"}},[t._v("llvm")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E7%BC%96%E8%AF%91%E5%99%A8/gccgo"}},[t._v("gccgo")])])]),t._v(" "),a("h2",{attrs:{id:"工程"}},[t._v("工程")]),t._v(" "),a("ul",[a("li",[a("RouterLink",{attrs:{to:"/工程/go编程范式/"}},[t._v("go 编程范式/设计模式")])],1),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7"}},[t._v("包管理工具")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/log"}},[t._v("log 包")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95"}},[t._v("测试")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95"}},[t._v("动态调试")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/cgo"}},[t._v("cgo")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5"}},[t._v("代码检查")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84"}},[t._v("反射")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B"}},[t._v("go web 编程")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/wasm"}},[t._v("wasm")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/ioc"}},[t._v("ioc")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4"}},[t._v("命令")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81"}},[t._v("字符编码")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86"}},[t._v("系统信号的处理")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E7%9A%84%E7%A7%98%E5%AF%86%E5%AD%A6"}},[t._v("go 语言的密码学")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85"}},[t._v("优秀第三方包")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93"}},[t._v("go 标准库")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F"}},[t._v("go 项目组织形式")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B"}},[t._v("go 命名惯例")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83"}},[t._v("go 语言规范")])]),t._v(" "),a("li",[a("a",{attrs:{href:"./%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98"}},[t._v("go 面试题")])])]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://go.dev",target:"_blank",rel:"noopener noreferrer"}},[t._v("go.dev"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/golang/go",target:"_blank",rel:"noopener noreferrer"}},[t._v("go src"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://www.gopl.io/",target:"_blank",rel:"noopener noreferrer"}},[t._v("the go programming language"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://book.douban.com/subject/35720729/",target:"_blank",rel:"noopener noreferrer"}},[t._v("GO 语言精进之路"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://shgopher.github.io/pdf/mastering-go-cn.pdf",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mastering Go"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://draveness.me/golang/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Go 语言设计与实现"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://book.douban.com/subject/36104087/",target:"_blank",rel:"noopener noreferrer"}},[t._v("深度探索 GO 语言"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://juejin.cn/post/7241452578125824061",target:"_blank",rel:"noopener noreferrer"}},[t._v("我为什么放弃 GO 语言?"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/teivah/100-go-mistakes",target:"_blank",rel:"noopener noreferrer"}},[t._v("100-go-mistakes"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://time.geekbang.org/opencourse/intro/100069501",target:"_blank",rel:"noopener noreferrer"}},[t._v("Go 语言编程模式实战"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://time.geekbang.org/column/intro/100061801",target:"_blank",rel:"noopener noreferrer"}},[t._v("Go 并发编程实战课"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://time.geekbang.org/column/intro/100079601",target:"_blank",rel:"noopener noreferrer"}},[t._v("Go 语言项目开发实战"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://time.geekbang.org/column/intro/100013101",target:"_blank",rel:"noopener noreferrer"}},[t._v("Go 语言核心 36 讲"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://time.geekbang.org/column/intro/100090601",target:"_blank",rel:"noopener noreferrer"}},[t._v("手把手带你写一个 Web 框架"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://coding.imooc.com/class/chapter/180.html#Anchor",target:"_blank",rel:"noopener noreferrer"}},[t._v("Google 资深工程师深度讲解 Go 语言"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/LeoYang90/Golang-Internal-Notes",target:"_blank",rel:"noopener noreferrer"}},[t._v("Golang-Internal-Notes"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://space.bilibili.com/373073810",target:"_blank",rel:"noopener noreferrer"}},[t._v("刘丹冰 Aceld bilibili"),a("OutboundLink")],1)])]),t._v(" "),a("h2",{attrs:{id:"扫一扫添加我的公众号-回复-加群-可以加入微信群。"}},[t._v("扫一扫添加我的公众号,回复 “加群”,可以加入微信群。")]),t._v(" "),a("p",{attrs:{id:"wechat.png",align:"center"}},[a("br"),t._v(" "),a("br"),t._v(" "),a("img",{attrs:{src:e(426),alt:"公众号搜:科科人神"}})]),t._v(" "),a("h2",{attrs:{id:"star"}},[t._v("star")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://starchart.cc/shgopher/GOFamily",target:"_blank",rel:"noopener noreferrer"}},[a("img",{attrs:{src:"https://starchart.cc/shgopher/GOFamily.svg",alt:"Stargazers over time"}}),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"证书"}},[t._v("证书")]),t._v(" "),a("p",[a("a",{attrs:{rel:"license",href:"http://creativecommons.org/licenses/by/3.0/"}},[a("img",{staticStyle:{"border-width":"0"},attrs:{alt:"知识共享许可协议",src:"https://i.creativecommons.org/l/by/3.0/88x31.png"}})]),a("br"),t._v("本作品采用"),a("a",{attrs:{rel:"license",href:"http://creativecommons.org/licenses/by/3.0/"}},[t._v("知识共享署名 3.0 未本地化版本许可协议")]),t._v("进行许可。")])])}),[],!1,null,null,null);r.default=E.exports}}]); \ No newline at end of file diff --git a/assets/js/60.f162e276.js b/assets/js/60.f162e276.js new file mode 100644 index 000000000..ee40799e3 --- /dev/null +++ b/assets/js/60.f162e276.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[60],{491:function(t,s,e){"use strict";e.r(s);var n=e(36),r=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"创建者模式"}},[this._v("创建者模式")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/61.155a3987.js b/assets/js/61.155a3987.js new file mode 100644 index 000000000..dce5f1bf5 --- /dev/null +++ b/assets/js/61.155a3987.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[61],{490:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/62.ad6d715b.js b/assets/js/62.ad6d715b.js new file mode 100644 index 000000000..f4d640c09 --- /dev/null +++ b/assets/js/62.ad6d715b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[62],{492:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/63.088bb315.js b/assets/js/63.088bb315.js new file mode 100644 index 000000000..17ac3cb0d --- /dev/null +++ b/assets/js/63.088bb315.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[63],{493:function(t,s,e){"use strict";e.r(s);var n=e(36),r=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"原型模式"}},[this._v("原型模式")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/64.58e4a79c.js b/assets/js/64.58e4a79c.js new file mode 100644 index 000000000..efaaff597 --- /dev/null +++ b/assets/js/64.58e4a79c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[64],{495:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/65.9e82002d.js b/assets/js/65.9e82002d.js new file mode 100644 index 000000000..23afe3ca6 --- /dev/null +++ b/assets/js/65.9e82002d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[65],{494:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/66.949483d3.js b/assets/js/66.949483d3.js new file mode 100644 index 000000000..cc4fd883b --- /dev/null +++ b/assets/js/66.949483d3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[66],{496:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/67.613f77e3.js b/assets/js/67.613f77e3.js new file mode 100644 index 000000000..e4558768d --- /dev/null +++ b/assets/js/67.613f77e3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[67],{497:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/68.f73d44cf.js b/assets/js/68.f73d44cf.js new file mode 100644 index 000000000..896abf9ca --- /dev/null +++ b/assets/js/68.f73d44cf.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[68],{499:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/69.a717baf8.js b/assets/js/69.a717baf8.js new file mode 100644 index 000000000..c553f4659 --- /dev/null +++ b/assets/js/69.a717baf8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[69],{498:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/7.5280db48.js b/assets/js/7.5280db48.js new file mode 100644 index 000000000..9c86c9ebb --- /dev/null +++ b/assets/js/7.5280db48.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{427:function(t,s,a){t.exports=a.p+"assets/img/hash.b54950a0.svg"},454:function(t,s,a){"use strict";a.r(s);var n=a(36),p=Object(n.a)({},(function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"map"}},[t._v("map")]),t._v(" "),n("p",[t._v("导读:")]),t._v(" "),n("ul",[n("li",[t._v("map 的基本操作")]),t._v(" "),n("li",[t._v("map 基础知识")]),t._v(" "),n("li",[t._v("map 底层知识")]),t._v(" "),n("li",[t._v("iussues")])]),t._v(" "),n("h2",{attrs:{id:"map-的基本操作"}},[t._v("map 的基本操作")]),t._v(" "),n("p",[t._v("因为 go 使用拉链法去构造 go 语言的 map,所以只要内存不被消耗光,map 中的元素是无限的。跟 slice 不同,map 不分 lenth 和 cap,在 make 中"),n("strong",[t._v("只有")]),t._v("一个位置,这个位置表示的含义就是 cap")]),t._v(" "),n("p",[t._v("map 的基础操作")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 声明一个新的map")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" m "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 给引用类型map分配底层数据结构")]),t._v("\n\tm "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// or m = make(map[string]int,100)")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 插入数据")]),t._v("\n\tm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" ok "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在初始化的时候无法初始化两个一样的key,这个检查是编译器就开始的")]),t._v("\n\tm "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// error")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在初始化的时候无法初始化两个一样的key,但是如果是一个变量的话是可以的,")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 因为编译器时无法获取变量的值的,所以这种方式通过。")]),t._v("\n\tm "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这样是正确的。")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 遍历数据")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" m "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("k"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('":"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 删除数据,不存在这个数据不会panic")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 删除 map 所有条目")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("clear")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("h2",{attrs:{id:"map-基础知识"}},[t._v("map 基础知识")]),t._v(" "),n("p",[t._v("映射的第一步就是把键值转化为哈希值 (通常是一个很大的整数),然后根据哈希值的映射,把 key-value 本体,以及对应的哈希值存储在哈希筒中,go 使用链表法充当哈希筒,当寻找值的时候,通过哈希计算,以及取模映射,先查找到哈希筒,然后使用哈希值的方式去寻找有没有符合的哈希值,如果找到了,那么再使用 key 原来的值二次比较,这一步主要是为了规避哈希碰撞,即:俩 key 算出来的哈希值是一样的这种行为。")]),t._v(" "),n("p",[t._v("因为存 "),n("code",[t._v("==")]),t._v(" 这种行为,所以 go 语言 map 的键值是有局限的,"),n("strong",[t._v("不可以是函数类型、字典类型和切片类型")]),t._v(",如果是接口类型,传入的实际类型也不能是函数,字典和切片,例如")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// panic")]),t._v("\n\t\t"),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[t._v("**虽然,map 的 key 可以设置为接口,但是最好不要这么干,因为会在运行时引入风险,比如上述代码就是风险。同样的,如果 key 是数组类型,亦或者是 struct,参数值都不能是函数,切片和 map。**无论被埋藏的有多深,都不能出现切片,map,函数这几种类型,比如说 "),n("code",[t._v("[10][2][]string")]),t._v(",运行时都会看出来。")]),t._v(" "),n("p",[t._v("那么用什么类型的作为 key 值是比较推荐的呢?")]),t._v(" "),n("p",[t._v("这里有两个关键词:求哈希的速度,判断相等的速度,基本原理是越简单的类型速度越快,比如 bool,int8,就比 int64 快,因为 int8 单个值只占了一个字节,int64 是 8 个字节,所以越复杂的越慢,比如一个 struct,因为求一个 struct 的哈希值,需要对里面的字段都进行哈希计算,然后合并起来,大大影响了速度,所以优先选用数值类型和指针类型 (因为指针类型也就是一个 16 进制的正整数而已),如果选 string,最好短一些的比较好")]),t._v(" "),n("p",[t._v("在内存不爆炸的情况下,map 的 key 是无限量的,随意添加。")]),t._v(" "),n("p",[t._v("map 有一个最佳实践是使用形如 "),n("code",[t._v("value,ok := map[key]")]),t._v(" 的 “comma OK” 的方法去获取 map 的值,OK 的意义就是为了获得 key 是否存在这个 map 里,因为就算不存在,map 也不会报错或者 Panic,返回的是这个值的零值,比如 int 就返回 0,那如果某一个 key 刚好结果是 0 就说不清了对吧,所以引入了这个 “comma ok” 机制,另外还存在一个不存在也不会 Panic 的操作,就是使用 "),n("code",[t._v("delete(map,key)")]),t._v(" 的方法去删除 key 值")]),t._v(" "),n("p",[t._v("map 的遍历跟 slice 一样,使用 m := range map 的方法,但是输出的顺序是不固定的,如果想输出稳定的值,可以将 range 改成普通的 for 循环,然后 key 值使用一个切片存储,这样的话,读取 key 值的时候顺序就是固定的了。")]),t._v(" "),n("h2",{attrs:{id:"map-底层知识"}},[t._v("map 底层知识")]),t._v(" "),n("p",[t._v("当 map 使用字面量的方式进行初始化的时候,数量小于25时,它会首先启用 make 关键字创建一个 map,然后使用 "),n("code",[t._v('m["k"] = v')]),t._v(" 的方式进行初始化,当超过 25 的时候,其实也差不多,它会使用两个切片分别存储 key 和 value,然后使用 "),n("code",[t._v("m[k] = v")]),t._v(" 的方式进行初始化,实际上 go 的复合类型使用字面量进行初始化基本上都是这种方式,基本上的流程就是使用关键字创建底层数据,然后使用最简单的方式进行 k-v 赋值,所以你也可以把字面量的赋值当作一种语法糖。")]),t._v(" "),n("p",[t._v("map 的语法在运行时会转化为另一套对应关系,这个转化是在编译器搞定的。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" m "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("makemap")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maptype"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// maptype 下文有解释")]),t._v("\n\nv "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("mapaccess1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maptype"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// 这里实际上引入的是 "hello"的 指针')]),t._v("\n\nv"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" v"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("ok "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("mapacess2")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maptype"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nm"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" v "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" runtime"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("mapassign")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maptype"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("delete")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" runtiem"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("mapdelete")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("maptype"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("m "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),n("p",[t._v("hmap 是一个 struct,这个结构体拥有众多字段,它用来描述这个 map 底层应用具有的所有字段。可以理解为它是描述 map 的头部文件,存储了所有的字段,但是并不存储真实的 body。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" hmap "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tcount "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" \n\tflags "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v("\n\tB "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" \n\tnoverflow "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint16")]),t._v(" \n\thash0 "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v(" \n\tbuckets unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pointer "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 重点")]),t._v("\n\toldbuckets unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pointer \n\tnevacuate "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v(" \n\textra "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("mapextra \n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" mapextra "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\toverflow "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bmap\n\toldoverflow "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bmap\n\tnextOverflow "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("bmap\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这是一个桶本身的数据结构,但是在运行时阶段会重塑这个结构体,添加更多的字段")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" bmap "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ttophash "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("bucketCnt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这是添加字段以后的样子")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 所以三个数组就完成了数据的存储,也可以避免padding的发生")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" bmap "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n topbits "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v("\n keys "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("keytype\n values "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("valuetype\n pad "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n overflow "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("ul",[n("li",[t._v("count:当前 map 的 value 个数,len 返回的就是这个值")]),t._v(" "),n("li",[t._v("flags:map 的状态标志 iterator oldterator hashwriting samesizegrow")]),t._v(" "),n("li",[t._v("B:"),n("code",[t._v("2 ^ B = 桶数量")])]),t._v(" "),n("li",[t._v("noverflow:指的是 overflow 的桶的数量")]),t._v(" "),n("li",[t._v("hash0:哈希函数的种子值,用作哈希函数的参数,引入随机性")]),t._v(" "),n("li",[t._v("buckets:指向桶数组的指针")]),t._v(" "),n("li",[t._v("oldbuckets:在 map 扩容阶段指向前一个桶的指针")]),t._v(" "),n("li",[t._v("nevacuate:map 扩容阶段充当扩容进度计数器,所有下标号小于 nevacuate 的桶都是已经完成了数据排空和迁移的操作的")]),t._v(" "),n("li",[t._v("extra:【此字段是可选字段】如果有 overflow 的桶出现,该字段保证 overflow 的桶不会被 gc,具体操作就是该字段存储所有指向 overflow 的桶的指针")])]),t._v(" "),n("p",[t._v("当声明一个 map 的时候,运行时就会为这个 map 具体的变量生成一个实例,上门那个是 map 的描述符号,这里说的这个数据结构是定义这个 map 中所有元信息的。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[t._v("\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" maptype "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ttyp _type\n\tkey "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("_type\n\telem "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("_type\n\tbucket "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("_type "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 表示hash bucket 内部的类型")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// function for hashing keys (ptr to key, seed) -> hash")]),t._v("\n\thasher "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Pointer"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uintptr")]),t._v("\n\tkeysize "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// size of key slot")]),t._v("\n\telemsize "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint8")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// size of elem slot")]),t._v("\n\tbucketsize "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint16")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// size of bucket")]),t._v("\n\tflags "),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("uint32")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),n("p",[t._v("go 的 map 只有一套 method,只要使用这个 maptype 的具体不同实现就可以满足操作。比如 map[int]int 和 map[int]string,他们都使用 maptype 来定义自己的元信息,但是操作这这个元信息的函数是一个,只要取不同的 typ key 这种指针类型取操作就可以了。")]),t._v(" "),n("p",[t._v("存储数据的 body 本体是由一个 "),n("code",[t._v("类似二维数组")]),t._v(" + "),n("code",[t._v("链表")]),t._v(" 组成的,具体的图像如下:")]),t._v(" "),n("p",[n("img",{attrs:{src:a(427),alt:""}})]),t._v(" "),n("p",[t._v("tophash 区域就是为了寻找 key 和 value 使用空间换时间的原理做的索引,当我们把 hashcode 的高位值逐一比较的时候就可以确定 key 和 value 的位置。")]),t._v(" "),n("p",[t._v("key 和 value 都是连续的内存区域,key 和 value 在一个桶中只能存在 8 个,多余的在不满足扩容的情况下就会存储在溢出桶中,寻找 key 和 value 使用 tophash 的位置即可,go 使用分开存储 tophash,key,value 的方式,所以 go 就避免了数据 padding,满足了内存对齐,避免了内存的浪费。需要注意的是,当 key 和 value 大于 128 个字节的时候,存储的就是他们的指针")]),t._v(" "),n("p",[t._v("map 的扩容有一个具体的衡量指标,负载因子,当 hmap 中的 "),n("code",[t._v("count > 负载因子 * 2^B")]),t._v(" (map 的负载因子为 6.5),或者溢出桶过多的时候,就会扩容。当因为溢出桶太多的时候,创建的新 map 的桶和现有的桶一样,当因为不满足负载因子导致的扩容时,会创建两倍于现有 bucket 的新 bucket,但是旧的桶 data 并不会立刻被迁移到新的 bucket 中,在 map 进行插入和删除的过程中旧的内容会被逐步迁移到新的桶中。原来旧的内容就会被 gc 掉。")]),t._v(" "),n("p",[t._v("普通 map 的扩容并不是原子性的,所以 map 的扩容过程会去检查是否已经处于扩容中。")]),t._v(" "),n("p",[t._v("当持续向 map 中写入数据,并且删除,然后继续写入删除,这个时候如果没有造成装载因子的超出,就会造成溢出桶过多的情况,这个时候就会造成内存的泄漏,所以会创建一个一样大的 map,存储没有被删除的数据,并且将那些被标记为 delete 的数据进行垃圾回收,没错,你进行 delete 的时候并没有真的 delete,只有 gc 以后才是真的 delete。")]),t._v(" "),n("p",[t._v("将旧的数据放在 runtime.hmap 中的 oldbuckets 字段上,然后将新的数据结构放在 buckets 上,溢出桶的设置也是一样的,因为 extra 指向的数据结构也是三个字段,老的,新的,正在使用的。")]),t._v(" "),n("p",[t._v("运行时会将一个旧桶的数据分流到两个新的桶子里,但是如果是内存泄漏的等量扩容时,就只会把一个旧桶的数据导入到一个新的桶子里,请注意这里的迁移指的是拷贝,在计数器计算数据已经被分流完全以后,旧的桶和旧的溢出桶的数据就会被 gc 掉")]),t._v(" "),n("p",[t._v("因为存在旧桶和新桶,所以在查找数据的时候,会先从旧桶查找数据,如果没有再去新的桶中查找,当我们写入和删除数据的时候,除了写入的新数据到新的桶中,也会把旧的桶中的一部分数据拷贝到新的桶中,当然了不会拷贝全部,这是为了效率考虑的,")]),t._v(" "),n("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),n("p",[n("code",[t._v("问题一:")]),t._v(" "),n("strong",[t._v("map 元素可以取地址吗?")])]),t._v(" "),n("p",[n("RouterLink",{attrs:{to:"/基础/其他内容/#go可寻址类型"}},[t._v("不能")]),t._v(",map 元素 (例如 ma [“12”]) 属于结果值,所以无法获取地址")],1),t._v(" "),n("p",[n("code",[t._v("问题二:")]),t._v(" "),n("strong",[t._v("map 可以并发读写吗?可以 recover 吗?")])]),t._v(" "),n("p",[t._v("map 是线程不安全类型,读写得加互斥锁;被 recover 的 Panic 有几项是不能的:")]),t._v(" "),n("ul",[n("li",[t._v("数据竞争 (比如:"),n("strong",[t._v("对 map 进行并发读写")]),t._v(")")])]),t._v(" "),n("blockquote",[n("p",[t._v("可以通过 go 的编译标记 race 对代码进行检测是否存在数据竞争")])]),t._v(" "),n("ul",[n("li",[t._v("内存不足出现的 Panic")]),t._v(" "),n("li",[t._v("死锁出现的 Panic")])]),t._v(" "),n("p",[n("code",[t._v("问题三:")]),t._v(" "),n("strong",[t._v("sync.Map 适合的场景,和 map 加锁的区别")])]),t._v(" "),n("p",[t._v("sync.Map 在读多写少性能比较好,否则并发性能很差")]),t._v(" "),n("blockquote",[n("p",[t._v("有关 sync.Map 的"),n("RouterLink",{attrs:{to:"/工程/go标准库/sync.html#syncmap"}},[t._v("详细内容")])],1)]),t._v(" "),n("p",[t._v("map 不支持并发的读或者是写 (go1.6 以后就不支持并发的读和写了,之前的版本支持并发的读,但是不支持并发的写),所以 map+锁性能在读多写少和读少写多,读和写一样多的情况下是一样的。")]),t._v(" "),n("p",[t._v("最优解是使用多把锁即:分段锁的方式,并发读写,大幅提高性能")]),t._v(" "),n("p",[n("code",[t._v("问题四:")]),t._v(" "),n("strong",[t._v("在值为 nil 的字典上执行读操作会成功吗,那写操作呢?")])]),t._v(" "),n("p",[t._v("答案是在值为 nil 的字典写会 Panic,读是没问题的。")]),t._v(" "),n("div",{staticClass:"language-go extra-class"},[n("pre",{pre:!0,attrs:{class:"language-go"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tfmt"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 结果是int的一个初始值 0 ")]),t._v("\n a"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// panic")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),n("p",[n("code",[t._v("问题五:")]),t._v(" "),n("strong",[t._v("为什么不用向下寻址式?")])]),t._v(" "),n("p",[t._v("我们知道解决哈希碰撞的问题有向下寻址法,链表法,这是因为哈希函数只能把数据尽可能分布的均匀,如果哈希函数的输出的范围大于输入的范围,这是不现实的,这就要求映射无穷多,这显然不可能,所以必然会有两个不同的 key 算出来的哈希值是相同的,那么如果很多 key 算出的哈希值都是一样的,这就出现了查找效率从 O(1) 下降到了 O(n) 这就是所谓的哈希冲突。")]),t._v(" "),n("blockquote",[n("p",[t._v("这里提到的哈希值一样,有可能是后几位一样,也就是部分一样,比如后 9 位相同")])]),t._v(" "),n("p",[t._v("向下寻址法的意思是:依次向下一位去探究是否是要找的哈希对,当然插入的时候也是这,向没有数据的地方插入,所以这种方法必须要使用数组这种结构,而且遍历的时候还得使用循环数组的这种思想 "),n("code",[t._v('index := hash("author") % array.len')]),t._v(",开放寻址法有一个数据指标叫做装载因子,就是说元素的个数/数组长度,一旦装载因子大于 70 %乃至 90 % 基本上就倒退为了 O(n) 的时间复杂度,并且底层是数组的情况下,必须使用连续的内存地址,并且数组长度是有限的,并且大概率会发生内存 padding 的情况,因为 kv 要存储在一起,这就又造成了更大的浪费。")]),t._v(" "),n("p",[t._v("总结一下:不使用向下寻址使用拉链法的原因在于,1 可以利用碎片式的内存,2 不用内存 padding 造成浪费 3 原则上链表长度无限,可以无限增加。")]),t._v(" "),n("p",[n("code",[t._v("问题六:")]),t._v(" "),n("strong",[t._v("map 如何操作真缩容?")])]),t._v(" "),n("p",[t._v("可以使用 cap 重新生成一个 map,然后使用遍历的方式将老的 map 数据导入到新的小的 map 中,如果你知道数据不会再次增大的情况下是可以这么做的。")]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://github.com/golang/go/")]),t._v(" "),n("li",[t._v("https://blog.csdn.net/EDDYCJY/article/details/120465701")])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/70.b3476fa3.js b/assets/js/70.b3476fa3.js new file mode 100644 index 000000000..60883d6d4 --- /dev/null +++ b/assets/js/70.b3476fa3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[70],{501:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/71.57746954.js b/assets/js/71.57746954.js new file mode 100644 index 000000000..8fd31c998 --- /dev/null +++ b/assets/js/71.57746954.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[71],{500:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/72.4cc3186e.js b/assets/js/72.4cc3186e.js new file mode 100644 index 000000000..cf1e3cfb4 --- /dev/null +++ b/assets/js/72.4cc3186e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[72],{502:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/73.03d8974c.js b/assets/js/73.03d8974c.js new file mode 100644 index 000000000..4499567a5 --- /dev/null +++ b/assets/js/73.03d8974c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[73],{503:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/74.4f1eeb3c.js b/assets/js/74.4f1eeb3c.js new file mode 100644 index 000000000..53bfe8f31 --- /dev/null +++ b/assets/js/74.4f1eeb3c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[74],{504:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/75.d44fc2e7.js b/assets/js/75.d44fc2e7.js new file mode 100644 index 000000000..c2ec40c16 --- /dev/null +++ b/assets/js/75.d44fc2e7.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[75],{505:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/76.f53bf284.js b/assets/js/76.f53bf284.js new file mode 100644 index 000000000..3f76b7fb7 --- /dev/null +++ b/assets/js/76.f53bf284.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[76],{506:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/77.bad2588a.js b/assets/js/77.bad2588a.js new file mode 100644 index 000000000..2e10c97ea --- /dev/null +++ b/assets/js/77.bad2588a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[77],{507:function(t,e,o){"use strict";o.r(e);var s=o(36),i=Object(s.a)({},(function(){var t=this,e=t.$createElement,o=t._self._c||e;return o("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[o("h1",{attrs:{id:"go-语言规范"}},[t._v("go 语言规范")]),t._v(" "),o("p",[t._v("总结了 go,google 官方以及腾讯的 go 语言规范。")]),t._v(" "),o("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),o("ul",[o("li",[t._v("https://go.dev/ref/spec")]),t._v(" "),o("li",[t._v("https://github.com/Tencent/secguide/blob/main/Go%E5%AE%89%E5%85%A8%E6%8C%87%E5%8D%97.md")]),t._v(" "),o("li",[t._v("https://google.github.io/styleguide/go/best-practices")]),t._v(" "),o("li",[t._v("https://colobu.com/2023/11/17/golang-quick-reference-top-20-best-coding-practices/")])])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/78.2ee31447.js b/assets/js/78.2ee31447.js new file mode 100644 index 000000000..04b0bc024 --- /dev/null +++ b/assets/js/78.2ee31447.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[78],{508:function(t,o,r){"use strict";r.r(o);var e=r(36),i=Object(e.a)({},(function(){var t=this,o=t.$createElement,r=t._self._c||o;return r("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[r("h1",{attrs:{id:"go-面试题"}},[t._v("go 面试题")]),t._v(" "),r("ul",[r("li",[r("RouterLink",{attrs:{to:"/工程/go面试题/中高级go面试题一.html"}},[t._v("中高级 go 面试题一")])],1)]),t._v(" "),r("h2",{attrs:{id:"按照公司排序"}},[t._v("按照公司排序")]),t._v(" "),r("h2",{attrs:{id:"最终总结出的面试题"}},[t._v("最终总结出的面试题")]),t._v(" "),r("ul",[r("li",[r("RouterLink",{attrs:{to:"/工程/go面试题/primary.html"}},[t._v("初级")])],1),t._v(" "),r("li",[r("RouterLink",{attrs:{to:"/工程/go面试题/intermediate.html"}},[t._v("中级")])],1),t._v(" "),r("li",[r("RouterLink",{attrs:{to:"/工程/go面试题/senior.html"}},[t._v("高级")])],1),t._v(" "),r("li",[r("RouterLink",{attrs:{to:"/工程/go面试题/architect.html"}},[t._v("架构师")])],1)])])}),[],!1,null,null,null);o.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/79.f5c3f20d.js b/assets/js/79.f5c3f20d.js new file mode 100644 index 000000000..015de86df --- /dev/null +++ b/assets/js/79.f5c3f20d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[79],{509:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/8.ff976029.js b/assets/js/8.ff976029.js new file mode 100644 index 000000000..6cd915207 --- /dev/null +++ b/assets/js/8.ff976029.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[8],{428:function(t,s,n){t.exports=n.p+"assets/img/gofunc.32e2f0aa.svg"},466:function(t,s,n){"use strict";n.r(s);var a=n(36),p=Object(a.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"函数和方法"}},[t._v("函数和方法")]),t._v(" "),a("p",[t._v("重点内容前情提要")]),t._v(" "),a("ul",[a("li",[t._v("函数初始化的顺序")]),t._v(" "),a("li",[t._v("init 函数")]),t._v(" "),a("li",[t._v("defer 的运用")]),t._v(" "),a("li",[t._v("变长参数")]),t._v(" "),a("li",[t._v("类型嵌入来完成继承")]),t._v(" "),a("li",[t._v("define 类型的方法集合")]),t._v(" "),a("li",[t._v("类型别名的方法集合")]),t._v(" "),a("li",[t._v("函数式编程")])]),t._v(" "),a("p",[t._v("go 语言中函数的基本使用方法如下:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数的一般用法, go 拥有多个返回值")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 返回值具有变量的返回模式")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Post")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数作为value值赋值给一个变量变量")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" Get0 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"函数的初始化顺序"}},[t._v("函数的初始化顺序")]),t._v(" "),a("p",[a("img",{attrs:{src:n(428),alt:""}})]),t._v(" "),a("ul",[a("li",[t._v("main 函数是所有 go 可执行函数的起始位置")]),t._v(" "),a("li",[t._v("在 main 函数运行前,需要先运行导入子包的流程")]),t._v(" "),a("li",[t._v("在导包的过程中,最先运行的是最深层的子包")]),t._v(" "),a("li",[t._v("按照"),a("strong",[t._v("全局常量,全局变量,init 函数")]),t._v("的顺序进行初始化的操作")]),t._v(" "),a("li",[t._v("子包初始化之后,开始返回前一层的包中进行常量,全局变量,init 函数的初始化,图示流程非常清晰的画出了这个过程。")]),t._v(" "),a("li",[t._v("多个相同的包只会导入一次,并且取相同包不同版本的可满足的最小版本导入,例如 "),a("code",[t._v("v1.1.0 v1.2.0")]),t._v(",只导入 "),a("code",[t._v("v1.2.0")]),t._v(",不会默认导入最新的版本。")])]),t._v(" "),a("h2",{attrs:{id:"init-函数"}},[t._v("init 函数")]),t._v(" "),a("p",[t._v("在一个包中,以及在一个包的某个文件中,可以存在多个 init 函数,一般来说,同一个包的不同 file,按照文件字符串比较的 “从小到大” 的顺序先被编译 file 中的 init 先执行,同一个 file 中的 init 函数按照先后顺序执行,但是 go 语言规范告诉我们,不要依赖 init 的执行顺序。")]),t._v(" "),a("p",[t._v("init 函数无法主动执行,它的执行是系统自动执行的,所以显式的去调用 init 函数会发生报错。")]),t._v(" "),a("p",[t._v("通常来说,init 的目的就是系统的初始化,因为它一定会被执行,下面我们介绍一下 init 函数的几个用途。")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("重置包级变量值。")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// src/context/context.go")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" closedchan "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("closedchan"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们的包级变量是一个 chan,并且需要它是一个已经关闭的 chan,我们使用 init 来确保它提前一定处于一个已关闭的状态。")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("对包级变量进行初始化,保证其后续可用。")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n OutBox "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n InBox "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n OutBox "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n InBox "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("init 函数中的注册模式。")])])]),t._v(" "),a("p",[t._v("这种模式在 go 中有两处经典的案例,其一是 "),a("code",[t._v("database/sql")]),t._v(" 包的使用,其二是 image 包的使用。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// databsae/sql 包的使用")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"database/sql"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/lib/pq"')]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n db"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" sql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"postgres"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这里使用 "),a("code",[t._v("import _")]),t._v(" 就是只有导包的过程,并没有任何除了 init 函数之外的函数调用。那么这么做的原因是什么呢?")]),t._v(" "),a("p",[a("code",[t._v("工厂方法 + 导包的顺序")])]),t._v(" "),a("p",[t._v("下面我们看一下这两个包的源码")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// github.com/golnag/go/src/database/sql/sql.go")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" drivers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("driverName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" dataSourceName "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("DB"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tdriveri"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" drivers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("driverName"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" driver driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tdrivers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" driver\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("ul",[a("li",[t._v("sql 包有一个全局的 map,这里存放了所有的 driver,这个 map 的 key 是 driver 的名字,value 是 driver.Driver 的接口类型,通常来说存入的都是实现了这个接口的动态类型。")]),t._v(" "),a("li",[t._v("open 函数会直接判断是否拥有含有这个 key 的 value 值")]),t._v(" "),a("li",[t._v("register 函数,也就是注册函数,这个函数通常由实现了 sql.driver 的数据库第三方库的 init 函数去进行最终的注册。")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// github.com/lib/pq")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tsql"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"postgres"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("ul",[a("li",[t._v("这里就是实现了 sql.Driver 的 pq.Driver 结构体进行了名为 “postgress” 的注册。")])]),t._v(" "),a("p",[t._v("下面我们进行整体的分析:")]),t._v(" "),a("ul",[a("li",[t._v("在 pq 包实现的时候,它引入了 “database/sql”,“database/sql/driver” 这两个包,它将实现的数据库实例注册到 sql 的 map 中")]),t._v(" "),a("li",[t._v("用户调用的时候,我们调用了 "),a("code",[t._v("sql.Open")]),t._v(" 使用不同的 name 就可以使用不同的数据库,这里是工厂方法设计模式的运用")])]),t._v(" "),a("p",[t._v("这种方法可以使 pq 这个包完全没有暴露到用户面前,仅需要使用 sql 包就可以间接的使用 pq 的代码,很好的做了隔绝。")]),t._v(" "),a("p",[t._v("下面看一下 image 包的运用。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image/png"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image/gif"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image/jpeg"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"os"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n width"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("height"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("image")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Args"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("width"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" height"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("image")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n img"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" image"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Decode")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" img"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Bounds")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Max"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("X"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Max"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Y"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们发现,image.Decode(f) 应该就如同上文提到的 Open 函数一样的功能,也就是工厂方法中的工厂。")]),t._v(" "),a("p",[t._v("下面我们看一下 image/gif 包中的 init 函数:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//https://github.com/golang/go/blob/master/src/image/gif/reader.go")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\timage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("RegisterFormat")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"gif"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"GIF8?a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" Decode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" DecodeConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("可以看到,这个 gif 包也是调用了 image 包,并且通过 init 函数,将动态类型注册到了 image 提供的注册器中。")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("init 函数中检查失败的处理方法。")])])]),t._v(" "),a("p",[t._v("使用 init 去检查某些数据的正确性,相当于做最后的质检工作,一旦发生了错误,直接使用 Panic,快速停掉程序。")]),t._v(" "),a("h2",{attrs:{id:"defer-函数"}},[t._v("defer 函数")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test.txt"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 此处就是 defer 函数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("defer 函数有下面几个规则")]),t._v(" "),a("ul",[a("li",[t._v("defer 后面只能跟函数或者是方法")]),t._v(" "),a("li",[t._v("一个函数中的 defer 函数,会使用 “栈” 的方式运行")]),t._v(" "),a("li",[t._v("defer 后面的函数和方法,返回值会被直接舍弃")])]),t._v(" "),a("p",[t._v("下面看一下 defer 函数的几种用法")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("配合 recover 函数处理 panic")])])]),t._v(" "),a("p",[t._v("在 go 里,如果要处理函数内的 panic,有且仅有一种方法,那就是使用 recover 函数。而且 recover 函数必须运行在 defer 之中。那么让我们看一下具体的代码实现")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("recover")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"recoverd"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"panic"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("修改函数的具名返回值")])])]),t._v(" "),a("p",[t._v("具名返回值,就是返回值带有变量的,比如:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("y "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("b\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("b\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// hi(1,3) 返回值为 (5,-1)")]),t._v("\n")])])]),a("p",[t._v("在分析这段代码的时候,我们要牢记一句话,在具名返回值的函数中,go 的 return 并不会立刻 return,它会等待 defer 执行完毕后再真的 return。也就是说,它 return 的是 x y 的最后时刻。")]),t._v(" "),a("p",[t._v("那么,让我们看一下非具名的函数:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" \n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("y "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"defer 会执行的"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("b\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("b\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" y\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// hi(1,3) ")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// output:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// defer 会执行的 5 -1")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 4 -2")]),t._v("\n")])])]),a("p",[t._v("在非具名的函数中,return x,y 的时候就已经决定返回值的最终结果了,但是这个 defer 还是会执行,这个是真的,xy 的值确实也是在 defer 里改变了,但是 return 的是之前的中间量,defer 里面的 xy,并不会左右之前已经设定好的 x y 的复制值了。")]),t._v(" "),a("p",[t._v("所以输出的是 4 -2,而且 defer 里面的输出 “defer 会执行的 5 -1” 也执行了。")]),t._v(" "),a("p",[t._v("defer 函数虽然是先入后出,在所有的正式指令执行完成以后执行,但是它的变量初始化可是***顺序的***,这里强调一下,仅仅是变量的初始化是顺序执行,defer 函数是不会顺序执行的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" y "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tj "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// j 顺序的初始化数据了,")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// println却不会顺序执行!")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tj"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// output: 0")]),t._v("\n")])])]),a("p",[t._v("这里的 defer 顺序执行完变量的初始化,所以它里面的 j 变量完成了值的复制,为 0,那么下文的 j++ 就不会对上面的复制品起任何作用了,即便 prinln(j) 确实发生在 j++ 之后,总结一句话,defer 函数执行是最后,但是初始化是正常的先后顺序。")]),t._v(" "),a("p",[t._v("如果想得到 1 的答案,可以这么改:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" y "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tj "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("j"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tj"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这里的 j "),a("strong",[t._v("就会")]),t._v("受到下面 j++的影响了。")]),t._v(" "),a("p",[t._v("还有一点要注意,defer 函数的作用域也是正常的作用域,也就是说,上文 hi 函数演示内容,j:= 0 必须声明在 defer 函数之前,虽然我们知道 defer 的内容最后执行,但是它也遵循正常的作用域。如果 j := 0 发生在 defer 之后,它就会无法找到这个变量。")]),t._v(" "),a("p",[t._v("看了上面那么多容易搞混的 defer 用法,这里要说明一下,正常的使用方法是这样的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("hi")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("y "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("b\n y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("b\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("也就是我们第一种使用的惯例,它的效果就是最后改变返回值,这也是这几种方式中最常用的方式。")]),t._v(" "),a("p",[t._v("看了上文关于 defer 函数的初始化 int 类型参数以后,我们还得注意切片在 defer 函数初始化参数的问题,因为它更容易出现误判。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("s1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("ul",[a("li",[t._v("前者输出 1 2 3")]),t._v(" "),a("li",[t._v("后者输出 4 5 6")])]),t._v(" "),a("p",[t._v("我们分析一下:")]),t._v(" "),a("blockquote",[a("p",[a("strong",[t._v("❗️ 这个地方很容易搞错,望周知。")])])]),t._v(" "),a("p",[t._v("首先我们确定的一件事就是:"),a("strong",[t._v("defer 函数的参数初始化是顺序执行的")]),t._v(",它顺序执行之后,将数据保存在了一个专用的栈中。")]),t._v(" "),a("p",[t._v("所以,第一个函数中,v 就等于 []int {1,2,3},换言之,v 初始化的时候等于一个指向底层数据是 1 2 3 的数组,所以当 s1 重新指向一个新的数据 4 5 6 的时候,v 的数据并不会有任何的影响,它仍然执行的还是底层数据是 1 2 3 的数组,所以它的最终结果就是输出 1 2 3")]),t._v(" "),a("p",[t._v("第二个函数,在初始化阶段,v 正常的初始化,它的值是 s1 的地址,那么当下文中 s1 重新指向了一个新的底层数组为 4 5 6 的数据之后,v 的数据是一直跟着 s1 走的,因为它的本质是 s1 的地址,这把钥匙一直都没有变化,所以它的最终结果就是新的内容 4 5 6")]),t._v(" "),a("p",[t._v("最后提一嘴,defer 函数的性能消耗 (go 1.14+),跟不使用 defer 相比,几乎没有差距,所以放心大胆的使用 defer。")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("输出调试信息")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("trace")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"prepare"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" s\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("un")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"out"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("un")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("trace")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"in a"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("b")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("un")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("trace")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"b"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"in b"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("b")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prepare b")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// in b")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// prepare a")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// in a")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// out a")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// out b ")]),t._v("\n")])])]),a("p",[t._v("这是 go 文档提供的一个日志记录的例子,接下来我们分析一下")]),t._v(" "),a("ul",[a("li",[t._v("首先 b 的执行,b 中的 defer 函数 un 开始初始化,它的初始化就是执行 trace (“b”),所以最先执行的是 prepare b")]),t._v(" "),a("li",[t._v("然后开始执行 println (“in b”)")]),t._v(" "),a("li",[t._v("接下来执行 a,跟 b 一样,先执行初始化的 un 中的 trace (“a”) 函数,然后执行 println (“in a”)")]),t._v(" "),a("li",[t._v("然后开始执行 a 的 defer 函数,所以 a 的 out 先执行,(因为它后入,先出)")]),t._v(" "),a("li",[t._v("接下来最后执行的是 b 中的 defer,那么就是 out b")])]),t._v(" "),a("p",[a("em",[a("strong",[t._v("还原变量的旧值")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n oldfile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" firstfile\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n firstfile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" oldfile\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n firstfile "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"README.md"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//...")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("我们知道,defer 后面只能放置函数,包括自匿名函数,或者是自定义的函数以及方法 (如果有返回值自动舍弃),那么 go 内置的函数是否可以放到 defer 后面执行呢?")])])]),t._v(" "),a("p",[t._v("答案是,部分内置函数可以直接放到 defer 后面,部分不能直接放到 defer 后面执行,需要放到一个匿名或者自定义函数中。")]),t._v(" "),a("ul",[a("li",[t._v("可以直接放到 defer 后面的函数有:close copy delete print recover")]),t._v(" "),a("li",[a("strong",[t._v("不能")]),t._v("直接放到 defer 后面的函数有:append cap len make new")])]),t._v(" "),a("p",[t._v("但是通常来说,我们使用 defer 的时候都是会跟一个匿名函数或者是自定义的函数,并不会直接跟一个内置函数。")]),t._v(" "),a("p",[t._v("比如直接跟匿名函数的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("recover")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"error"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("跟一个自定义函数的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"README.md"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n \n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// defer 后面是一个方法,并且舍弃了这个方法的error参数")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"defer-函数因为无法-return-造成的内存泄露-bug"}},[t._v("defer 函数因为无法 return 造成的内存泄露 bug")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readFiles")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" path "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" ch "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfile"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Do something with file")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("在这个案例中,defer 函数用于关闭一个文件的句柄,假设我们在读取文件的过程中发生了 bug,readFile 永远无法 return nil,那么这个 defer 函数就永远不会实行,就会造成内存的泄露。")]),t._v(" "),a("p",[t._v("改正的话,我们可以给 defer 函数 wrap 一层函数,在这个子函数中只要能 return,运行 defer 函数即可")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readFiles")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ch "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<-")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("chan")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" path "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" ch "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 我们设置了一个新的函数,只要在这个函数里可以正常return 即可")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("readFile")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfile"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" file"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Close")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Do something with file")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h3",{attrs:{id:"再次强调-有无返回值具体变量对于-defer-的影响"}},[t._v("再次强调:有无返回值具体变量对于 defer 的影响")]),t._v(" "),a("p",[t._v("有返回变量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 13")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 12")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//13")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("执行顺序是这样的:\n1。i 初始化为原始数据 0\n2。i++\n3。i+= 10\n4。i++\n5。fmt.Println(i+1) // 13\n6。return 这个时候最终的 i // 12")]),t._v(" "),a("p",[t._v("所以当拥有返回值变量的时候,return 返回的是最终的 i,就连 defer 中的 i 的变量也算上。")]),t._v(" "),a("p",[t._v("无返回变量")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 11")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//3")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("执行的顺序:\n1。i 初始化为 0\n2。i++\n3。执行 i + 10 并把这个数据记录到 return 上去,但是并不会真的 return\n4。i++\n5。fmt.Println(i+1)// 3\n6。defer 执行完毕以后,return 开始返回之前记录的那个值。")]),t._v(" "),a("p",[t._v("为什么在这个没有返回变量的时候,i 在 defer 中的变化不会影响返回值呢,因为返回值记录的那个值发生在 defer 之前,所以 defer 再将 i 变化也不会影响之前记录的那个值了,那个值是已经固定的了,它没有立即返回是因为要执行 defer,你也可以理解为")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("a")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//3")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" a\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("所以 a 的值是不会再受到 defer 中的 i 的变化的。")]),t._v(" "),a("h2",{attrs:{id:"变长参数"}},[t._v("变长参数")]),t._v(" "),a("p",[t._v("举个变长参数函数的例子:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fprintln")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Stdout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们平时使用的 "),a("code",[t._v("fmt.Println(...any)")]),t._v(" 就是标准的变长参数的例子。")]),t._v(" "),a("p",[t._v("它的组织形式就是 "),a("code",[t._v("...")]),t._v(" + "),a("code",[t._v("类型")]),t._v(",比如 "),a("code",[t._v("...int")]),t._v(" "),a("code",[t._v("...string")])]),t._v(" "),a("ol",[a("li",[t._v("一个函数的参数中只能有一个变长参数,且必须为最后一位")]),t._v(" "),a("li",[t._v("变长参数在函数内部以 slice 的方式存在")]),t._v(" "),a("li",[t._v("变长参数只能接受两种形式的值,其一就是多个同样类型的值,例如 "),a("code",[t._v('fmt.Println("hi","there",12)')]),t._v(",或者直接接受一个 "),a("code",[t._v("slice...")]),t._v(",例如 "),a("code",[t._v('fmt.Println([]any{1, 2, "hi"}...)')]),t._v(",并且,这两种用法不能混用,比如 "),a("code",[t._v("fmt.Println(1,2,[]any{1,2}...)")]),t._v(" 这种混写的方法错误。")])]),t._v(" "),a("p",[t._v("any 类型和 string 类型是绝对的不同的两种类型,因为 any 是 interface {} 的别名 ("),a("code",[t._v("type any = interface{}")]),t._v("),string 类型虽然实现了空接口,但是它不是空接口类型,如果要转换成空接口,必须显式的转换:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("any")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("go 语言在 append 字符串到[]byte 的时候提供了一个语法糖")])])]),t._v(" "),a("p",[a("code",[t._v("func append(slice []Type, elems ...Type) []Type")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ee"')]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" b"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这种语法糖只适用于 append 内置函数。底层应该是帮你把字符串转化为了 "),a("code",[t._v("[]byte()")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 类似这种转换")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ee"')]),t._v("\n\tc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("append")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("如果自己实现一个的时候不进行转换就会报错。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("byte")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"123"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v('//cannot use "123" (untyped string constant)')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// as []byte value in argument to get")]),t._v("\n\n")])])]),a("h3",{attrs:{id:"使用变长函数去模拟重载函数"}},[t._v("使用变长函数去模拟重载函数")]),t._v(" "),a("p",[t._v("重载函数就是同一个作用域下,可以有相同名称的函数,只不过他们的参数不同,go 语言是不支持这种类型的函数的。")]),t._v(" "),a("p",[t._v("类似这种")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("如果真的想使用这种重载函数,我们可以使用这种方法来间接实现:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" args "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int16")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("vi"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("h3",{attrs:{id:"使用变长函数去实现默认参数"}},[t._v("使用变长函数去实现默认参数")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("CheckIn")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"shgopher"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"男"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("CheckIn")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"jackie"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"男"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"上海"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Contents "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tName "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tAge "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\tSex "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\tAddress "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("CheckIn")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("arges "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("any"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Contents"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tc "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Contents"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tAddress"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Beijing "')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" k"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" arges "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("switch")]),t._v(" k "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tname"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"name is not a string"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\tc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tage"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"age is not a int"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\tc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Age "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" age\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\tsex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sex is not a string"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\tc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Sex "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" sex\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("case")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\taddress"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"address is not a string"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t\t\tc"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" address\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("default")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("\n\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Errorf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"unknown argument"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这段代码的意思就是先给定一个默认值,比如这里地址是默认值的,也即是它是可选的内容,鉴于这段代码标识的意义,这个可省略的一定是在最后一位的。")]),t._v(" "),a("h1",{attrs:{id:"方法"}},[t._v("方法")]),t._v(" "),a("p",[t._v("接下来,我们介绍方法,所谓方法,其实只是函数的一种语法糖,它跟函数并没有本质的区别,我们看一个简单的例子:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("可以看到,这是一个定义在指针类型 "),a("code",[t._v("*student")]),t._v(" 上的方法 "),a("code",[t._v("GetName")]),t._v(",实际上,它完全等于函数的这种形态:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("go 语言本身对于方法的使用是很宽泛的:")]),t._v(" "),a("ul",[a("li",[t._v("指针类型的变量可以使用值类型的方法")]),t._v(" "),a("li",[t._v("值类型的变量可以使用指针类型的方法")])]),t._v(" "),a("p",[t._v("这跟后文要讲的接口绝对是差距极大,因为接口的要求非常严格,这个可以看接口和函数的对比。")]),t._v(" "),a("p",[t._v("值类型的变量可以使用指针类型的方法")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"张三"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当值类型来使用指针类型的方法时,系统默认会调用这个值的指针,因此这是系统给予的语法糖。")]),t._v(" "),a("p",[t._v("指针类型的变量可以使用值类型的方法")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" name\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("GetName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"张三"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"out:"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//out:")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当指针类型来使用值类型的方法时,系统默认会调用这个指针指向的值,因此这是系统给予的语法糖。")]),t._v(" "),a("p",[t._v("这个例子其实是错误的行为,因为 s 的方法是定义在值类型的,使用一个 s 去调用它上面的 GetName,改变的只是方法中,s 的***复制品上***的值,外部调用的这个 s,实际上是不会有任何的改变的,我们如果从实质出发 "),a("code",[t._v("func GetName(s Student, name string)")]),t._v(",就能看出来了。")]),t._v(" "),a("p",[t._v("跟函数以及全局变量,常量是一样的,方法也是首字母大写可以导出包,小写无法导出包。")]),t._v(" "),a("p",[t._v("这里有个细节要注意一下,不能跨越包去定义方法,go 语言不支持,比如,原生类型 "),a("code",[t._v("(int,map,slice,bool 等)")]),t._v(" 是无法提供方法的,例如")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("所以通常来说,我们就定义一个底层为 int 的新类型才可以")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("那么我们总结一下关于方法的几个小细节:")]),t._v(" "),a("ul",[a("li",[t._v("方法首字母的大小写注定了是否可以导出包")]),t._v(" "),a("li",[t._v("不能跨越包去定义方法")]),t._v(" "),a("li",[t._v("每一个方法只能被一个类型去定义,不能俩类型去定义一个方法")]),t._v(" "),a("li",[a("em",[a("strong",[t._v("指针类型和接口类型不能作为方法的基底类型")])])])]),t._v(" "),a("p",[t._v("最后一条,我们详细展开一下:")]),t._v(" "),a("p",[t._v("以下定义是错误的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌ 指针类型不能有自己的方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ✅ 类型的指针可以有自己的方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌ 接口类型不能有自己的方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// ❌ 以接口为基底的类型不能有自己的方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A xxInterface\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a A"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("h2",{attrs:{id:"类型嵌入来完成继承"}},[t._v("类型嵌入来完成继承")]),t._v(" "),a("p",[t._v("go 语言使用类型的嵌入来实现继承母体的对象以及对象上的方法。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("People"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("现在我们将类型嵌入到一个新的类型来实现继承:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People\n address "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们还可以重写继承的方法来完成重载操作:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("People"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"学生"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当发生嵌入类型和本类型,字段重合的时候,优先调用本类型的字段,嵌入类型的只需要加上前缀就可以了。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("People"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("如果你不想直接嵌入,也可以在前面加上变量名称:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 不嵌入也可以")]),t._v("\n people People\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("不过,如果是不嵌入的方式,就无法直接调用方法了,需要加上前缀。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("people"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("内置类型也可以作为字段直接嵌入到新类型中")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("不过使用的时候比较非常规了:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a\n a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v("\n a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2"')]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("指针类型也可以直接嵌入:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("b\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('""')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\tb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("b"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们可以看到,直接嵌入的时候,其实是省略了写法。但是通常,int string,这种内置的类型我们都会指定一个变量给他们。例如常规写法:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n year "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("b\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("无论嵌入的是值类型还是指针类型,函数都可以直接调用他们身上的方法:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" People "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("People"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("p"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Address "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n value "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Value")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n fmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People\n "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Address\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//由于这里的address字段是指针,所以我们必须给address赋予实际的值的地址:")]),t._v("\n s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Value")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("s 是指针类型和值类型在调用实质上还是区别的,但是在实际使用中,并不会有什么区别,这主要还是因为要看方法是定义在值类型还是指针类型上。")]),t._v(" "),a("p",[t._v("值类型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Value")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//由于这里的address字段是指针,所以我们必须给address赋予实际的值的地址:")]),t._v("\n s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Value")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("当 s 是值时,它调用的就是 People 的方法 + *Address 的方法,")]),t._v(" "),a("p",[t._v("但是如果 s 这里是指针类型的话,那么它调用的就是 *People 的方法 +*Address 的方法")]),t._v(" "),a("p",[t._v("不过即便 s 是值的时候,people 上本身是定义在指针上的方法,那么它在底层调用的时候也势必是 *People")]),t._v(" "),a("p",[t._v("总结一下:结构体变量是什么类型不重要,重要的是定义方法时使用的是什么类型。")]),t._v(" "),a("p",[t._v("你也可以不使用嵌入,使用 "),a("code",[t._v("s.Address.Value()")]),t._v(" 来调用方法:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n People People\n Address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Address\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" s Student\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//由于这里的address字段是指针,所以我们必须给address赋予实际的值的地址:")]),t._v("\n s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("People"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Name")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Value")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"define-类型的方法集合"}},[t._v("define 类型的方法集合")]),t._v(" "),a("p",[t._v("define 就是 "),a("code",[t._v("type A int")]),t._v(" 的意思 (type A = int 是另一个意思表示 alias),其中新类型 A 叫做 define 类型,int 叫做 underlying 类型")]),t._v(" "),a("p",[t._v("define 类型的底层如果是接口,那么它完全可以 “继承” 底层数据的方法,比如底层接口拥有三个抽象函数,那么它也有三个一模一样的三个抽线函数")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello, 世界"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b B\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" d D\n\tb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" d\n\tb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" B A\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" D "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("D"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("但是,如果不是接口类型,那么这个类型上就什么方法都没有。它跟它底层的 underlying 将没有任何的联系。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello, 世界"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a1 a\n\ta1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b1 b\n\tb1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" b a\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// error: b1.get undefined (type b has no field or method get)")]),t._v("\n")])])]),a("h2",{attrs:{id:"类型别名的方法集合"}},[t._v("类型别名的方法集合")]),t._v(" "),a("p",[t._v("接下来我们介绍一个类型的别名 alias")]),t._v(" "),a("p",[t._v("使用方法是这样的:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("rune")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v("\n")])])]),a("p",[t._v("可以看到跟")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("rune")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int32")]),t._v("\n")])])]),a("p",[t._v("非常像,但是,我要强调一下,这两者是完全不同的东西。前者是类型别名,rune 就是 int32 的一个分身,它跟 int32 完全拥有相同的权利,后者,rune 和 int32 是完全两个类型,只是 rune 使用了 int32 作为自己的底层数据而已。")]),t._v(" "),a("p",[t._v("我们看一个例子:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello, 世界"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" h hiInterface\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" hi hiStruct\n\th "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" hi\n\n\th"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" myInterface "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" myStruct "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("myStruct"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" hiInterface "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" myInterface\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" hiStruct "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" myStruct\n\n")])])]),a("p",[t._v("可以看到,别名和类型之间,完全相同,完全等价,不管是接口还是结构体,亦或者是其它的东西。")]),t._v(" "),a("h2",{attrs:{id:"函数式编程"}},[t._v("函数式编程")]),t._v(" "),a("p",[t._v("函数就是一个普通的类型,它跟 int,string,拥有相同的地位,所以你会发现函数式编程在 go 语言的代码里运用的很广泛。")]),t._v(" "),a("p",[t._v("比如:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("函数作为 go 语言中的一等公民,拥有以下特征:")]),t._v(" "),a("ul",[a("li",[t._v("在源码的顶层正常的创建函数")]),t._v(" "),a("li",[t._v("函数可以存在于函数内部")]),t._v(" "),a("li",[t._v("函数可以作为类型")]),t._v(" "),a("li",[t._v("函数可以赋值给一个变量")]),t._v(" "),a("li",[t._v("函数可以作为参数")]),t._v(" "),a("li",[t._v("函数可以作为返回值,并且拥有闭包")])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在源码的顶层正常的创建函数")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// main.go")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数可以存在于函数内部")]),t._v("\n\nfun "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数可以作为类型")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" A "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数可以赋值给一个变量")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数可以作为参数")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" f1 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 函数可以作为返回值,并且拥有闭包")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\tg "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hello"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"world"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"--------------------------------"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("g")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你好"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Get")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\ti"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("++")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//out")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//hello")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 1")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// world")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 2")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// --------------------------------")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 3")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// hi")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 4")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 你好")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 5")]),t._v("\n\n")])])]),a("h3",{attrs:{id:"函数式编程的实际应用"}},[t._v("函数式编程的实际应用")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("柯里化函数")])])]),t._v(" "),a("p",[t._v("概念:接受多个参数的函数,变成接受一个单一参数的函数,并且返回接受剩余参数以及返回值的新函数。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" y"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" x "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" y "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" c\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("partialSum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("y"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" y"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" c"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tt1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("partialSum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tt2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("partialSum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tt3 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("partialSum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("t1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("t2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("t3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("8")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("9")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[a("em",[a("strong",[t._v("函子")])])]),t._v(" "),a("p",[t._v("概念:functor (函子) 本身是一个容器 (slice map channel),容器类型实现一个方法,该方法接受一个函数类型参数,并且每一个容器参数都要被这个函数去改变,这里会得到一个新的 functor,原有的容器没有任何的影响。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" IntSliceFunctor "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fmap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IntSliceFunctor\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" IntSliceFunctorImpl "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tints "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f IntSliceFunctorImpl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fmap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f1 "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IntSliceFunctor "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tnewInts "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("len")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ints"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" f"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("ints "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tnewInts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("f1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" IntSliceFunctorImpl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("newInts"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewIntSliceFunctorImpl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("ints "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" IntSliceFunctor "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" IntSliceFunctorImpl"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("ints"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\ti "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewIntSliceFunctorImpl")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tm1 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fmap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tm1p "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" i"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fmap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tm2 "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" m1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fmap")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" i "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("m1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" m1p"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" m2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[a("em",[a("strong",[t._v("配置选项问题")])])]),t._v(" "),a("p",[a("em",[a("strong",[t._v("最基础的方法就是全部暴露出去")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Server "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n Protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewDefalutServer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Server "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n port"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n protocol"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewPortServer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Server "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"8080"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tcp"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("直接暴露这是一种最基础的方案,这种方法可扩展性很差。")]),t._v(" "),a("p",[t._v("如果想改进,完全可以把非固定的字段单独的封装在一个 struct 中,比如这种写法:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Server "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n options "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Options\n \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Options "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewServer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" options "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Server "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("还有一种场景是这样的,我们输出的 API 是一定的,但是我们的配置信息,因为是共同使用的,它可能会越来越多,这个时候改如何处理呢?")]),t._v(" "),a("p",[a("em",[a("strong",[t._v("设置一个固定的 struct,以及一个可共用的 opintions struct")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Server "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n Protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Options "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n Protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这种写法,API内容不变,共同的options即便是变化了也无关紧要。")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewServer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("options "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Server "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" options "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Addr\n port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Port\n protocol "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Protocol\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n port"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n protocol"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("我们还可以使用链式调用的方式去写这种参数")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Server "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n Port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n Protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ServerBulder "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n Server\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Addr "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addr\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" sb\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("BuildWithPort")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" port\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" sb\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("BuildWithProtocol")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n sb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Protocol "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" protocol\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" sb\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("sb "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ServerBulder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Run")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("Server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" sb"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Server\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[a("em",[a("strong",[t._v("functional Options --- 功能选项模式")])])]),t._v(" "),a("p",[t._v("使用场景:在一个配置中心,我们并不想把配置的 struct 暴漏出去,那么我们可以将这个 struct 定义为非导出类型,然后我们定义一个可导出的函数类型,将这个 struct 设置为函数的参数,使用这个可导出的函数来完成配置的操作。")]),t._v(" "),a("p",[t._v("首先是定义一个函数类型")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Option "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" server "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\n protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们使用函数式的方式去定义一组函数")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithPort")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("port "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Options "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("port "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" port\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithProtocol")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("protocol "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" Options "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n retrun "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("protocol "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" protocol\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewServer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addr "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" options "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("...")]),t._v("Option"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("server "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n serv "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" server"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n addr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"8080"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tcp"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" opt "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" options "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("opt")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("serv"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 接下来的处理")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"xx/example"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewServer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bj"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithPort")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"8080"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("WithProtocol")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"tcp"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("如你所见,使用了函数作为返回值,函数作为参数,变长函数以及闭包等知识,去完成了 “functional options” 这种函数式编程的模式。\n在这个场景下,我们扩展配置变得非常容易,并不需要更改现有的代码,并且也防止了配置 struct 的外漏。")]),t._v(" "),a("h3",{attrs:{id:"这里还有关于函数式编程其它相关内容"}},[t._v("这里还有关于函数式编程其它相关内容:")]),t._v(" "),a("blockquote",[a("p",[t._v("这里的主要内容来自酷壳 https://coolshell.cn/?s=GO+编程模式 (R.I.P 耗子叔)")])]),t._v(" "),a("ul",[a("li",[a("RouterLink",{attrs:{to:"/基础/函数方法/0.html"}},[t._v("反转控制")])],1),t._v(" "),a("li",[a("RouterLink",{attrs:{to:"/基础/函数方法/1.html"}},[t._v("map-reduce")])],1),t._v(" "),a("li",[a("RouterLink",{attrs:{to:"/基础/函数方法/3.html"}},[t._v("修饰器")])],1),t._v(" "),a("li",[a("RouterLink",{attrs:{to:"/基础/函数方法/4.html"}},[t._v("pipeline")])],1),t._v(" "),a("li",[a("RouterLink",{attrs:{to:"/基础/函数方法/5.html"}},[t._v("k8s visitor")])],1),t._v(" "),a("li",[t._v("k8s builder")]),t._v(" "),a("li",[a("RouterLink",{attrs:{to:"/基础/函数方法/7.html"}},[t._v("综合题")])],1)]),t._v(" "),a("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),a("p",[a("code",[t._v("问题一:")]),t._v(" "),a("em",[a("strong",[t._v("关于方法的一道题:判断输出")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"一"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"二"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"三"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" a "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"四"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"五"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"六"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" v "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" b "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" v"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\ttime"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Sleep")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("time"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Second"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Student "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tname "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("答案是:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("三\n六\n六\n一\n二\n六\n")])])]),a("p",[t._v("回答:")]),t._v(" "),a("p",[t._v("可以看到,我们期望的一二三四五六并没有输出,这里不考虑顺序,那么四和五为什么没有输出呢?这个时候我们应该考虑方法的本质。")]),t._v(" "),a("p",[t._v("首先我们定了一个在指针类型上的方法 pName,所以第一个 for 循环中,实际上的运行是,每一个指针类型,然后定义在他们上面的方法,并且输出,但是第二个他们是值类型,go 的编译器自动给引出了指针类型,所以说按照指针的实质")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("pName")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("Student"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n \n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("这里放置的就是 &v,还有个大的原因,就是整个 for 循环比开辟一个新的 goroutine 并且运行完毕远远的快,所以当三个 goroutine 开辟完成的时候,所引用的&v 就是同一个数据了。所以这个时候输出的就是同样的最后的数据值,也就是 “六”,不过这里如果 for 的每一次循环事件都很长,那么 goroutine 运行将会输出 “四五六”。")]),t._v(" "),a("p",[t._v("如果想正常的输出,可以把定义在指针上的方法,改成定义在值上的方法即可。")]),t._v(" "),a("p",[a("code",[t._v("问题二:")]),t._v(" "),a("em",[a("strong",[t._v("panic(nil) 时,defer 函数中的 recover() == nil 成立吗")])])]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"reflect"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("defer")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\ta "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("recover")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("答案是:")]),t._v(" "),a("p",[t._v("当 go1.21+ 的时候,不成立,在小于 1.21 的版本中是成立的。")]),t._v(" "),a("p",[t._v("在 1.21 以下,panic 中的 nil 是会传递给 recover() 函数的,所以必定是 true,但是在 1.21+的版本中,"),a("code",[t._v("panic(nil)")]),t._v(" 在编译时,底层修改为了 "),a("code",[t._v("panic(new(runtime.PanicNilError))")])]),t._v(" "),a("p",[t._v("所以说,nil 是不等于 *runtime.PanicNilError 的,综上所述,小于 1.21 的版本成立,大于 1.21 的版本不成立。")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://book.douban.com/subject/35720728/ 170 页 - 243 页")]),t._v(" "),a("li",[t._v("https://coolshell.cn/?s=GO+编程模式")]),t._v(" "),a("li",[t._v("https://github.com/golang/go/blob/06264b740e3bfe619f5e90359d8f0d521bd47806/src/database/sql/sql.go#L813")]),t._v(" "),a("li",[t._v("https://github.com/lib/pq/blob/922c00e176fb3960d912dc2c7f67ea2cf18d27b0/conn.go#L60")])])])}),[],!1,null,null,null);s.default=p.exports}}]); \ No newline at end of file diff --git a/assets/js/80.5aa44af4.js b/assets/js/80.5aa44af4.js new file mode 100644 index 000000000..7ff2f0cc8 --- /dev/null +++ b/assets/js/80.5aa44af4.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[80],{510:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/81.33455a03.js b/assets/js/81.33455a03.js new file mode 100644 index 000000000..6ab142a36 --- /dev/null +++ b/assets/js/81.33455a03.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[81],{511:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/82.9f2284bd.js b/assets/js/82.9f2284bd.js new file mode 100644 index 000000000..1d8f2daf7 --- /dev/null +++ b/assets/js/82.9f2284bd.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[82],{512:function(t,e,n){"use strict";n.r(e);var s=n(36),l=Object(s.a)({},(function(){var t=this.$createElement;return(this._self._c||t)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/83.5e222179.js b/assets/js/83.5e222179.js new file mode 100644 index 000000000..14ef7072d --- /dev/null +++ b/assets/js/83.5e222179.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[83],{514:function(v,_,l){"use strict";l.r(_);var i=l(36),n=Object(i.a)({},(function(){var v=this,_=v.$createElement,l=v._self._c||_;return l("ContentSlotsDistributor",{attrs:{"slot-key":v.$parent.slotKey}},[l("ol",[l("li",[v._v("自我介绍")]),v._v(" "),l("li",[v._v("代码效率分析,考察局部性原理")]),v._v(" "),l("li",[v._v("多核 CPU 场景下,cache 如何保持一致、不冲突?")]),v._v(" "),l("li",[v._v("uint 类型溢出")]),v._v(" "),l("li",[v._v("介绍 rune 类型")]),v._v(" "),l("li",[v._v("编程题:3 个函数分别打印 cat、dog、fish,要求每个函数都要起一个 goroutine,按照 cat、dog、fish 顺序打印在屏幕上 100 次。")]),v._v(" "),l("li",[v._v("介绍一下 channel,无缓冲和有缓冲区别")]),v._v(" "),l("li",[v._v("是否了解 channel 底层实现,比如实现 channel 的数据结构是什么?")]),v._v(" "),l("li",[v._v("channel 是否线程安全?")]),v._v(" "),l("li",[v._v("Mutex 是悲观锁还是乐观锁?悲观锁、乐观锁是什么?")]),v._v(" "),l("li",[v._v("Mutex 几种模式?")]),v._v(" "),l("li",[v._v("Mutex 可以做自旋锁吗?")]),v._v(" "),l("li",[v._v("介绍一下 RWMutex")]),v._v(" "),l("li",[v._v("项目中用过的锁?")]),v._v(" "),l("li",[v._v("介绍一下线程安全的共享内存方式")]),v._v(" "),l("li",[v._v("介绍一下 goroutine")]),v._v(" "),l("li",[v._v("goroutine 自旋占用 cpu 如何解决 (go 调用、gmp)")]),v._v(" "),l("li",[v._v("介绍 linux 系统信号")]),v._v(" "),l("li",[v._v("goroutine 抢占时机 (gc 栈扫描)")]),v._v(" "),l("li",[v._v("Gc 触发时机")]),v._v(" "),l("li",[v._v("是否了解其他 gc 机制")]),v._v(" "),l("li",[v._v("Go 内存管理方式")]),v._v(" "),l("li",[v._v("Channel 分配在栈上还是堆上?哪些对象分配在堆上,哪些对象分配在栈上?")]),v._v(" "),l("li",[v._v("介绍一下大对象小对象,为什么小对象多了会造成 gc 压力?")]),v._v(" "),l("li",[v._v("项目中遇到的 oom 情况?")]),v._v(" "),l("li",[v._v("项目中使用 go 遇到的坑?")]),v._v(" "),l("li",[v._v("工作遇到的难题、有挑战的事情,如何解决?")]),v._v(" "),l("li",[v._v("如何指定指令执行顺序?")])])])}),[],!1,null,null,null);_.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/84.b93653e7.js b/assets/js/84.b93653e7.js new file mode 100644 index 000000000..bc68c747a --- /dev/null +++ b/assets/js/84.b93653e7.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[84],{513:function(t,s,i){"use strict";i.r(s);var n=i(36),e=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"ioc"}},[this._v("IOC")]),this._v(" "),s("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),s("ul",[s("li",[this._v("https://mp.weixin.qq.com/s/Ar-JdkrQ5NnCWcGOoCuVgg")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/85.aff346f9.js b/assets/js/85.aff346f9.js new file mode 100644 index 000000000..305d6eec3 --- /dev/null +++ b/assets/js/85.aff346f9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[85],{515:function(t,o,e){"use strict";e.r(o);var l=e(36),s=Object(l.a)({},(function(){var t=this,o=t.$createElement,e=t._self._c||o;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"log-包"}},[t._v("log 包")]),t._v(" "),e("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),e("ul",[e("li",[t._v("https://github.com/uber-go/zap")]),t._v(" "),e("li",[t._v("https://pkg.go.dev/golang.org/x/exp/slog")])])])}),[],!1,null,null,null);o.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/86.ca707802.js b/assets/js/86.ca707802.js new file mode 100644 index 000000000..349c81eac --- /dev/null +++ b/assets/js/86.ca707802.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[86],{516:function(t,s,e){"use strict";e.r(s);var l=e(36),o=Object(l.a)({},(function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"wasm-在-go-中的实践"}},[t._v("wasm 在 go 中的实践")]),t._v(" "),e("h2",{attrs:{id:"参考文章"}},[t._v("参考文章")]),t._v(" "),e("ul",[e("li",[t._v("https://github.com/golang/go/wiki/WebAssembly")]),t._v(" "),e("li",[t._v("https://blog.csdn.net/jojo1001/article/details/130611146")])])])}),[],!1,null,null,null);s.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/87.d9bc2332.js b/assets/js/87.d9bc2332.js new file mode 100644 index 000000000..32bd3409e --- /dev/null +++ b/assets/js/87.d9bc2332.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[87],{517:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"代码检查工具"}},[t._v("代码检查工具")]),t._v(" "),a("p",[t._v("代码检查通常会被配置再 CI 中,用于自动检查代码的质量,本次我们介绍三个用于代码检查的工具")]),t._v(" "),a("ul",[a("li",[t._v("go vet / go tool vet")]),t._v(" "),a("li",[t._v("golangci-lint")]),t._v(" "),a("li",[t._v("govulncheck")])]),t._v(" "),a("h2",{attrs:{id:"go-vet-go-tool-vet"}},[t._v("go vet / go tool vet")]),t._v(" "),a("p",[t._v("go vet 命令是 go tool vet 的简单封装,go vet 实际上还是需要调用 go tool vet 才能完成工作,这俩命令的主要目的就是为了基础的代码检查。不过这个命令只能做简单的检查,下面我们介绍一下更常用的工具。")]),t._v(" "),a("h2",{attrs:{id:"golangci-lint"}},[t._v("golangci-lint")]),t._v(" "),a("p",[t._v("首先在介绍 golangci-lint 之前我们先下载它,它是一个 go 语言写的可执行文件,使用")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" install github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golangci"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golangci"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("lint"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("cmd"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golangci"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("lint@latest \n")])])]),a("p",[t._v("即可下载到本地的~/go/bin/ 目录,这里专门存储使用 go install 下载的使用 go 写的可执行文件,记得将这个路径加入 PATH。")]),t._v(" "),a("p",[t._v("通过在要检查的项目中设置配置文件,用来配置 lint 工具的选项,使用 "),a("code",[t._v(".golangci.yaml")]),t._v(" 即可")]),t._v(" "),a("p",[t._v("例如:")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("\nrun:\n skip-dirs: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 设置要忽略的目录")]),t._v("\n - util\n - .*~\n - api/swagger/docs\n skip-files: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 设置不需要检查的go源码文件,支持正则匹配,这里建议包括:_test.go")]),t._v("\n - "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('".*'),a("span",{pre:!0,attrs:{class:"token entity",title:"\\\\"}},[t._v("\\\\")]),t._v(".my"),a("span",{pre:!0,attrs:{class:"token entity",title:"\\\\"}},[t._v("\\\\")]),t._v('.go$"')]),t._v("\n - _test.go\nlinters-settings:\n errcheck:\n check-type-assertions: "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 这里建议设置为true,如果确实不需要检查,可以写成`num, _ := strconv.Atoi(numStr)`")]),t._v("\n check-blank: "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n gci:\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 将以`github.com/marmotedu/iam`开头的包放在第三方包后面")]),t._v("\n local-prefixes: github.com/marmotedu/iam\n godox:\n keywords: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 建议设置为BUG、FIXME、OPTIMIZE、HACK")]),t._v("\n - BUG\n - FIXME\n - OPTIMIZE\n - HACK\n goimports:\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 设置哪些包放在第三方包后面,可以设置多个包,逗号隔开")]),t._v("\n local-prefixes: github.com/marmotedu/iam\n gomoddirectives: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 设置允许在go.mod中replace的包")]),t._v("\n replace-local: "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),t._v("\n replace-allow-list:\n - github.com/coreos/etcd\n - google.golang.org/grpc\n - github.com/marmotedu/api\n - github.com/marmotedu/component-base\n - github.com/marmotedu/marmotedu-sdk-go\n gomodguard: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 下面是根据需要选择可以使用的包和版本,建议设置")]),t._v("\n allowed:\n modules:\n - gorm.io/gorm\n - gorm.io/driver/mysql\n - k8s.io/klog\n domains: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# List of allowed module domains")]),t._v("\n - google.golang.org\n - gopkg.in\n - golang.org\n - github.com\n - go.uber.org\n blocked:\n modules:\n - github.com/pkg/errors:\n recommendations:\n - github.com/marmotedu/errors\n reason: "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"'),a("span",{pre:!0,attrs:{class:"token variable"}},[a("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("github.com/marmotedu/errors"),a("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v(' is the log package used by marmotedu projects."')]),t._v("\n versions:\n - github.com/MakeNowJust/heredoc:\n version: "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"> 2.0.9"')]),t._v("\n reason: "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"use the latest version"')]),t._v("\n local_replace_directives: "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),t._v("\n lll:\n line-length: "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("240")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 这里可以设置为240,240一般是够用的")]),t._v("\n importas: "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 设置包的alias,根据需要设置")]),t._v("\n jwt: github.com/appleboy/gin-jwt/v2 \n metav1: github.com/marmotedu/component-base/pkg/meta/v1\n\n")])])]),a("p",[t._v("使用 golangci-lint run (等于 golangci-lint run ./... 意思就是把所有的包,子包,遍历完全) 你会得到一个类似:")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("\ncollie.go:171:41: composites: image/jpeg.Options struct literal uses unkeyed fields "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("govet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err :"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" jpeg.Encode"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("file, i.img, "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("jpeg.Options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("q"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" nil "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t\t\t ^\ncollie.go:241:2: printf: "),a("span",{pre:!0,attrs:{class:"token variable"}},[a("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("fmt.Println"),a("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v(" arg list ends with redundant newline "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("govet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt.Println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"声明:本程序来自GitHub:shgopher,欢迎关注公众号:科科人神;'),a("span",{pre:!0,attrs:{class:"token entity",title:"\\n"}},[t._v("\\n")]),t._v("免费软件,如果使用期间出现任何后果,本软件不承担任何责任谢谢"),a("span",{pre:!0,attrs:{class:"token entity",title:"\\n"}},[t._v("\\n")]),t._v('"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t^\ncollie.go:244:2: printf: "),a("span",{pre:!0,attrs:{class:"token variable"}},[a("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("fmt.Println"),a("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v(" arg list ends with redundant newline "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("govet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt.Println"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"运行结束 ☕️ ☕ ☕'),a("span",{pre:!0,attrs:{class:"token entity",title:"\\n"}},[t._v("\\n")]),t._v('"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t^\ncollie.go:162:5: SA9001: defers "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" this range loop won't run unless the channel gets closed "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("staticcheck"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\tdefer file.Close"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\t\t\t^\n")])])]),a("p",[t._v("这样的结果,这样你就会发现是哪个配置的 linter 发出的警告,以及是什么样子的警告。")]),t._v(" "),a("h2",{attrs:{id:"govulncheck"}},[t._v("govulncheck")]),t._v(" "),a("p",[t._v("go 官方维护了一个 https://vuln.go.dev/ 的漏洞库,我们可以使用 "),a("code",[t._v("go install golang.org/x/vuln/cmd/govulncheck@latest")]),t._v(" 的方式,下载目前 (go 1.19) 还在测试阶段的这一功能,"),a("code",[t._v("govulncheck")]),t._v(" 将会是一个独立的工具,并且 go 在 https://pkg.go.dev/golang.org/x/vuln/vulncheck 还提供了相关功能的 API,可以更灵活的去使用这个功能,目前已知的即将推出的功能分别是提供 vscode 插件,以及将此功能集成在 pkg.go.dev 这个 go 包的集合地,也就是说只要被收录在这个网站的 go 包都将自动接受漏洞检查,另外,go 以后可能还会将这个功能直接集成在例如 "),a("code",[t._v("go build")]),t._v(" 这种常用命令上。")]),t._v(" "),a("ul",[a("li",[t._v("下载 govulncheck "),a("code",[t._v("go install golang.org/x/vuln/cmd/govulncheck@latest")])]),t._v(" "),a("li",[t._v("在一个拥有 go.mod 的目录下,使用 govulncheck 跟上一个有 go 文件的路径,例如:"),a("code",[t._v("govulncheck ./pkg/watcher")])])]),t._v(" "),a("p",[t._v("只需要这样简单的设置就可以去检查代码中存在的风险和漏洞,govulncheck 就会打印出这样的信息:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("Vulnerability #"),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" GO"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2022")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0493")]),t._v("\n When called with a non"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("zero flags parameter"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" the Faccessat\n function can incorrectly report that a file is accessible"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n Found in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" golang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sys"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("unix@v0"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20211020064051")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("0ec99a608a1b\n Fixed in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" golang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("sys"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("unix@v0"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20220412211240")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("33da011f77ad\n More info"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" https"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("pkg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("dev"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("vuln"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("GO"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("2022")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0493")]),t._v("\n")])])]),a("p",[t._v("信息中包括了你引用的某些包出现的一些漏洞,在 fix 中有修复的信息,可以把你引用的包进行一个升级。")]),t._v(" "),a("h2",{attrs:{id:"x-tools-工具系列"}},[t._v("x/tools 工具系列")]),t._v(" "),a("blockquote",[a("p",[t._v("https://pkg.go.dev/golang.org/x/tools#section-readme")])]),t._v(" "),a("p",[t._v("比如检测变量 shadow 的工具")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("go "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow\n")])])]),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://go.dev/blog/vuln")]),t._v(" "),a("li",[t._v("https://time.geekbang.org/column/article/390401")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/88.87973a44.js b/assets/js/88.87973a44.js new file mode 100644 index 000000000..525bccfe9 --- /dev/null +++ b/assets/js/88.87973a44.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[88],{518:function(t,n,e){"use strict";e.r(n);var s=e(36),r=Object(s.a)({},(function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"优秀第三方包"}},[t._v("优秀第三方包")]),t._v(" "),e("ul",[e("li",[e("a",{attrs:{href:"./gin"}},[t._v("gin")]),t._v(" 优秀的 web 框架")]),t._v(" "),e("li",[e("a",{attrs:{href:"./sonic"}},[t._v("sonic")]),t._v(" 字节跳动出品的 json 引擎")])])])}),[],!1,null,null,null);n.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/89.37b7fea9.js b/assets/js/89.37b7fea9.js new file mode 100644 index 000000000..6e2569819 --- /dev/null +++ b/assets/js/89.37b7fea9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[89],{519:function(t,e,n){"use strict";n.r(e);var i=n(36),o=Object(i.a)({},(function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[n("h1",{attrs:{id:"gin"}},[t._v("gin")]),t._v(" "),n("blockquote",[n("p",[t._v("https://github.com/gin-gonic/gin")])]),t._v(" "),n("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),n("ul",[n("li",[t._v("https://betterprogramming.pub/a-do-it-yourself-implementation-of-the-golang-middleware-6f02f155ed17")])])])}),[],!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/9.e2b0263e.js b/assets/js/9.e2b0263e.js new file mode 100644 index 000000000..5385a455d --- /dev/null +++ b/assets/js/9.e2b0263e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{429:function(t,n){t.exports="data:image/png;base64,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"},470:function(t,n,a){"use strict";a.r(n);var s=a(36),e=Object(s.a)({},(function(){var t=this,n=t.$createElement,s=t._self._c||n;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"go-数字类型"}},[t._v("go 数字类型")]),t._v(" "),s("p",[s("strong",[t._v("导读:")])]),t._v(" "),s("ul",[s("li",[t._v("int")]),t._v(" "),s("li",[t._v("float")]),t._v(" "),s("li",[t._v("complex")]),t._v(" "),s("li",[t._v("issues")])]),t._v(" "),s("h2",{attrs:{id:"int"}},[t._v("int")]),t._v(" "),s("p",[t._v("int 是 go 语言的整数类型,一共分为下面这么几类")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("类型")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("描述")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("int")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("有符号的整数类型,具体占几个字节要看操作系统的分配,不过至少分配给32位")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("uint")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("非负整数类型,具体占几个字节要看操作系统的分配,不过至少分配给32位")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("int8")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("有符号的整数类型,占8位bit,1个字节。范围从负的2的7次方到正的2的7次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("int16")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("有符号的整数类型,占16位bit,2个字节。范围从负的2的15次方到正的2的15次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("int32")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("有符号的整数类型,占32位bit,4个字节。范围从负的2的31次方到正的2的31次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("int64")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("有符号的整数类型,占64位bit,8个字节。范围从负的2的63次方到正的2的63次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("uint8")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("无符号的正整数类型,占8位,从0到2的8次方减1.也就是0到255")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("uint16")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("无符号的正整数类型,占16位,从0到2的16次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("uint32")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("无符号的正整数类型,占32位,从0到2的32次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("uint64")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("无符号的正整数类型,占64位,从0到2的64次方减1")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("uintptr")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("无符号整数类型。它大到足以容纳任何指针")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("rune")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("int32的别名,代表一个 UTF-8 字符")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("byte")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("uint8别名,代表了ASCII 码的一个字符")])])])]),t._v(" "),s("p",[t._v("go 使用 "),s("code",[t._v("'\\x12'")]),t._v(" 或者使用 "),s("code",[t._v("0x12")]),t._v(" 来表示 16 进制")]),t._v(" "),s("p",[t._v("go 使用 "),s("code",[t._v("'\\012'")]),t._v(" 或者使用 "),s("code",[t._v("012")]),t._v(" 来表示 8 进制")]),t._v(" "),s("p",[t._v("go 不能直接显示 2 进制,使用 "),s("code",[t._v('fmt.Printf("%b",12)')]),t._v(" "),s("code",[t._v("1000")]),t._v(" 来输出一个二进制")]),t._v(" "),s("h2",{attrs:{id:"float"}},[t._v("float")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("类型")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("描述")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("float32")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("浮点型,包括正负小数,IEEE-754 32位的集合,提供大约 6 个十进制数的精度,math.MaxFloat32 表示 float32 能取到的最大数值,math.SmallestNonzeroFloat32表示最小值")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("float64")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("浮点型,包括正负小数,IEEE-754 64位的集合,提供约 15 个十进制数的精度,math.MaxFloat64 表示 float64 能取到的最大数值,math.SmallestNonzeroFloat64表示最小值")])])])]),t._v(" "),s("p",[t._v("浮点数使用 "),s("code",[t._v('fmt.Printf("%.4f\\n", math.Pi)')]),t._v(","),s("code",[t._v("%.nf")]),t._v(" 来控制保留几位小数")]),t._v(" "),s("p",[t._v("我们知道根据 IEEE 754 标准,使用有限个位置的二进制数字去代表无限个数字,那么必然是不精确的,是近似的。")]),t._v(" "),s("p",[t._v("由于浮点数计算的时候并不精确,容易发生较大误差,所以我们可以使用现有的高精度第三方库进行替换:https://github.com/shopspring/decimal")]),t._v(" "),s("h3",{attrs:{id:"基础浮点数-math-big-包-decimal-三方包的对比"}},[t._v("基础浮点数,math/big 包,decimal 三方包的对比")]),t._v(" "),s("p",[t._v("让我们看一下著名的 0.1 + 0.2 != 0.3 这个问题")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" a "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.1")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" b "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.2")]),t._v("\n\t\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// false")]),t._v("\n\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("a"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v("b "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[s("em",[s("strong",[t._v("基础浮点数 IEEE 754 详细介绍")])])]),t._v(" "),s("p",[t._v("这是一个 IEEE 754 的内部存储示意图,这个标准下,数字使用二进制的方式进行存储:")]),t._v(" "),s("p",[s("img",{attrs:{src:a(429),alt:"IEEE 754"}})]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("sign")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("exponent")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("fraction")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("代表正负的符号位")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("指数位")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("尾数")])])])]),t._v(" "),s("ul",[s("li",[s("p",[t._v("sign:"),s("code",[t._v("(-1)^sign")]),t._v(",所以当 sign 等于 0 时,就是正数,当 sign 等于 1 时就是负数")])]),t._v(" "),s("li",[s("p",[t._v("exponent:指数,也就是 2 的指数,在计算的时候,我们要减去一个偏移量 (127 或者 1023,这取决于 32 位还是 64 位),在 32 位的情况下,0 - 255,然后减去偏移量 127,结果是:[-126,127] (正常情况下,不算上 00000000 和 11111111 这两种情况)")])]),t._v(" "),s("li",[s("p",[t._v("fraction:尾数,表示为 1.fraction 或者 0。fraction 的样子,后者通常表示的极小浮点数")])])]),t._v(" "),s("p",[t._v("例如,图示的 0.15625,使用 IEEE 754 来表示:")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1111100")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.01")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("124")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("127")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.01")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.01")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.00101")]),t._v("(二进制)\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.15625")]),t._v(" (十进制)\n")])])]),s("p",[t._v("可以看到,一个十进制的 0.15625 要转化为一个 2 进制的信息进行保存,那么问题来了,为什么浮点数的 0.1 不等于整数的 0.1 呢?")]),t._v(" "),s("blockquote",[s("p",[t._v("10 进制小数转化为 2 进制:使用十进制的小数部分乘以 2,然后取整数部分,然后再把这个数的小数部分再次乘以 2... 直到小数部分为零结束;十进制的整数部分就按照普通的除法,每次都除以 2,然后取余数,直到商为 0:")])]),t._v(" "),s("blockquote",[s("p",[t._v("举一个例子:十进制 8.35;")])]),t._v(" "),s("blockquote",[s("p",[t._v("整数部分是 8,8 /2 = 4 余 0,4/2 = 2 余 0,2/2 = 1 余 0,1/2=0 余 1,那么根据倒序排列来得出结果就是 1000;")])]),t._v(" "),s("blockquote",[s("p",[t._v("小数部分是 0.35,0.35 "),s("em",[t._v("2 = 0.7 整数部分是 0,0.7")]),t._v(" 2 = 1.4 整数部分是 1,0.4 "),s("em",[t._v("2 = 0.8 整数部分是 0,0.8")]),t._v(" 2 = 1.6 整数部分是 1,0.6 "),s("em",[t._v("2 = 1.2 整数部分是 1,0.2")]),t._v(" 2 = 0.4 整数部分是 0,0.4 "),s("em",[t._v("2 = 0.8 整数部分是 0,0.8")]),t._v("2 = 1.6 ... 那么小数部分就是 0.01011001... 那么在满足某个精度的情况下,它的值用二进制表示就是 1000.01011001;")])]),t._v(" "),s("blockquote",[s("p",[t._v("将它还原也很简单,整数部分按照 2 的指数,小数部分按照 2 的负指数:1*2^3 + 2^-2 + 2^-4 + 2^-5 = 8.34375")])]),t._v(" "),s("p",[t._v("第一步,我们需要将 0.1 转化为二进制,那么等于多少呢?")]),t._v(" "),s("p",[t._v("答案是:0.0001100110011...")]),t._v(" "),s("p",[t._v("看到了吧,除不尽啊,那么我们取它的尾数 1.1001100110011001100 * 2^-4")]),t._v(" "),s("p",[t._v("如果填入他们的图就是")]),t._v(" "),s("ul",[s("li",[t._v("sign 为 0")]),t._v(" "),s("li",[t._v("指数的十进制为 -4 + 127 = 123,也就是 "),s("code",[t._v("1111011")]),t._v(" 填入上面的内容就是 01111011")]),t._v(" "),s("li",[t._v("尾数是 100110011001100")])]),t._v(" "),s("p",[t._v("所以你会发现从这里的存储再转化为 10 进制的结果就是")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("^")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.1001100110011")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.00011001100110011")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0999984741210937")]),t._v("\n")])])]),s("p",[t._v("总结:由于某些数字,从 10 进制转化为 2 进制的时候,无法得到精确值,除不尽,所以,浮点数存储数字,有些数字不能精确存储")]),t._v(" "),s("p",[s("em",[s("strong",[t._v("math/big 包详细介绍")])])]),t._v(" "),s("p",[t._v("big 拥有下面三个类型")]),t._v(" "),s("ul",[s("li",[t._v("Int")]),t._v(" "),s("li",[t._v("Float")]),t._v(" "),s("li",[t._v("Rat (有理数)")])]),t._v(" "),s("p",[t._v("big 包提供的 "),s("code",[t._v("big.Int")]),t._v(" 底层数据是一个切片,所以说它可以保存超过 "),s("code",[t._v("uint64")]),t._v(" 的数据;"),s("code",[t._v("big.Rat")]),t._v(" 的底层数据是,分子和分母分别都是一个 "),s("code",[t._v("big.Int")]),t._v(" 类型,所以说它也可以保存超过 uint64 的数据。")]),t._v(" "),s("p",[t._v("big.Float 类型是 Go 语言中提供的一个高精度的浮点数计算库,它使用了任意精度的浮点数表示,可以处理大数和小数,并提供了一系列的计算方法")]),t._v(" "),s("p",[t._v("虽然它是高精度的浮点数计算,但是仍然不够精确,如果是绝对的精确的浮点数计算,通常要使用有理数,或者使用整数去取代真正的小数,下面这个第三方包就是使用整数去取代浮点数的方式来获取精确的浮点数运行结果。")]),t._v(" "),s("p",[s("em",[s("strong",[t._v("decimal")])])]),t._v(" "),s("p",[t._v("这个第三方包底层使用 "),s("code",[t._v("big.Int")]),t._v(" 进行处理数据,也就是说,它使用整数存储,计算然后得出结论的时候再把之前的指数还原即可,所以它可以进行精确的浮点数运算")]),t._v(" "),s("p",[t._v("https://github.com/shopspring/decimal")]),t._v(" "),s("p",[t._v("这个包中,0.1 + 0.2 就等于 0.3 了")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 创建一个新的Float类型")]),t._v("\n\ta "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" decimal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewFromFloat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tb "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" decimal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewFromFloat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" decimal"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("NewFromFloat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tvalue "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" a"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Add")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("b"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 0")]),t._v("\n\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Cmp")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("c"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"complex-复数"}},[t._v("complex 复数")]),t._v(" "),s("table",[s("thead",[s("tr",[s("th",{staticStyle:{"text-align":"center"}},[t._v("类型")]),t._v(" "),s("th",{staticStyle:{"text-align":"center"}},[t._v("描述")])])]),t._v(" "),s("tbody",[s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("complex64")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("实部和虚部是 float32")])]),t._v(" "),s("tr",[s("td",{staticStyle:{"text-align":"center"}},[t._v("complex128")]),t._v(" "),s("td",{staticStyle:{"text-align":"center"}},[t._v("实部和虚部都是 float64")])])])]),t._v(" "),s("p",[s("code",[t._v("c := complex(3, 4)")]),t._v(" 创建一个复数,实部为 3,虚部为 4")]),t._v(" "),s("p",[t._v("或者还可以这样:"),s("code",[t._v("c := 3 + 4i")])]),t._v(" "),s("p",[t._v("使用 go 语言内置的函数 "),s("code",[t._v("real()")]),t._v(" 和 "),s("code",[t._v("imag()")]),t._v(" 来分别获取到复数的实部和虚部")]),t._v(" "),s("h2",{attrs:{id:"issues"}},[t._v("issues")]),t._v(" "),s("p",[t._v("***问题一:***go 语言数字之间的类型转化是如何进行的")]),t._v(" "),s("p",[t._v("go 语言的类型转换是显性转化的,数字类型之间可以使用这种方法")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" i "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),t._v("\nf "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("float64")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("i"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("***问题二:***能说说 "),s("code",[t._v("uintptr")]),t._v(" 和 "),s("code",[t._v("unsafe.Pointer")]),t._v(" 的区别吗")]),t._v(" "),s("ul",[s("li",[s("code",[t._v("unsafe.Pointer")]),t._v(" 是通用指针类型,它不能参与计算")]),t._v(" "),s("li",[s("code",[t._v("uintptr")]),t._v(" 是指针运算的工具,但是它不能持有指针对象 (意思就是它跟指针对象不能互相转换)")]),t._v(" "),s("li",[s("code",[t._v("unsafe.Pointer")]),t._v(" 和 "),s("code",[t._v("uintptr")]),t._v(" 可以相互转换,"),s("code",[t._v("unsafe.Pointer")]),t._v(" 和指针对象可以相互转换,但是 "),s("code",[t._v("uintptr")]),t._v(" 和指针对象不能相互转换")]),t._v(" "),s("li",[t._v("unsafe.Pointer 是指针对象进行运算 (也就是 uintptr) 的桥梁")])]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"unsafe"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 指针对象")]),t._v("\n\tv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将指针对象转化为通用指针类型")]),t._v("\n\tvp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" unsafe"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 将通用指针类型转换为指针对象")]),t._v("\n\tvo "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("vp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//将通用指针对象转化为uintptr")]),t._v("\n\tuv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("uintptr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("vp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//将uintptr转换为通用指针对象")]),t._v("\n\tvpp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" unsafe"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("uv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("v"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" uv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" vpp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 对指针对象的地址进行计算")]),t._v("\n\tt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 首先先将t转化为unsafe.Pointer类型")]),t._v("\n\tpt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" unsafe"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 然后将pointer再转化为 uintptr")]),t._v("\n\trt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("uintptr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//进行计算")]),t._v("\n\tnpt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" rt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("uintptr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 计算完毕后,再将uintptr转化为unsafe.Pointer再转换为*string类型")]),t._v("\n\tnt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("unsafe"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Pointer")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("npt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\tfmt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("t"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" pt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" npt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" nt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),s("p",[t._v("***问题三:***rune 和 byte 的区别")]),t._v(" "),s("p",[t._v("rune 是 int32,byte 是 uint8,相比 byte 来说,rune 可以容纳的字符个数要多很多,所以 utf8 编码的字符使用 rune,而 ascii 使用 byte,例如 ‘中’ byte 无法承受,“中” 转为 "),s("code",[t._v("[]byte")]),t._v(" 的时候是 "),s("code",[t._v("[228 184 173]")]),t._v(",“中” 转换为 "),s("code",[t._v("[]rune")]),t._v(" 则是等于 "),s("code",[t._v("[20013]")]),t._v(" 因为 rune 可承受的数值更大,并且一个 utf8 的字符就等于一个 rune 的数值,如果是使用 ‘中’ 那默认就是 rune 类型")]),t._v(" "),s("blockquote",[s("p",[t._v("unicode 是一种字符编码,让每个字符和一个数字对应起来,仅此而已,至于这个数字如何存储它就不管了。utf8 就是定义了如何具体存储这个编码数字的一种方法")])]),t._v(" "),s("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),s("ul",[s("li",[t._v("https://zhuanlan.zhihu.com/p/145220416")]),t._v(" "),s("li",[t._v("http://www.manongjc.com/article/50416.html")]),t._v(" "),s("li",[t._v("http://c.biancheng.net/view/18.html")]),t._v(" "),s("li",[t._v("https://zhuanlan.zhihu.com/p/353013671")]),t._v(" "),s("li",[t._v("https://developer.aliyun.com/article/673258")])])])}),[],!1,null,null,null);n.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/90.dedfc540.js b/assets/js/90.dedfc540.js new file mode 100644 index 000000000..217b2ecda --- /dev/null +++ b/assets/js/90.dedfc540.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[90],{520:function(t,s,n){"use strict";n.r(s);var e=n(36),i=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"sonic"}},[this._v("sonic")]),this._v(" "),s("blockquote",[s("p",[this._v("https://github.com/bytedance/sonic")])])])}),[],!1,null,null,null);s.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/91.dbd4ca9b.js b/assets/js/91.dbd4ca9b.js new file mode 100644 index 000000000..1487d3c81 --- /dev/null +++ b/assets/js/91.dbd4ca9b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[91],{521:function(t,s,i){"use strict";i.r(s);var e=i(36),n=Object(e.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"动态调试"}},[this._v("动态调试")]),this._v(" "),s("h2",{attrs:{id:"资料"}},[this._v("资料")]),this._v(" "),s("ul",[s("li",[this._v("https://mp.weixin.qq.com/s/qfukFmJRcBAjn-e2K73VLQ")])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/92.61c0947f.js b/assets/js/92.61c0947f.js new file mode 100644 index 000000000..9166a683f --- /dev/null +++ b/assets/js/92.61c0947f.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[92],{524:function(t,s,a){"use strict";a.r(s);var n=a(36),e=Object(n.a)({},(function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h1",{attrs:{id:"go-包管理工具"}},[t._v("go 包管理工具")]),t._v(" "),a("ul",[a("li",[t._v("go 导包的过程")]),t._v(" "),a("li",[t._v("go 包的版本管理")]),t._v(" "),a("li",[t._v("go 包的最小版本原则")]),t._v(" "),a("li",[t._v("go module 命令的使用\n"),a("ul",[a("li",[t._v("go get / go install")]),t._v(" "),a("li",[t._v("GOPROXY")]),t._v(" "),a("li",[t._v("GOSUMDB")]),t._v(" "),a("li",[t._v("go 使用私有服务器")]),t._v(" "),a("li",[t._v("workspace")])])])]),t._v(" "),a("h2",{attrs:{id:"go-语言的包导入过程"}},[t._v("go 语言的包导入过程")]),t._v(" "),a("ul",[a("li",[t._v("go 编译快的原因")]),t._v(" "),a("li",[t._v("go 程序的构建过程")])]),t._v(" "),a("p",[t._v("go 程序编译快的原因。1 是因为 go 要求每一个包都必须显式的标记处引入的包。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" hi\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"io"')]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/shgopher/hui"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("所以编译器无需去查找这个文件中具体引入了哪些包就可以在头部检索出全部的导包名单")]),t._v(" "),a("p",[t._v("2 是因为 go 语言不允许循环引用,比如说 a 引用了 b,b 又引入了 a,所以每一个包都是独立的存在,处于 “有向无环图 “这种格式下,进而可以并行去编译不同的包,提高编译效率。")]),t._v(" "),a("p",[t._v("3 包编译的结果里 ("),a("code",[t._v("xx.o")]),t._v(","),a("code",[t._v("xx.a")]),t._v(") 中不仅存储了此包的导出信息,还存储了它引入的包的导出信息,这样编译器只需要读取一个目标文件就可以获取全部的包信息,不需要读取全部的文件。比如 p 包要引入 q 包,那么 q 包的。a 文件已经包括了它引入的全部包的导出信息,这样编译器可以快速统计某一个包被引用的情况,比如包引用了 a b,a b 分别引用了 c 但是版本不同,那么这种情况下因为主包已经了解了他们的情况,所以就可以用最小版本原则去选择一个版本的包进行编译即可。有点类似分封制,我帝王 p 包,我的直接负责人是诸侯 q,q 掌握了它下级 s 的所有数据,假设 s 还有下级,s 掌握了 w 的所有数据,然后层层回报,当帝王 p 最终编译的时候,它已经完全拥有了所有的数据,可以精准调控。再结合每一个包都可以独立的并行编译")]),t._v(" "),a("p",[t._v("所以这一整套下来 go 的编译速度就会很快。并且在 go.mod 文件中也会详细记录使用过的包及其版本,那么并行下载,快速编译就不是梦了。")]),t._v(" "),a("h2",{attrs:{id:"go-程序的构建过程。"}},[t._v("go 程序的构建过程。")]),t._v(" "),a("p",[t._v("go 程序的建立是由编译和链接两个阶段组成的,举个例子\n有一个项目拥有一个 main 包,一个 lib 包,lib 包会被引入到 main 包中,那么编译的过程是这样的,首先创建一个临时工作区域,编译 lib 包为 lib.a,编译 main 包为 main.a,链接器将 lib.a 和 main.a 链接成 name.out,然后改名为 name (unix-like),"),a("strong",[t._v("使用第三方包的意思就是链接了该包的源代码编译的最新的。a 文件而已")]),t._v(",并且"),a("strong",[t._v("每次编译")]),t._v("都会重新编译最新的。a 文件 (所以只保留。a 文件,删除源码是不可行的),但是标准库除外,并不会每次编译都会重新编译标准库,所以说如果你修改了源码一定得把标准库。a 文件删除,并且 build 的时候使用 "),a("code",[t._v("build -a")]),t._v(" 的方式才可以使用自己更新的标准库。")]),t._v(" "),a("p",[t._v("一个小 tip:go 导包的时候引入的是路径名称,路径名称"),a("strong",[t._v("通常")]),t._v("最后一位路径名称跟包名保持一致,当然也可以不一致。例如 "),a("code",[t._v("github.com/shgopher/go-hui")]),t._v(" 但是实际上包名称是这个 "),a("code",[t._v("package hui")]),t._v(",所以导入的时候按照 "),a("code",[t._v("github.com/shgopher/go-hui")]),t._v(",使用的时候用 "),a("code",[t._v("hui.xxx()")]),t._v("。")]),t._v(" "),a("p",[t._v("因为包的名称很容易发生冲突,所以 go 接受包名称的重命名")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\n app "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/shgopher/app"')]),t._v("\n app1 "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/googege/app"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("除此之外还有 "),a("code",[t._v("_")]),t._v(" 方式,它会"),a("strong",[t._v("计算包级变量的初始化表达式")]),t._v("和"),a("strong",[t._v("执行导入包的 init 初始化函数")]),t._v(",意思就是跟 init 函数有关的内容都会被计算,并且导入进去。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image/jpeg"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"image/png"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"io"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"os"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toJPEG")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Stdin"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Stdout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fprintf")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Stderr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"jpeg: %v\\n"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t\tos"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Exit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toJPEG")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Reader"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" out io"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Writer"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("error")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\timg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" kind"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" image"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Decode")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("in"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" err "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("nil")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" err\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Fprintln")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("os"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Stderr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Input format ="')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" kind"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" jpeg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Encode")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("out"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" img"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("jpeg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Options"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("Quality"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("95")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("比如这个例子,image.Decode 会查询注册表,看看注册表里都有谁,这个时候我们引入的 _ iumage/png 的 init 函数就是将 png 中实现了接口的具体数据导入到了注册表中,所以说这里只需要导入这个 init 函数即可。")]),t._v(" "),a("p",[t._v("这种用法还是比较重要的,我们来自己编写一段代码,来看看实现这种注册器的基本原理:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里是实现这个注册器")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" go2\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 在某个包实现go2的时候,这里是go3,这个drivers就被初始化了。")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" drivers "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("make")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("map")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("Driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" Driver "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("interface")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" driver Driver"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tdrivers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" driver\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("DDD")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("name "),a("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("string")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" d Driver\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" d1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" ok "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" drivers"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("name"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("ok "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("panic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"no real driver registered"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\td "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" d1\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\td"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这里是实际的实现我们注册器那个包实现的抽象方法")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" go3\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"shgopher.com/go2"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("type")]),t._v(" ddd "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("struct")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("d "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("ddd"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Open")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tfmt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"this is go3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("init")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\tgo2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("Register")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"go3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("ddd"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 最后我们来使用一下:")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"shgopher.com/go2"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"shgopher.com/go3"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n\tgo2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("DDD")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"go3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("另外还有一种导入包的奇妙用法,就是")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fmt"')]),t._v("\n\n\t"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("func")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t\t"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("println")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"hi"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("它的意思是省略包名,no!,请不要这么用。")]),t._v(" "),a("h2",{attrs:{id:"go-module-构建工具"}},[t._v("go module 构建工具")]),t._v(" "),a("ul",[a("li",[t._v("go111MODULE")]),t._v(" "),a("li",[t._v("GOPROXY")]),t._v(" "),a("li",[t._v("GOSUMDB")]),t._v(" "),a("li",[t._v("module 版本的升级")]),t._v(" "),a("li",[t._v("workspace")])]),t._v(" "),a("p",[t._v("go 自带包管理工具 go module,本文章写作时 go 的版本是 1.19,所以过去的 go path,go vendor,go dep 均不再提及,读者也不用去 care,鉴于干谈 go module 非常的枯燥,我设立一个例子来讲述 go module。")]),t._v(" "),a("p",[t._v("在桌面,我们使用 go module 的创建命令")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" ~/Desktop\n\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("mkdir")]),t._v(" hello\n\ngo mod init github.com/shgopher/hello \n\n")])])]),a("p",[t._v("创立了一个以 hello 作为包名称的包。这里我们使用 "),a("code",[t._v("github.com/shgopher/hello")]),t._v(" 是证明这个包使用 GitHub 进行存储,因为 go 使用 git 来管理版本,在项目内部,这个项目的包名称就是最后一个名称,hello 才是这个包的正式名称,此处是惯用,实际上真实管理包正式名称的是每一个文件上的 package xx 管理的,整个就是路径而已,不过习惯于最后一个路径名称为包的名称,即:最后一个名称 == package 后面的 xxx。")]),t._v(" "),a("p",[t._v("然后我们在这个项目的 root 路径下会发现 go 帮我们创建了一个 go.mod 的文件,它就是 go module 的版本文件,我们拿一个 go.mod 来作为举例")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 一个 go.mod 目录:")]),t._v("\n\nmodule github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("shgopher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("hello\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.19")]),t._v("\n\n\nrequire "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("apache"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("thrift v0"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("13.0")]),t._v("\n github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("bytedance"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("gopkg v0"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("20220531084716")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("665b4f21126f\n github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("appleboy"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("gin"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("jwt"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("v2 v2"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("6.4")]),t._v("\n gopkg"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("in"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("yaml"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("v3 v3"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.1")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nrequire "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\n\tgithub"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("beorn7"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("perks v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.1")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// indirect")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\nreplace "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 后面指向的要么是相对路径例如 ../shgopher/.com/net")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 要么一定要在后面加上版本,并且是可以获取到的包")]),t._v("\n\tgolang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("x"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("net v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.2")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" shgopher"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("net v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.5")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),a("p",[t._v("我们一个一个解释,首先最开头的是这个包的路径名称,实际上 go 会使用 "),a("code",[t._v("git clone https://github.com/shgopher/hello.git")]),t._v(" 的方式下载包,当然,假设你不使用 GitHub 的 git 作为项目的存储位置,使用自建的也是 OK 的,比如 "),a("code",[t._v("module shgopher.com/hello")]),t._v(" 只要同样配置了 git 服务器都可以,因为底层都是使用的 "),a("code",[t._v("git clone https://xxx.com/xx.git")]),t._v(" 模式。")]),t._v(" "),a("p",[t._v("接下来的 "),a("code",[t._v("go 1.19")]),t._v(" 是这个项目使用的 go 的大版本,比如你使用的是 "),a("code",[t._v("1.19.1")]),t._v(","),a("code",[t._v("1.19.2")]),t._v(",上面写的都是 "),a("code",[t._v("go 1.19")]),t._v(",比如你使用 "),a("code",[t._v("go mod edit -go=1.19")]),t._v(" 来更新此项目使用的 go 版本的时候,只能写到 minor,而不能加上 patch (minor 和 patch 下文有说)。")]),t._v(" "),a("p",[t._v("接下里有两个 require,其中第一个 require 指的是直接引入的包,后面的 require 是间接引用的包。意思就是你引用的包,它引入的包。")]),t._v(" "),a("p",[t._v("第一个 require 中,我给出了四种常见的版本用法")]),t._v(" "),a("ol",[a("li",[t._v("使用 git version 命名的版本 "),a("code",[t._v("v0.13.0")])]),t._v(" "),a("li",[t._v("项目没有使用 version 命名,go 官方使用最新的文件,并且给予了它一个临时的版本号 "),a("code",[t._v("v0.0.0-20220531084716-665b4f21126f")])]),t._v(" "),a("li",[t._v("当项目的版本超过 1.x 的时候,go 推荐使用再加上一个/v2 的方式进行命名,但是实际上它的包名称仍然是 gin-jwt,并且 1.x 和 2.x 的包可以同时引入项目中,因为他们算两个包,只需要重命名即可。版本 2 和版本 1 的 module 后面写的也不一样,比如一个是 "),a("code",[t._v("module github.com/shgopher/collie")]),t._v(" 版本 2 就是 "),a("code",[t._v("module github.com/shgopher/collie/v2")]),t._v(" 不过虽然最后结尾的是 v2 但是 package 后面写的仍然是 collie")]),t._v(" "),a("li",[t._v("也可以使用 yaml.v3 的方式进行命名,因为路径名称并不是包的名称,所以这种方式也有不少项目使用")])]),t._v(" "),a("p",[t._v("第二个 require,全部都是间接引用的包名称,go 也会一并下载到本地缓存,go 会使用 "),a("code",[t._v("~/go/pkg/mod/包名称@版本号")]),t._v(" 的地方去保存下载下来的包。")]),t._v(" "),a("p",[t._v("使用 "),a("code",[t._v("go list -m -json all")]),t._v(" 命令可以查看当前项目的所有依赖的包名称,例如")]),t._v(" "),a("div",{staticClass:"language-json extra-class"},[a("pre",{pre:!0,attrs:{class:"language-json"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Path"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/marmotedu/iam"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Main"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Dir"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/Users/shgopher/Desktop/github-projects/iam"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"GoMod"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/Users/shgopher/Desktop/github-projects/iam/go.mod"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"GoVersion"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.18"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Path"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"cloud.google.com/go"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Version"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"v0.93.3"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Time"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2021-08-17T22:38:11Z"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Indirect"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"GoMod"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/Users/shgopher/go/pkg/mod/cache/download/cloud.google.com/go/@v/v0.93.3.mod"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"GoVersion"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.11"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Path"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/marmotedu/component-base"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Version"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"v1.6.2"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"Time"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2021-12-21T06:47:41Z"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"GoMod"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/Users/shgopher/go/pkg/mod/cache/download/github.com/marmotedu/component-base/@v/v1.6.2.mod"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token property"}},[t._v('"GoVersion"')]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"1.17"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("我们重点关注几个字段,首先第一个对象中,"),a("code",[t._v('"Main":true')]),t._v(",表示这个对象描述的包属于主包,即,这个项目的 root 路径下的 "),a("code",[t._v("go.mod")]),t._v(";第二个对象中,我们看到 "),a("code",[t._v('"Indirect": true,')]),t._v(" 意思就是指这个包是间接引入的包,第三个对象里,并没有出现 indirect 的字段,就证明这个包是直接引入的。因为这个列举的主要是 go.mod 的目录,又因为拥有一个 go.mod 的包拥有同样的版本号,所以包和包的子包是公用一个 go.mod 的,只会出现一次。")]),t._v(" "),a("h3",{attrs:{id:"如何控制-go-引入的包的版本号。"}},[t._v("如何控制 go 引入的包的版本号。")]),t._v(" "),a("p",[t._v("当我们更新一个旧的项目中的依赖时,我们可以使用 "),a("code",[t._v("go clean -modcache")]),t._v(" 的命令去删除 go 缓存的 go 包。然后显式的为包设置版本,第一种方法是直接在 go.mod 写入要引入的包的版本,第二种方法是使用 "),a("code",[t._v("go mod -require=github.com/shgopher/hello@v0.1.1")]),t._v(" 的方式写入你想要的包的版本,除了第二种这种比较精确的方式,go mod 还支持 query 的方式去指定范围,例如说 "),a("code",[t._v("go mod -require=github.com/shgopher/hello@>=v0.1.1")]),t._v("。")]),t._v(" "),a("p",[t._v("go 包采用 “最小版本” 选择的理念。举个例子,我的项目 hello,直接引入了 c 包和 d 包,然后 c 和 d 又分别引入了 e 包,那么最后本项目使用的 c,d,e 包采用的是哪个版本呢?")]),t._v(" "),a("p",[t._v("我们详细说明一下,假设我们使用的 cde 都是@latest,那么每次 build 的时候,都会去下载最新的包;如果我们使用了具体的版本,假设我们在 go.mod 中给定的 c d 分别是 v0.1.0 v1.0.1 但是呢,c 存在多个版本,比如现在有 v0.1.1 v0.2.1 那么根据最小版本的选择问题,go 会选择一个符合 v0.1.0 的最小版本,即:>=v0.1.0,所以此处会选用 v0.1.1,也就是说 go 的版本的隐藏含义是大于等于选最小,很多别的语言都是大于等于选最大,例如 rust,但是强调一下,"),a("strong",[t._v("这个大于等于选最大或者最小说的是一个版本的情况下,超过版本号的时候,算俩包 (例如 v1.1.0 和 v2.1.0 就算俩大版本了,所以说他们是俩包都不为过)")]),t._v(",而且我们在改变版本的时候应该先把缓存给清除了 "),a("code",[t._v("go clean -modcache")]),t._v(",接下来我们的 cd 包分别引入了 e 包,假如 e 存在 v1.1.0 v1.2.0 v1.3.0 v1.4.0,c d 分别引入的是 v1.1.0 v1.3.0 那么 go 会"),a("strong",[t._v("合并需求 (只引入包众多版本的一个版本)")]),t._v(",并且依然采用最小版本的方式即:最终只选用 e 包的 v1.3.0 这一个版本的包引入,总结一下:单个包,使用 >= 的最小值引入,多个包引入同一个包的情况,使用满足他们共同条件下的最小值。")]),t._v(" "),a("p",[t._v("使用 go mod tidy 可以对这个项目的包进行梳理,比如使用 latest 的包会重新比对,然后下载最新版本的包,比如在 require 中明确引入的包,但是在实际上线前发现没有继续使用这个包了,那么使用 go mod tidy 也可以删除这个包,这个命令类似于 “刷新” 这个概念。")]),t._v(" "),a("h3",{attrs:{id:"如何优雅的升级和降级引入的包版本"}},[t._v("如何优雅的升级和降级引入的包版本?")]),t._v(" "),a("p",[t._v("我们会用到下面两个命令")]),t._v(" "),a("ul",[a("li",[t._v("go list")]),t._v(" "),a("li",[t._v("go get")])]),t._v(" "),a("p",[t._v("首先,我们使用 "),a("code",[t._v("go list -m -versions github.com/shgopher/hello")]),t._v(" 的命令查找这个包的众多版本 (没有使用 git 给定版本的就没办法了,给定@latest,直接用最新的了),例如说会有 v1.1.0 v1.2.0,假设我们本来用的是 v1.1.0 想升级一下,我们使用 "),a("code",[t._v("go get github.com/shgopher/hello@v1.2.0")]),t._v(" 即可优雅的升级这个包的版本,当然降级也是一样的,反正指定一个包即可,要注意的是,go 在升级或者降级的时候,会自动将间接使用的包也做出相应的版本调整。假如我们现在想把所有的依赖包升级为这个版本下的最新包,使用 "),a("code",[t._v("go get -u")]),t._v(" 就可以更新所有的直接依赖和间接依赖的包为最新包。如果只想升级 patch 而不是 minor (v1.2.0;1 是 version,2 是 minor,3 是 patch) 使用 "),a("code",[t._v("go get -u=patch")]),t._v(",如果只想升级某一个包 (及其依赖包) 到最新版本,在后面指出来具体的包名称即可,"),a("code",[t._v("go get -u github.com/shgopher/hello")]),t._v("。")]),t._v(" "),a("p",[t._v("go install 和 go get 是两个比较像的命令,其中 go get 仅仅用在 go module 中调整版本的时候,比如升级,降级,go install 用于下载包,两者都是一样的,如果包的后面带上版本那么就是指定版本,如果不带就是最新版本。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" install github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("shgopher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("hello \n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" install github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("shgopher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("hello@v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.2")]),t._v("\n")])])]),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" get "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("u github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("shgopher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("hello\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" get github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("shgopher"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("hello@v1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.4")]),t._v("\n")])])]),a("p",[t._v("在使用 go install 的时候其实是忽略 go.mod 的,所以 go install 跟 go.mod 没有任何关系,也不会记录 go.mod 中,它的作用就是下载包,go get 跟 go.mod 紧密相关,它需要 go.mod,并且每次更改都会记录在 go.mod 中,当你在一个没有 go.mod 的路径下 (指的是此路径,此路径的父路径也没有) 使用 go get 会提示如下错误")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("mod file not found in current directory or any parent directory"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token char"}},[t._v("'go get'")]),t._v(" is no longer supported outside a module"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n\tTo build and install a command"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" use "),a("span",{pre:!0,attrs:{class:"token char"}},[t._v("'go install'")]),t._v(" with a version"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\tlike '"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" install example"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("cmd@latest'\n\tFor more information"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" see https"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("golang"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("org"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("doc"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("get"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("install"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("deprecation\n\tor run '"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" help get"),a("span",{pre:!0,attrs:{class:"token char"}},[t._v("' or '")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),t._v(" help install'"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n")])])]),a("p",[t._v("所以这个时候应该使用的是 go install。")]),t._v(" "),a("h3",{attrs:{id:"引入的-go-包-git-更改名称了怎么办"}},[t._v("引入的 go 包 git 更改名称了怎么办?")]),t._v(" "),a("p",[t._v("Go 语言提出了一个模块代号 (Module Path) 的概念来解决这个问题。")]),t._v(" "),a("p",[t._v("简单来说,模块代号就是一个模块的唯一标识,即使模块仓库的路径名改变了,但其模块代号不变。")]),t._v(" "),a("p",[t._v("例如一个模块:")]),t._v(" "),a("p",[t._v("模块路径:"),a("code",[t._v("github.com/user/project")]),t._v("\n模块代号:"),a("code",[t._v("github.com/user/project")]),t._v("\n如果模块 rename 后路径变成了 "),a("code",[t._v("github.com/newUser/newProj")]),t._v(",但模块代号不变:")]),t._v(" "),a("p",[t._v("模块新路径:"),a("code",[t._v("github.com/newUser/newProj")]),t._v("\n模块代号:"),a("code",[t._v("github.com/user/project")]),t._v("\n这样通过模块代号,其他依赖它的模块导入语句就不用修改了,还是导入老的模块代号,但实际上会去新路径下找。")]),t._v(" "),a("p",[t._v("在发布新版本代码时,只需要在 go.mod 文件中声明:")]),t._v(" "),a("p",[a("code",[t._v("module github.com/user/project")])]),t._v(" "),a("p",[t._v("就可以确保模块代号不变,其他依赖不受影响。")]),t._v(" "),a("p",[t._v("所以 Go 语言通过模块代号很好地解决了模块路径变更的问题,最大程度保证了导入的稳定性。")]),t._v(" "),a("h3",{attrs:{id:"go-包代理"}},[t._v("go 包代理")]),t._v(" "),a("p",[t._v("GOPROXY 是 go 的代理服务器。go 之前使用 GitHub,gitlab 等托管平台,goproxy 命令可以设置一个集中式的代理服务,比如")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("export")]),t._v(" GOPROXY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" https://goproxy.cn,direct \n\n"),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("export")]),t._v(" GOPROXY "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" https://proxy.golang.org,direct\n\n")])])]),a("p",[t._v("其中前者是国内常用的代理服务器,后者是 go 官方的代理服务器;"),a("code",[t._v("direct")]),t._v(" 的意思是,"),a("strong",[t._v("直接")]),t._v("使用代理服务器的内容,"),a("code",[t._v(",")]),t._v(" 的意思是前面的服务器"),a("strong",[t._v("只有")]),t._v("出现 404 和 410 错误的时候才会去选择逗号后面的服务,如果想设置只要发生错误就使用后者的命令,那么可以使用 "),a("code",[t._v("|")]),t._v(",例如使用")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("go "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" -w "),a("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("GOPROXY")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("https://proxy.golang.org"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("https://goproxy.cn"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("direct`\n")])])]),a("p",[t._v("这里有个小知识,因为 "),a("code",[t._v("|")]),t._v(" 在 unix-like 操作系统中通常还表示通道的含义,就是前面的输出等于后面的输入,所以我们需要将这个符号进行转义才能正常使用:")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("go "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("env")]),t._v(" -w "),a("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("GOPROXY")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("https://proxy.golang.org"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("https://goproxy.cn"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("\\")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v("direct\n\n")])])]),a("p",[t._v("go module 还有 go.sum 这个文件,它存储的是包的一些基础信息,最重要的是对于一个包求 hash 值,记录这个 hash,在每次 build 的时候对于缓存的包和 go.sum 中的 hash 值做对比,来规避恶意更改,go.sum 会在项目的更新换代过程中保存多个版本的包信息。")]),t._v(" "),a("p",[t._v("GOSUMDB 命令指向的服务就是保存公有包的校验和的数据库。一个新的包,在一切运行正确的情况下,go 会通过 GOSUMDB 配置的数据库去查询这个包的校验和,查询出结果后和下载的包进行比对,正确的情况下存入 go.sum;如果一个已经缓存的包,每次 run build 的时候都会将缓存的包文件校验跟 go.sum 进行比对来保证正确性。")]),t._v(" "),a("p",[t._v("当然,如果你不想使用 GOSUMDB,使用 "),a("code",[t._v("go env -w GOSUMDB=off")]),t._v(" 即可。这样就无法对比包和数据库中的校验和,只能做本地校验了。")]),t._v(" "),a("h3",{attrs:{id:"如何使用一个私有包"}},[t._v("如何使用一个私有包")]),t._v(" "),a("p",[t._v("我们讲解了如果配置公有的代理服务器 GOPROXY,文件校验和数据库 GOSUMDB,接下来我们谈一下如果我们想使用一个私有的包,比如一个 GitHub 上的私有包,一个本地 git 服务器上的包,我们使用 GOPRIVATE,它的目的就是绕过 GOPROXY 和 GOSUMDB,因为是私有的所以在代理服务器和文件校验和数据库都不会有它的记录,我们可以这么设置")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 意思是这个路径下的所有包都不会经过代理服务器了。")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 这个命令支持多个路径使用逗号分隔")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("export")]),t._v(" GOPRIVATE "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" shgopher.com,shgopher.io,*.api.shgopher.com\n")])])]),a("p",[t._v("除了设置这个命令之外,还需要设置一个密钥用来 ssh 的方式去访问 GitHub 上的私有仓库,或者是 GitHub --- personal access tokens")]),t._v(" "),a("p",[t._v("使用 ssh,将主机公钥 (~/.ssh/id_rsa.pub) 添加到 github.com 的 ssh keys 中。")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#我们谈一下如果生成公钥:")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("## 在~/.ssh/ 路径下")]),t._v("\n\tssh-keygen -t rsa -C "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"个人邮箱"')]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("## 将这个id_rsa.pub中的公钥 添加到GitHub中的ssh keys 中")]),t._v("\n")])])]),a("p",[t._v("如果使用 ssh 的方式获取代码,那么在~/.gitconfig 中添加 (这一步其实就是一个映射:保持你的日常习惯的情况下,使用了 ssh)")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("url "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ssh://git@github.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tinsteadOf "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" https://github.com\n")])])]),a("p",[t._v("如果是本地服务器那么就是")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("url "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ssh://git@local.com"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tinsteadOf "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" https://git.local.com\n")])])]),a("p",[t._v("不过要注意一下,如果使用 ssh 那么远程的服务就得变更名称,因为通常我们的 GitHub 给我们的都是 https 的方式,使用 ssh 的话就是:")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("git")]),t._v(" remote set-url origin git@github.com:USERNAME/REPOSITORY.git\n")])])]),a("p",[t._v("从 ssh 更改为 https 就是")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("git remote set"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("-")]),t._v("url origin https"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("github"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("com"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("USERNAME"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("REPOSITORY"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("git\n")])])]),a("p",[t._v("使用 GitHub personal access token 的方式")]),t._v(" "),a("div",{staticClass:"language-bash extra-class"},[a("pre",{pre:!0,attrs:{class:"language-bash"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# 在GitHub personal access tokens中申请即可,然后配置在~/.netrc")]),t._v("\n\nmachine github.com login shgopher password 你的 personal access tokens\n")])])]),a("p",[t._v("在 Linux 中要配置~/.netrc,但在 macOS 中,git 输入的 username 和令牌会自动的缓存,不用设置这个配置文件。")]),t._v(" "),a("p",[t._v("更多关于 GitHub 访问的信息可以访问"),a("a",{attrs:{href:"https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories#switching-remote-urls-from-ssh-to-https",target:"_blank",rel:"noopener noreferrer"}},[t._v("这里"),a("OutboundLink")],1)]),t._v(" "),a("p",[t._v("我个人建议直接使用 GitHub 的 personal access tokens (仅支持 https) 这种令牌的方式代替密码,并且使用 https 即可,简单,安全,好用,\n另外如果你的令牌更新了,假设是 Macos 的情况下,可以去钥匙串访问的互联网密码种类中去更新令牌")]),t._v(" "),a("p",[t._v("如果我们引入的包是不支持 https 协议的,那么我们可以设置 "),a("code",[t._v("GOINSECURE = private.res.com")]),t._v(" 来使用这种私有库。")]),t._v(" "),a("p",[t._v("go 仅仅支持 https 和 http 标准端口的带有域名的包,比如我们使用 ip,或者端口不是 80 和 443,那么设置 GOPROXY 和 GOPRIVATE GOINSECURE 都没用了。")]),t._v(" "),a("p",[t._v("比如类似这种:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 这种无法使用")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("192.168")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v(".1")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v(".1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("9090")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("test"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("t\n")])])]),a("p",[t._v("这种直接使用 ip 的方式不能写到 go 的代码中,所以我们可以使用 git 的 insteadof 功能来改变一下,使用一个正常的 url 去改变掉这个 ip")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[t._v("# ~"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("gitconfig\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("url "),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"132.148.1.1:9090/test/t"')]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\tinsteadof"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"shgopher.com/test/t"')]),t._v("\n")])])]),a("p",[t._v("这个时候你引入的时候写 shgopher.com/test/t 就可以了,它会自己找 192.168.1.1:9090/test/t 真实值去代理,并且 shgopher.com/test/t 也要加入到 GOPRIVATE 中才可以。")]),t._v(" "),a("p",[t._v("这个时候有个问题,就是如果 shgopher.com 没有配置版本管理软件,例如 git 这种,go 是无法获取数据的,go 一般会存储一些网站,例如 GitHub,gitlab,所以它看到类似 github.com/xxx/的地址就去找使用 git,或者你手动写上 git,比如 shgopher/d/x.git go 也会明白你使用的 git,go 还能发送请求的方式去获取你使用的版本软件,比如 golang.org/x/net go 就会请求 https://golang.org/x/net?go-get=1 这个服务提供了一个 html:")]),t._v(" "),a("div",{staticClass:"language-html extra-class"},[a("pre",{pre:!0,attrs:{class:"language-html"}},[a("code",[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),t._v("head")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),t._v("meta")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token attr-value"}},[a("span",{pre:!0,attrs:{class:"token punctuation attr-equals"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')]),t._v("go-import"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("content")]),a("span",{pre:!0,attrs:{class:"token attr-value"}},[a("span",{pre:!0,attrs:{class:"token punctuation attr-equals"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')]),t._v("golang/x/net git https://go.googlesource.com/net"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),t._v("meta")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("name")]),a("span",{pre:!0,attrs:{class:"token attr-value"}},[a("span",{pre:!0,attrs:{class:"token punctuation attr-equals"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')]),t._v("go-source"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token attr-name"}},[t._v("content")]),a("span",{pre:!0,attrs:{class:"token attr-value"}},[a("span",{pre:!0,attrs:{class:"token punctuation attr-equals"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')]),t._v("golang.org/x/net https://github.com/golang/net"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token tag"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),t._v("head")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v("\n")])])]),a("p",[t._v("这表示这个 golang.org/x/net 的包实际是通过 git 的方式从 https://go.googlesource.com/net 获取的。")]),t._v(" "),a("p",[t._v("我们可以让 "),a("code",[t._v("GET shgopher.com?go-get=1")]),t._v(" 返回一个 html,在里面设置为 content=“shgopher.com/test/t git 132.148.1.1:9090/test/t”。")]),t._v(" "),a("p",[t._v("其实,老老实实的使用 go 推荐的导包方式挺好的,即便是私有包也好好的安排一个 git 版本服务器,仅限内部使用的话,配置好 GOPRIVATE 并且使用 ssh 公钥和私钥或者 GPG 的方式加密获取包,这种才是王道。")]),t._v(" "),a("p",[t._v("配置私有的 GOPROXY,你不能总想着靠别人,如果想搭建一个属于自己的 goproxy 服务器,那么可以使用 https://github.com/goproxy/goproxy 这个项目")]),t._v(" "),a("h3",{attrs:{id:"本地开发使用的配置文件-go-work"}},[t._v("本地开发使用的配置文件 go.work")]),t._v(" "),a("p",[t._v("go 推出了仅用于本地开发的 workspace,我们来介绍一下这个功能,比如说我们要在一个项目中你引入一个还未公开到公共仓库的包 github.com/shgopher/hui,那么在这个时候就需要 workspace 了。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("package")]),t._v(" main\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"github.com/shgopher/hui"')]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("很显然这个包还未发布,所以不可能引入,在之前通常使用 replace 的方式,但是有了 workspace 以后,不到特定的场景就不需要使用 replace,比如尚未发布的包这种场景用 workspace 最好用 (包的子包不需要任何设置,就可以主包直接引入这个子包了,这一点要搞清楚)。")]),t._v(" "),a("p",[t._v("使用 go work init 来创建一个工作区,go.work 形如:")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//go.work")]),t._v("\ngo1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("19")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("use")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("//go.work当前路径是可以省略的")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("Users"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("ddd"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("src"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("go")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("hui\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),a("p",[t._v("go.work 可以设置在需要工作区的路径的父路径 (如果父路径没有就会一直忘外寻找直到根路径),工作区中的命令会向外部去寻找 go.work,所以我们通常可以在需要 workspace 的地方的父路行下设置 go.work,并且设置为绝对路径这样简单高效,记住,路径是不包含子路径的,比如本来是/workspace/go1 但是你设置的是/workspace 那么就是错的,它会寻找/workspace 中有没有 go.mod 它以 go.mod 作为寻找对象。当然了一个包的子包 (例如/workspace/go1/a) 无需再写进去 go.work 中,它跟外部的包是一个包。")]),t._v(" "),a("div",{staticClass:"language-go extra-class"},[a("pre",{pre:!0,attrs:{class:"language-go"}},[a("code",[a("span",{pre:!0,attrs:{class:"token function"}},[t._v("use")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("workspace"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("a\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("workspace"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("b\n\t"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("workspace"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("/")]),t._v("c\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),a("p",[t._v("在工作区同样可以设置 replace,但是级别没有 go.mod 中的高,会被 go.mod 覆盖。")]),t._v(" "),a("p",[t._v("go 的包和包的管理工具 go module 基本上已经讲解完毕了,以后有了新的见解再更新这篇文章。")]),t._v(" "),a("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),a("ul",[a("li",[t._v("https://go.dev/blog/get-familiar-with-workspaces")]),t._v(" "),a("li",[t._v("https://book.douban.com/subject/35720728/ 图书下册 321 页 - 349 页;图书上册 120 页 - 131 页")])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/93.eaa3fe92.js b/assets/js/93.eaa3fe92.js new file mode 100644 index 000000000..1f802678c --- /dev/null +++ b/assets/js/93.eaa3fe92.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[93],{522:function(t,s,e){"use strict";e.r(s);var n=e(36),r=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"反射包的使用"}},[this._v("反射包的使用")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/94.c3c51d69.js b/assets/js/94.c3c51d69.js new file mode 100644 index 000000000..f392d89f1 --- /dev/null +++ b/assets/js/94.c3c51d69.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[94],{523:function(t,o,s){"use strict";s.r(o);var v=s(36),a=Object(v.a)({},(function(){var t=this,o=t.$createElement,s=t._self._c||o;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"命令"}},[t._v("命令")]),t._v(" "),s("p",[t._v("go 拥有众多命令操作,这里将讲述关于这些命令的使用方法")]),t._v(" "),s("p",[t._v("介绍一下最常见的命令")]),t._v(" "),s("ul",[s("li",[t._v("go help 显示一个命令基本的用法,例如:"),s("code",[t._v("go help fmt")])]),t._v(" "),s("li",[t._v("go doc 显示一个命令全部的用法,例如:"),s("code",[t._v("go doc cmd/gofmt")])])]),t._v(" "),s("p",[t._v("使用 go help 可以显示全部的形如 "),s("code",[t._v("go fmt")]),t._v(" "),s("code",[t._v("go build")]),t._v(" 这种挂靠在 go 后面的命令,然后 help 加具体的命令,就可以显示基本用法,然后在 help 提示的内容中,通常会有提示你,如果使用 go doc 命令去寻找更加详细的内容,比如下文要写到的,使用 "),s("code",[t._v("go help fmt")]),t._v(" 就会显示去寻找 "),s("code",[t._v("go doc cmd/gofmt")])]),t._v(" "),s("h2",{attrs:{id:"gofmt"}},[t._v("gofmt")]),t._v(" "),s("blockquote",[s("p",[t._v("go fmt 命令简单封装了 gofmt 命令")])]),t._v(" "),s("p",[t._v("gofmt 的目的是标准化 go 语言的代码,增加代码的亲切感,消除不同人员写的代码的之间的隔阂感")]),t._v(" "),s("p",[t._v("介绍几个常见的使用方法,详细内容可以使用 "),s("code",[t._v("go doc cmd/gofmt")])]),t._v(" "),s("ul",[s("li",[s("p",[s("code",[t._v("gofmt -s")]),t._v(" 简化代码")]),t._v(" "),s("div",{staticClass:"language-go extra-class"},[s("pre",{pre:!0,attrs:{class:"language-go"}},[s("code",[t._v("v "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("int")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 复杂")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("_")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" v "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 使用 -s 后")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("range")]),t._v(" v "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("不过,这个命令虽然会显示出来要优化的简单写法,但是,并不会更改用户的代码,需要自己去更改。")])]),t._v(" "),s("li",[s("p",[s("code",[t._v("gofmt -r")]),t._v(" 代码重构 replace 能力")]),t._v(" "),s("p",[t._v("例子:"),s("code",[t._v("gofmt -r 'a -> Student'")]),t._v(" 意思可不是 a 字符改变成 Student,这里是采用的通配符,意思就是所有的英文字符都要改成 student。只要是小写字母都会被视为通配符。再举一个例子,"),s("code",[t._v("gofmt -r 'a[b:len(a)] -> a[b:]'")]),t._v(" 这里的 a 代表所有的英文字符串,b 就会代表整数类型")])]),t._v(" "),s("li",[s("p",[s("code",[t._v("gofmt -l")]),t._v(" 输出不满足 gofmt 要求的文件")]),t._v(" "),s("p",[t._v("比如 "),s("code",[t._v("gofmt -l $GOROOT")]),t._v(" 就会输出这个路径下不满足的文件列表,可以看出 go 的标准库不满足标准的也不少,😂")])])]),t._v(" "),s("h2",{attrs:{id:"goimports"}},[t._v("goimports")]),t._v(" "),s("p",[t._v("安装方法 "),s("code",[t._v("go get golang.org/x/tools/cmd/goimports")]),t._v(",一般的 IDE 都会内置这个工具,比如 goland")]),t._v(" "),s("ul",[s("li",[t._v("对于代码中使用了,但是没有 import 的包")]),t._v(" "),s("li",[t._v("对于代码中没有使用,但是 import 了的包")])]),t._v(" "),s("p",[t._v("这个工具都会一一管理,少了加上,多了取消掉")]),t._v(" "),s("h2",{attrs:{id:"go-build"}},[t._v("go build")]),t._v(" "),s("h2",{attrs:{id:"go-install"}},[t._v("go install")]),t._v(" "),s("h2",{attrs:{id:"go-get"}},[t._v("go get")]),t._v(" "),s("h2",{attrs:{id:"go-clean"}},[t._v("go clean")]),t._v(" "),s("h2",{attrs:{id:"go-doc-godoc"}},[t._v("go doc godoc")]),t._v(" "),s("h2",{attrs:{id:"go-run"}},[t._v("go run")]),t._v(" "),s("h2",{attrs:{id:"go-test"}},[t._v("go test")]),t._v(" "),s("h2",{attrs:{id:"go-list"}},[t._v("go list")]),t._v(" "),s("h2",{attrs:{id:"go-fix-go-tool-fix"}},[t._v("go fix go tool fix")]),t._v(" "),s("h2",{attrs:{id:"go-vet-go-tool-vet"}},[t._v("go vet / go tool vet")]),t._v(" "),s("h2",{attrs:{id:"go-tool-pprof"}},[t._v("go tool pprof")]),t._v(" "),s("h2",{attrs:{id:"go-tool-cgo"}},[t._v("go tool cgo")]),t._v(" "),s("h2",{attrs:{id:"go-env"}},[t._v("go env")])])}),[],!1,null,null,null);o.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/95.d1eac759.js b/assets/js/95.d1eac759.js new file mode 100644 index 000000000..bb51ca2f2 --- /dev/null +++ b/assets/js/95.d1eac759.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[95],{525:function(t,s,e){"use strict";e.r(s);var n=e(36),i=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"坑"}},[this._v("坑")]),this._v(" "),s("p",[this._v("这里记录 go 语言开发过程中,非常容易出现错误的地方。")])])}),[],!1,null,null,null);s.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/96.add14987.js b/assets/js/96.add14987.js new file mode 100644 index 000000000..f30aeb916 --- /dev/null +++ b/assets/js/96.add14987.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[96],{527:function(t,s,e){"use strict";e.r(s);var n=e(36),r=Object(n.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"字符编码"}},[this._v("字符编码")])])}),[],!1,null,null,null);s.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/97.357d16bb.js b/assets/js/97.357d16bb.js new file mode 100644 index 000000000..39cd1fd36 --- /dev/null +++ b/assets/js/97.357d16bb.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[97],{526:function(t,i,v){"use strict";v.r(i);var _=v(36),s=Object(_.a)({},(function(){var t=this,i=t.$createElement,v=t._self._c||i;return v("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[v("h1",{attrs:{id:"go-中的测试"}},[t._v("go 中的测试")]),t._v(" "),v("p",[t._v("go 中的测试一共分为如下类型")]),t._v(" "),v("ul",[v("li",[t._v("测试的主要注意事项")])]),t._v(" "),v("h2",{attrs:{id:"testing-包"}},[t._v("testing 包")]),t._v(" "),v("ul",[v("li",[t._v("基础测试")]),t._v(" "),v("li",[v("RouterLink",{attrs:{to:"/工程/测试/基准测试.html"}},[t._v("基准 (性能) 测试")])],1),t._v(" "),v("li",[t._v("例子测试")]),t._v(" "),v("li",[t._v("子测试/子基准测试")]),t._v(" "),v("li",[t._v("main 函数测试")]),t._v(" "),v("li",[v("RouterLink",{attrs:{to:"/工程/测试/模糊测试.html"}},[t._v("模糊 (fuzzing) 测试")])],1),t._v(" "),v("li",[t._v("mock")])]),t._v(" "),v("h2",{attrs:{id:"testing-fstest-包"}},[t._v("testing/fstest 包")]),t._v(" "),v("ul",[v("li",[t._v("文件系统的测试")])]),t._v(" "),v("h2",{attrs:{id:"testing-iotest-包"}},[t._v("testing/iotest 包")]),t._v(" "),v("ul",[v("li",[t._v("io 系统的测试")])]),t._v(" "),v("h2",{attrs:{id:"testing-quick-包"}},[t._v("testing/quick 包")]),t._v(" "),v("ul",[v("li",[t._v("黑箱辅助测试")])]),t._v(" "),v("h2",{attrs:{id:"net-http-test"}},[t._v("net/http/test")]),t._v(" "),v("ul",[v("li",[t._v("http 客户端测试")]),t._v(" "),v("li",[t._v("http 服务端测试")])]),t._v(" "),v("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),v("ul",[v("li",[t._v("https://mp.weixin.qq.com/s/41ux7cA-GXYTfeS5juP3wA")]),t._v(" "),v("li",[t._v("https://github.com/golang/mock")])])])}),[],!1,null,null,null);i.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/98.fe5446fa.js b/assets/js/98.fe5446fa.js new file mode 100644 index 000000000..5a583fb8a --- /dev/null +++ b/assets/js/98.fe5446fa.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[98],{528:function(t,e,s){"use strict";s.r(e);var r=s(36),n=Object(r.a)({},(function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"基准测试"}},[t._v("基准测试")]),t._v(" "),s("h2",{attrs:{id:"hey"}},[t._v("hey")]),t._v(" "),s("h2",{attrs:{id:"ethr"}},[t._v("ethr")]),t._v(" "),s("h2",{attrs:{id:"参考资料"}},[t._v("参考资料")]),t._v(" "),s("ul",[s("li",[t._v("https://mp.weixin.qq.com/s/kKNSKdPoeAWUXbwC_tFINw")])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/99.c9fd11f7.js b/assets/js/99.c9fd11f7.js new file mode 100644 index 000000000..96ea4b5d3 --- /dev/null +++ b/assets/js/99.c9fd11f7.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[99],{529:function(t,s,e){"use strict";e.r(s);var i=e(36),n=Object(i.a)({},(function(){var t=this.$createElement,s=this._self._c||t;return s("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}},[s("h1",{attrs:{id:"基础测试"}},[this._v("基础测试")]),this._v(" "),s("h2",{attrs:{id:"参考资料"}},[this._v("参考资料")]),this._v(" "),s("ul",[s("li",[this._v("https://www.alexedwards.net/blog/easy-test-assertions-with-go-generics")])])])}),[],!1,null,null,null);s.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/app.dbd5dba2.js b/assets/js/app.dbd5dba2.js new file mode 100644 index 000000000..1d5f96df1 --- /dev/null +++ b/assets/js/app.dbd5dba2.js @@ -0,0 +1,17 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,l=e[0],u=e[1],c=e[2],f=0,E=[];f<l.length;f++)a=l[f],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&E.push(o[a][0]),o[a]=0;for(r in u)Object.prototype.hasOwnProperty.call(u,r)&&(t[r]=u[r]);for(s&&s(e);E.length;)E.shift()();return i.push.apply(i,c||[]),n()}function n(){for(var t,e=0;e<i.length;e++){for(var n=i[e],r=!0,l=1;l<n.length;l++){var u=n[l];0!==o[u]&&(r=!1)}r&&(i.splice(e--,1),t=a(a.s=n[0]))}return t}var r={},o={1:0},i=[];function a(e){if(r[e])return r[e].exports;var n=r[e]={i:e,l:!1,exports:{}};return t[e].call(n.exports,n,n.exports,a),n.l=!0,n.exports}a.e=function(t){var e=[],n=o[t];if(0!==n)if(n)e.push(n[2]);else{var r=new Promise((function(e,r){n=o[t]=[e,r]}));e.push(n[2]=r);var i,l=document.createElement("script");l.charset="utf-8",l.timeout=120,a.nc&&l.setAttribute("nonce",a.nc),l.src=function(t){return a.p+"assets/js/"+({}[t]||t)+"."+{2:"5c331e53",3:"a22689ce",4:"a73c4d70",5:"864fc44c",6:"5f593451",7:"5280db48",8:"ff976029",9:"e2b0263e",10:"993cf521",11:"25dd6abf",12:"521ef871",13:"6a579e8b",14:"fa863532",15:"ccbbdb7a",16:"d5f6c328",17:"1312d121",18:"4b8a1599",19:"5ed73af4",20:"fea9a837",21:"321b1448",22:"e3bbafa7",23:"6633ca8a",24:"edf743ad",25:"831fd7ee",26:"83ccb127",27:"d1524f5d",28:"69e5608b",29:"742dd6e8",30:"4aafb94a",31:"87baab0b",32:"1ea926c5",33:"4d31d0db",34:"7610889f",35:"32a9ec30",36:"8d562ec5",37:"18cb13d8",38:"53670642",39:"9c8315fb",40:"3bf1fd84",41:"73deb46e",42:"85cfacd9",43:"1b441a63",44:"5dc33e34",45:"b2f02d30",46:"7fef4e9d",47:"6dd9b6a9",48:"e525f69a",49:"565c30a8",50:"249734db",51:"9dd5ff4a",52:"9dfffd13",53:"c98436b4",54:"ee26f0f5",55:"7b5dc58d",56:"e3024720",57:"ba1b4c58",58:"d6c32d73",59:"a733d97b",60:"f162e276",61:"155a3987",62:"ad6d715b",63:"088bb315",64:"58e4a79c",65:"9e82002d",66:"949483d3",67:"613f77e3",68:"f73d44cf",69:"a717baf8",70:"b3476fa3",71:"57746954",72:"4cc3186e",73:"03d8974c",74:"4f1eeb3c",75:"d44fc2e7",76:"f53bf284",77:"bad2588a",78:"2ee31447",79:"f5c3f20d",80:"5aa44af4",81:"33455a03",82:"9f2284bd",83:"5e222179",84:"b93653e7",85:"aff346f9",86:"ca707802",87:"d9bc2332",88:"87973a44",89:"37b7fea9",90:"dedfc540",91:"dbd4ca9b",92:"61c0947f",93:"eaa3fe92",94:"c3c51d69",95:"d1eac759",96:"add14987",97:"357d16bb",98:"fe5446fa",99:"c9fd11f7",100:"049dca94",101:"9e4a3cce",102:"60455322",103:"4ebce8b3",104:"dcbef6d1",105:"76803baf",106:"26567b10",107:"c757198e",108:"90ae536a",109:"55b5f850",110:"9afae874",111:"fcb96ca2",112:"9e9125b6"}[t]+".js"}(t);var u=new Error;i=function(e){l.onerror=l.onload=null,clearTimeout(c);var n=o[t];if(0!==n){if(n){var r=e&&("load"===e.type?"missing":e.type),i=e&&e.target&&e.target.src;u.message="Loading chunk "+t+" failed.\n("+r+": "+i+")",u.name="ChunkLoadError",u.type=r,u.request=i,n[1](u)}o[t]=void 0}};var c=setTimeout((function(){i({type:"timeout",target:l})}),12e4);l.onerror=l.onload=i,document.head.appendChild(l)}return Promise.all(e)},a.m=t,a.c=r,a.d=function(t,e,n){a.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},a.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},a.t=function(t,e){if(1&e&&(t=a(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)a.d(n,r,function(e){return t[e]}.bind(null,r));return n},a.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return a.d(e,"a",e),e},a.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},a.p="/GOFamily/",a.oe=function(t){throw console.error(t),t};var l=window.webpackJsonp=window.webpackJsonp||[],u=l.push.bind(l);l.push=e,l=l.slice();for(var c=0;c<l.length;c++)e(l[c]);var s=u;i.push([220,0]),n()}([function(t,e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof global&&global)||function(){return this}()||Function("return this")()},function(t,e,n){var r=n(0),o=n(34).f,i=n(20),a=n(14),l=n(103),u=n(108),c=n(101);t.exports=function(t,e){var n,s,f,E,p,h=t.target,d=t.global,v=t.stat;if(n=d?r:v?r[h]||l(h,{}):(r[h]||{}).prototype)for(s in e){if(E=e[s],f=t.noTargetGet?(p=o(n,s))&&p.value:n[s],!c(d?s:h+(v?".":"#")+s,t.forced)&&void 0!==f){if(typeof E==typeof f)continue;u(E,f)}(t.sham||f&&f.sham)&&i(E,"sham",!0),a(n,s,E,t)}}},function(t,e,n){var r=n(51),o=Function.prototype,i=o.bind,a=o.call,l=r&&i.bind(a,a);t.exports=r?function(t){return t&&l(t)}:function(t){return t&&function(){return a.apply(t,arguments)}}},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e){t.exports=function(t){return"function"==typeof t}},function(t,e,n){var r=n(0),o=n(39),i=n(9),a=n(70),l=n(40),u=n(141),c=o("wks"),s=r.Symbol,f=s&&s.for,E=u?s:s&&s.withoutSetter||a;t.exports=function(t){if(!i(c,t)||!l&&"string"!=typeof c[t]){var e="Symbol."+t;l&&i(s,t)?c[t]=s[t]:c[t]=u&&f?f(e):E(e)}return c[t]}},function(t,e,n){var r=n(51),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},function(t,e,n){var r=n(3);t.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},function(t,e,n){var r=n(4);t.exports=function(t){return"object"==typeof t?null!==t:r(t)}},function(t,e,n){var r=n(2),o=n(17),i=r({}.hasOwnProperty);t.exports=Object.hasOwn||function(t,e){return i(o(t),e)}},function(t,e,n){var r=n(111),o=n(14),i=n(250);r||o(Object.prototype,"toString",i,{unsafe:!0})},function(t,e,n){var r=n(0),o=n(8),i=r.String,a=r.TypeError;t.exports=function(t){if(o(t))return t;throw a(i(t)+" is not an object")}},function(t,e,n){var r=n(0),o=n(7),i=n(144),a=n(143),l=n(11),u=n(73),c=r.TypeError,s=Object.defineProperty,f=Object.getOwnPropertyDescriptor;e.f=o?a?function(t,e,n){if(l(t),e=u(e),l(n),"function"==typeof t&&"prototype"===e&&"value"in n&&"writable"in n&&!n.writable){var r=f(t,e);r&&r.writable&&(t[e]=n.value,n={configurable:"configurable"in n?n.configurable:r.configurable,enumerable:"enumerable"in n?n.enumerable:r.enumerable,writable:!1})}return s(t,e,n)}:s:function(t,e,n){if(l(t),e=u(e),l(n),i)try{return s(t,e,n)}catch(t){}if("get"in n||"set"in n)throw c("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var r=n(0),o=n(4),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},function(t,e,n){var r=n(0),o=n(4),i=n(20),a=n(210),l=n(103);t.exports=function(t,e,n,u){var c=!!u&&!!u.unsafe,s=!!u&&!!u.enumerable,f=!!u&&!!u.noTargetGet,E=u&&void 0!==u.name?u.name:e;return o(n)&&a(n,E,u),t===r?(s?t[e]=n:l(e,n),t):(c?!f&&t[e]&&(s=!0):delete t[e],s?t[e]=n:i(t,e,n),t)}},function(t,e,n){var r=n(0),o=n(81),i=r.String;t.exports=function(t){if("Symbol"===o(t))throw TypeError("Cannot convert a Symbol value to a string");return i(t)}},function(t,e){t.exports=!1},function(t,e,n){var r=n(0),o=n(25),i=r.Object;t.exports=function(t){return i(o(t))}},function(t,e,n){var r=n(50),o=n(25);t.exports=function(t){return r(o(t))}},function(t,e,n){"use strict";var r=n(168).charAt,o=n(15),i=n(37),a=n(148),l=i.set,u=i.getterFor("String Iterator");a(String,"String",(function(t){l(this,{type:"String Iterator",string:o(t),index:0})}),(function(){var t,e=u(this),n=e.string,o=e.index;return o>=n.length?{value:void 0,done:!0}:(t=r(n,o),e.index+=t.length,{value:t,done:!1})}))},function(t,e,n){var r=n(7),o=n(12),i=n(41);t.exports=r?function(t,e,n){return o.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e){var n=Array.isArray;t.exports=n},function(t,e,n){var r=n(0),o=n(4),i=n(54),a=r.TypeError;t.exports=function(t){if(o(t))return t;throw a(i(t)+" is not a function")}},function(t,e,n){var r=n(0),o=n(169),i=n(170),a=n(140),l=n(20),u=n(5),c=u("iterator"),s=u("toStringTag"),f=a.values,E=function(t,e){if(t){if(t[c]!==f)try{l(t,c,f)}catch(e){t[c]=f}if(t[s]||l(t,s,e),o[e])for(var n in a)if(t[n]!==a[n])try{l(t,n,a[n])}catch(e){t[n]=a[n]}}};for(var p in o)E(r[p]&&r[p].prototype,p);E(i,"DOMTokenList")},function(t,e,n){var r=n(176),o="object"==typeof self&&self&&self.Object===Object&&self,i=r||o||Function("return this")();t.exports=i},function(t,e,n){var r=n(0).TypeError;t.exports=function(t){if(null==t)throw r("Can't call method on "+t);return t}},function(t,e,n){var r=n(2),o=r({}.toString),i=r("".slice);t.exports=function(t){return i(o(t),8,-1)}},function(t,e,n){var r,o=n(11),i=n(142),a=n(106),l=n(55),u=n(147),c=n(72),s=n(76),f=s("IE_PROTO"),E=function(){},p=function(t){return"<script>"+t+"<\/script>"},h=function(t){t.write(p("")),t.close();var e=t.parentWindow.Object;return t=null,e},d=function(){try{r=new ActiveXObject("htmlfile")}catch(t){}var t,e;d="undefined"!=typeof document?document.domain&&r?h(r):((e=c("iframe")).style.display="none",u.appendChild(e),e.src=String("javascript:"),(t=e.contentWindow.document).open(),t.write(p("document.F=Object")),t.close(),t.F):h(r);for(var n=a.length;n--;)delete d.prototype[a[n]];return d()};l[f]=!0,t.exports=Object.create||function(t,e){var n;return null!==t?(E.prototype=o(t),n=new E,E.prototype=null,n[f]=t):n=d(),void 0===e?n:i.f(n,e)}},function(t,e,n){var r=n(69);t.exports=function(t){return r(t.length)}},function(t,e,n){var r=n(12).f,o=n(9),i=n(5)("toStringTag");t.exports=function(t,e,n){t&&!n&&(t=t.prototype),t&&!o(t,i)&&r(t,i,{configurable:!0,value:e})}},function(t,e,n){var r=n(1),o=n(0),i=n(42),a=n(255),l=o.WebAssembly,u=7!==Error("e",{cause:7}).cause,c=function(t,e){var n={};n[t]=a(t,e,u),r({global:!0,constructor:!0,arity:1,forced:u},n)},s=function(t,e){if(l&&l[t]){var n={};n[t]=a("WebAssembly."+t,e,u),r({target:"WebAssembly",stat:!0,constructor:!0,arity:1,forced:u},n)}};c("Error",(function(t){return function(e){return i(t,this,arguments)}})),c("EvalError",(function(t){return function(e){return i(t,this,arguments)}})),c("RangeError",(function(t){return function(e){return i(t,this,arguments)}})),c("ReferenceError",(function(t){return function(e){return i(t,this,arguments)}})),c("SyntaxError",(function(t){return function(e){return i(t,this,arguments)}})),c("TypeError",(function(t){return function(e){return i(t,this,arguments)}})),c("URIError",(function(t){return function(e){return i(t,this,arguments)}})),s("CompileError",(function(t){return function(e){return i(t,this,arguments)}})),s("LinkError",(function(t){return function(e){return i(t,this,arguments)}})),s("RuntimeError",(function(t){return function(e){return i(t,this,arguments)}}))},function(t,e,n){var r=n(14),o=n(259),i=Error.prototype;i.toString!==o&&r(i,"toString",o)},function(t,e,n){"use strict";var r=n(1),o=n(87);r({target:"RegExp",proto:!0,forced:/./.exec!==o},{exec:o})},function(t,e,n){var r=n(2);t.exports=r({}.isPrototypeOf)},function(t,e,n){var r=n(7),o=n(6),i=n(107),a=n(41),l=n(18),u=n(73),c=n(9),s=n(144),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=l(t),e=u(e),s)try{return f(t,e)}catch(t){}if(c(t,e))return a(!o(i.f,t,e),t[e])}},function(t,e,n){var r=n(290),o=n(293);t.exports=function(t,e){var n=o(t,e);return r(n)?n:void 0}},function(t,e,n){"use strict";function r(t,e,n,r,o,i,a,l){var u,c="function"==typeof t?t.options:t;if(e&&(c.render=e,c.staticRenderFns=n,c._compiled=!0),r&&(c.functional=!0),i&&(c._scopeId="data-v-"+i),a?(u=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},c._ssrRegister=u):o&&(u=l?function(){o.call(this,(c.functional?this.parent:this).$root.$options.shadowRoot)}:o),u)if(c.functional){c._injectStyles=u;var s=c.render;c.render=function(t,e){return u.call(e),s(t,e)}}else{var f=c.beforeCreate;c.beforeCreate=f?[].concat(f,u):[u]}return{exports:t,options:c}}n.d(e,"a",(function(){return r}))},function(t,e,n){var r,o,i,a=n(222),l=n(0),u=n(2),c=n(8),s=n(20),f=n(9),E=n(102),p=n(76),h=n(55),d=l.TypeError,v=l.WeakMap;if(a||E.state){var A=E.state||(E.state=new v),B=u(A.get),g=u(A.has),m=u(A.set);r=function(t,e){if(g(A,t))throw new d("Object already initialized");return e.facade=t,m(A,t,e),e},o=function(t){return B(A,t)||{}},i=function(t){return g(A,t)}}else{var y=p("state");h[y]=!0,r=function(t,e){if(f(t,y))throw new d("Object already initialized");return e.facade=t,s(t,y,e),e},o=function(t){return f(t,y)?t[y]:{}},i=function(t){return f(t,y)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!c(e)||(n=o(e)).type!==t)throw d("Incompatible receiver, "+t+" required");return n}}}},function(t,e){t.exports=function(t){return null!=t&&"object"==typeof t}},function(t,e,n){var r=n(16),o=n(102);(t.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.22.5",mode:r?"pure":"global",copyright:"© 2014-2022 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.22.5/LICENSE",source:"https://github.com/zloirock/core-js"})},function(t,e,n){var r=n(52),o=n(3);t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(51),o=Function.prototype,i=o.apply,a=o.call;t.exports="object"==typeof Reflect&&Reflect.apply||(r?a.bind(i):function(){return a.apply(i,arguments)})},function(t,e,n){var r=n(0);t.exports=r.Promise},function(t,e,n){var r=n(26);t.exports=Array.isArray||function(t){return"Array"==r(t)}},function(t,e,n){"use strict";var r=n(1),o=n(48).filter;r({target:"Array",proto:!0,forced:!n(86)("filter")},{filter:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){var r=n(22);t.exports=function(t,e){var n=t[e];return null==n?void 0:r(n)}},function(t,e,n){var r=n(146),o=n(106).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,o)}},function(t,e,n){var r=n(58),o=n(2),i=n(50),a=n(17),l=n(28),u=n(165),c=o([].push),s=function(t){var e=1==t,n=2==t,o=3==t,s=4==t,f=6==t,E=7==t,p=5==t||f;return function(h,d,v,A){for(var B,g,m=a(h),y=i(m),b=r(d,v),C=l(y),x=0,F=A||u,w=e?F(h,C):n||E?F(h,0):void 0;C>x;x++)if((p||x in y)&&(g=b(B=y[x],x,m),t))if(e)w[x]=g;else if(g)switch(t){case 3:return!0;case 5:return B;case 6:return x;case 2:c(w,B)}else switch(t){case 4:return!1;case 7:c(w,B)}return f?-1:o||s?s:w}};t.exports={forEach:s(0),map:s(1),filter:s(2),some:s(3),every:s(4),find:s(5),findIndex:s(6),filterReject:s(7)}},function(t,e,n){var r=n(66),o=n(275),i=n(276),a=r?r.toStringTag:void 0;t.exports=function(t){return null==t?void 0===t?"[object Undefined]":"[object Null]":a&&a in Object(t)?o(t):i(t)}},function(t,e,n){var r=n(0),o=n(2),i=n(3),a=n(26),l=r.Object,u=o("".split);t.exports=i((function(){return!l("z").propertyIsEnumerable(0)}))?function(t){return"String"==a(t)?u(t,""):l(t)}:l},function(t,e,n){var r=n(3);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},function(t,e,n){var r,o,i=n(0),a=n(71),l=i.process,u=i.Deno,c=l&&l.versions||u&&u.version,s=c&&c.v8;s&&(o=(r=s.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},function(t,e,n){var r=n(0),o=n(13),i=n(4),a=n(33),l=n(141),u=r.Object;t.exports=l?function(t){return"symbol"==typeof t}:function(t){var e=o("Symbol");return i(e)&&a(e.prototype,u(t))}},function(t,e,n){var r=n(0).String;t.exports=function(t){try{return r(t)}catch(t){return"Object"}}},function(t,e){t.exports={}},function(t,e){t.exports={}},function(t,e,n){var r=n(2),o=n(11),i=n(224);t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{(t=r(Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set))(n,[]),e=n instanceof Array}catch(t){}return function(n,r){return o(n),i(r),e?t(n,r):n.__proto__=r,n}}():void 0)},function(t,e,n){var r=n(2),o=n(22),i=n(51),a=r(r.bind);t.exports=function(t,e){return o(t),void 0===e?t:i?a(t,e):function(){return t.apply(e,arguments)}}},function(t,e,n){var r=n(0),o=n(43),i=n(4),a=n(101),l=n(77),u=n(5),c=n(234),s=n(16),f=n(52),E=o&&o.prototype,p=u("species"),h=!1,d=i(r.PromiseRejectionEvent),v=a("Promise",(function(){var t=l(o),e=t!==String(o);if(!e&&66===f)return!0;if(s&&(!E.catch||!E.finally))return!0;if(f>=51&&/native code/.test(t))return!1;var n=new o((function(t){t(1)})),r=function(t){t((function(){}),(function(){}))};return(n.constructor={})[p]=r,!(h=n.then((function(){}))instanceof r)||!e&&c&&!d}));t.exports={CONSTRUCTOR:v,REJECTION_EVENT:d,SUBCLASSING:h}},function(t,e,n){"use strict";var r=n(22),o=function(t){var e,n;this.promise=new t((function(t,r){if(void 0!==e||void 0!==n)throw TypeError("Bad Promise constructor");e=t,n=r})),this.resolve=r(e),this.reject=r(n)};t.exports.f=function(t){return new o(t)}},function(t,e,n){n(243),n(247),n(248),n(167),n(249)},function(t,e,n){"use strict";var r=n(73),o=n(12),i=n(41);t.exports=function(t,e,n){var a=r(e);a in t?o.f(t,a,i(0,n)):t[a]=n}},function(t,e,n){"use strict";var r=n(1),o=n(7),i=n(0),a=n(2),l=n(9),u=n(4),c=n(33),s=n(15),f=n(12).f,E=n(108),p=i.Symbol,h=p&&p.prototype;if(o&&u(p)&&(!("description"in h)||void 0!==p().description)){var d={},v=function(){var t=arguments.length<1||void 0===arguments[0]?void 0:s(arguments[0]),e=c(h,this)?new p(t):void 0===t?p():p(t);return""===t&&(d[e]=!0),e};E(v,p),v.prototype=h,h.constructor=v;var A="Symbol(test)"==String(p("test")),B=a(h.toString),g=a(h.valueOf),m=/^Symbol\((.*)\)[^)]+$/,y=a("".replace),b=a("".slice);f(h,"description",{configurable:!0,get:function(){var t=g(this),e=B(t);if(l(d,t))return"";var n=A?b(e,7,-1):y(e,m,"$1");return""===n?void 0:n}}),r({global:!0,constructor:!0,forced:!0},{Symbol:v})}},function(t,e,n){"use strict";var r=n(3);t.exports=function(t,e){var n=[][t];return!!n&&r((function(){n.call(null,e||function(){return 1},1)}))}},function(t,e,n){"use strict";var r=n(1),o=n(0),i=n(44),a=n(80),l=n(8),u=n(105),c=n(28),s=n(18),f=n(62),E=n(5),p=n(86),h=n(82),d=p("slice"),v=E("species"),A=o.Array,B=Math.max;r({target:"Array",proto:!0,forced:!d},{slice:function(t,e){var n,r,o,E=s(this),p=c(E),d=u(t,p),g=u(void 0===e?p:e,p);if(i(E)&&(n=E.constructor,(a(n)&&(n===A||i(n.prototype))||l(n)&&null===(n=n[v]))&&(n=void 0),n===A||void 0===n))return h(E,d,g);for(r=new(void 0===n?A:n)(B(g-d,0)),o=0;d<g;d++,o++)d in E&&f(r,o,E[d]);return r.length=o,r}})},function(t,e,n){var r=n(24).Symbol;t.exports=r},function(t,e,n){"use strict";n.d(e,"a",(function(){return i}));n(130);var r=n(68);n(61),n(63),n(10),n(84),n(19),n(23),n(174);var o=n(93);n(30),n(31);function i(t){return function(t){if(Array.isArray(t))return Object(r.a)(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||Object(o.a)(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}},function(t,e,n){"use strict";function r(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}n.d(e,"a",(function(){return r}))},function(t,e,n){var r=n(75),o=Math.min;t.exports=function(t){return t>0?o(r(t),9007199254740991):0}},function(t,e,n){var r=n(2),o=0,i=Math.random(),a=r(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+a(++o+i,36)}},function(t,e,n){var r=n(13);t.exports=r("navigator","userAgent")||""},function(t,e,n){var r=n(0),o=n(8),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},function(t,e,n){var r=n(145),o=n(53);t.exports=function(t){var e=r(t,"string");return o(e)?e:e+""}},function(t,e,n){var r=n(146),o=n(106);t.exports=Object.keys||function(t){return r(t,o)}},function(t,e){var n=Math.ceil,r=Math.floor;t.exports=function(t){var e=+t;return e!=e||0===e?0:(e>0?r:n)(e)}},function(t,e,n){var r=n(39),o=n(70),i=r("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},function(t,e,n){var r=n(2),o=n(4),i=n(102),a=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(t){return a(t)}),t.exports=i.inspectSource},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e,n){var r=n(26),o=n(0);t.exports="process"==r(o.process)},function(t,e,n){var r=n(2),o=n(3),i=n(4),a=n(81),l=n(13),u=n(77),c=function(){},s=[],f=l("Reflect","construct"),E=/^\s*(?:class|function)\b/,p=r(E.exec),h=!E.exec(c),d=function(t){if(!i(t))return!1;try{return f(c,s,t),!0}catch(t){return!1}},v=function(t){if(!i(t))return!1;switch(a(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return h||!!p(E,u(t))}catch(t){return!0}};v.sham=!0,t.exports=!f||o((function(){var t;return d(d.call)||!d(Object)||!d((function(){t=!0}))||t}))?v:d},function(t,e,n){var r=n(0),o=n(111),i=n(4),a=n(26),l=n(5)("toStringTag"),u=r.Object,c="Arguments"==a(function(){return arguments}());t.exports=o?a:function(t){var e,n,r;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=u(t),l))?n:c?a(e):"Object"==(r=a(e))&&i(e.callee)?"Arguments":r}},function(t,e,n){var r=n(2);t.exports=r([].slice)},function(t,e,n){var r=n(244),o=n(9),i=n(164),a=n(12).f;t.exports=function(t){var e=r.Symbol||(r.Symbol={});o(e,t)||a(e,t,{value:i.f(t)})}},function(t,e,n){n(83)("iterator")},function(t,e,n){var r=n(7),o=n(98).EXISTS,i=n(2),a=n(12).f,l=Function.prototype,u=i(l.toString),c=/function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/,s=i(c.exec);r&&!o&&a(l,"name",{configurable:!0,get:function(){try{return s(c,u(this))[1]}catch(t){return""}}})},function(t,e,n){var r=n(3),o=n(5),i=n(52),a=o("species");t.exports=function(t){return i>=51||!r((function(){var e=[];return(e.constructor={})[a]=function(){return{foo:1}},1!==e[t](Boolean).foo}))}},function(t,e,n){"use strict";var r,o,i=n(6),a=n(2),l=n(15),u=n(213),c=n(131),s=n(39),f=n(27),E=n(37).get,p=n(205),h=n(214),d=s("native-string-replace",String.prototype.replace),v=RegExp.prototype.exec,A=v,B=a("".charAt),g=a("".indexOf),m=a("".replace),y=a("".slice),b=(o=/b*/g,i(v,r=/a/,"a"),i(v,o,"a"),0!==r.lastIndex||0!==o.lastIndex),C=c.BROKEN_CARET,x=void 0!==/()??/.exec("")[1];(b||x||C||p||h)&&(A=function(t){var e,n,r,o,a,c,s,p=this,h=E(p),F=l(t),w=h.raw;if(w)return w.lastIndex=p.lastIndex,e=i(A,w,F),p.lastIndex=w.lastIndex,e;var _=h.groups,P=C&&p.sticky,O=i(u,p),k=p.source,D=0,S=F;if(P&&(O=m(O,"y",""),-1===g(O,"g")&&(O+="g"),S=y(F,p.lastIndex),p.lastIndex>0&&(!p.multiline||p.multiline&&"\n"!==B(F,p.lastIndex-1))&&(k="(?: "+k+")",S=" "+S,D++),n=new RegExp("^(?:"+k+")",O)),x&&(n=new RegExp("^"+k+"$(?!\\s)",O)),b&&(r=p.lastIndex),o=i(v,P?n:p,S),P?o?(o.input=y(o.input,D),o[0]=y(o[0],D),o.index=p.lastIndex,p.lastIndex+=o[0].length):p.lastIndex=0:b&&o&&(p.lastIndex=p.global?o.index+o[0].length:r),x&&o&&o.length>1&&i(d,o[0],n,(function(){for(a=1;a<arguments.length-2;a++)void 0===arguments[a]&&(o[a]=void 0)})),o&&_)for(o.groups=c=f(null),a=0;a<_.length;a++)c[(s=_[a])[0]]=o[s[1]];return o}),t.exports=A},function(t,e,n){var r=n(280),o=n(281),i=n(282),a=n(283),l=n(284);function u(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=a,u.prototype.set=l,t.exports=u},function(t,e,n){var r=n(178);t.exports=function(t,e){for(var n=t.length;n--;)if(r(t[n][0],e))return n;return-1}},function(t,e,n){var r=n(35)(Object,"create");t.exports=r},function(t,e,n){var r=n(302);t.exports=function(t,e){var n=t.__data__;return r(e)?n["string"==typeof e?"string":"hash"]:n.map}},function(t,e,n){var r=n(125);t.exports=function(t){if("string"==typeof t||r(t))return t;var e=t+"";return"0"==e&&1/t==-1/0?"-0":e}},function(t,e,n){"use strict";n.d(e,"a",(function(){return o}));n(65),n(10),n(85),n(174),n(19),n(32),n(127);var r=n(68);function o(t,e){if(t){if("string"==typeof t)return Object(r.a)(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Object(r.a)(t,e):void 0}}},function(t,e){var n=/^\s+|\s+$/g,r=/^[-+]0x[0-9a-f]+$/i,o=/^0b[01]+$/i,i=/^0o[0-7]+$/i,a=parseInt,l="object"==typeof global&&global&&global.Object===Object&&global,u="object"==typeof self&&self&&self.Object===Object&&self,c=l||u||Function("return this")(),s=Object.prototype.toString,f=Math.max,E=Math.min,p=function(){return c.Date.now()};function h(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function d(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&"[object Symbol]"==s.call(t)}(t))return NaN;if(h(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=h(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(n,"");var l=o.test(t);return l||i.test(t)?a(t.slice(2),l?2:8):r.test(t)?NaN:+t}t.exports=function(t,e,n){var r,o,i,a,l,u,c=0,s=!1,v=!1,A=!0;if("function"!=typeof t)throw new TypeError("Expected a function");function B(e){var n=r,i=o;return r=o=void 0,c=e,a=t.apply(i,n)}function g(t){return c=t,l=setTimeout(y,e),s?B(t):a}function m(t){var n=t-u;return void 0===u||n>=e||n<0||v&&t-c>=i}function y(){var t=p();if(m(t))return b(t);l=setTimeout(y,function(t){var n=e-(t-u);return v?E(n,i-(t-c)):n}(t))}function b(t){return l=void 0,A&&r?B(t):(r=o=void 0,a)}function C(){var t=p(),n=m(t);if(r=arguments,o=this,u=t,n){if(void 0===l)return g(u);if(v)return l=setTimeout(y,e),B(u)}return void 0===l&&(l=setTimeout(y,e)),a}return e=d(e)||0,h(n)&&(s=!!n.leading,i=(v="maxWait"in n)?f(d(n.maxWait)||0,e):i,A="trailing"in n?!!n.trailing:A),C.cancel=function(){void 0!==l&&clearTimeout(l),c=0,r=u=o=l=void 0},C.flush=function(){return void 0===l?a:b(p())},C}},function(t,e,n){var r,o; +/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT */void 0===(o="function"==typeof(r=function(){var t,e,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'};function o(t,e,n){return t<e?e:t>n?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var u=n.render(!e),c=u.querySelector(r.barSelector),s=r.speed,f=r.easing;return u.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,s,f)),1===t?(l(u,{transition:"none",opacity:1}),u.offsetWidth,setTimeout((function(){l(u,{transition:"all "+s+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),s)}),s)):setTimeout(e,s)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");c(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),u=t?"-100":i(n.status||0),s=document.querySelector(r.parent);return l(a,{transition:"all 0 linear",transform:"translate3d("+u+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&E(o),s!=document.body&&c(s,"nprogress-custom-parent"),s.appendChild(e),e},n.remove=function(){s(document.documentElement,"nprogress-busy"),s(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&E(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),l=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function u(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function c(t,e){var n=f(t),r=n+e;u(n,e)||(t.className=r.substring(1))}function s(t,e){var n,r=f(t);u(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function E(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";var r=n(1),o=n(48).map;r({target:"Array",proto:!0,forced:!n(86)("map")},{map:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){"use strict";var r=n(42),o=n(6),i=n(2),a=n(137),l=n(3),u=n(11),c=n(4),s=n(75),f=n(69),E=n(15),p=n(25),h=n(138),d=n(46),v=n(271),A=n(139),B=n(5)("replace"),g=Math.max,m=Math.min,y=i([].concat),b=i([].push),C=i("".indexOf),x=i("".slice),F="$0"==="a".replace(/./,"$0"),w=!!/./[B]&&""===/./[B]("a","$0");a("replace",(function(t,e,n){var i=w?"$":"$0";return[function(t,n){var r=p(this),i=null==t?void 0:d(t,B);return i?o(i,t,r,n):o(e,E(r),t,n)},function(t,o){var a=u(this),l=E(t);if("string"==typeof o&&-1===C(o,i)&&-1===C(o,"$<")){var p=n(e,a,l,o);if(p.done)return p.value}var d=c(o);d||(o=E(o));var B=a.global;if(B){var F=a.unicode;a.lastIndex=0}for(var w=[];;){var _=A(a,l);if(null===_)break;if(b(w,_),!B)break;""===E(_[0])&&(a.lastIndex=h(l,f(a.lastIndex),F))}for(var P,O="",k=0,D=0;D<w.length;D++){for(var S=E((_=w[D])[0]),j=g(m(s(_.index),l.length),0),T=[],M=1;M<_.length;M++)b(T,void 0===(P=_[M])?P:String(P));var $=_.groups;if(d){var L=y([S],T,j,l);void 0!==$&&b(L,$);var U=E(r(o,void 0,L))}else U=v(S,l,j,T,$,o);j>=k&&(O+=x(l,k,j)+U,k=j+S.length)}return O+x(l,k)}]}),!!l((function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$<a>")}))||!F||w)},function(t,e,n){var r=n(7),o=n(9),i=Function.prototype,a=r&&Object.getOwnPropertyDescriptor,l=o(i,"name"),u=l&&"something"===function(){}.name,c=l&&(!r||r&&a(i,"name").configurable);t.exports={EXISTS:l,PROPER:u,CONFIGURABLE:c}},function(t,e,n){"use strict";var r=n(1),o=n(172);r({target:"Array",proto:!0,forced:[].forEach!=o},{forEach:o})},function(t,e,n){var r=n(0),o=n(169),i=n(170),a=n(172),l=n(20),u=function(t){if(t&&t.forEach!==a)try{l(t,"forEach",a)}catch(e){t.forEach=a}};for(var c in o)o[c]&&u(r[c]&&r[c].prototype);u(i)},function(t,e,n){var r=n(3),o=n(4),i=/#|\.prototype\./,a=function(t,e){var n=u[l(t)];return n==s||n!=c&&(o(e)?r(e):!!e)},l=a.normalize=function(t){return String(t).replace(i,".").toLowerCase()},u=a.data={},c=a.NATIVE="N",s=a.POLYFILL="P";t.exports=a},function(t,e,n){var r=n(0),o=n(103),i=r["__core-js_shared__"]||o("__core-js_shared__",{});t.exports=i},function(t,e,n){var r=n(0),o=Object.defineProperty;t.exports=function(t,e){try{o(r,t,{value:e,configurable:!0,writable:!0})}catch(n){r[t]=e}return e}},function(t,e,n){var r=n(18),o=n(105),i=n(28),a=function(t){return function(e,n,a){var l,u=r(e),c=i(u),s=o(a,c);if(t&&n!=n){for(;c>s;)if((l=u[s++])!=l)return!0}else for(;c>s;s++)if((t||s in u)&&u[s]===n)return t||s||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},function(t,e,n){var r=n(75),o=Math.max,i=Math.min;t.exports=function(t,e){var n=r(t);return n<0?o(n+e,0):i(n,e)}},function(t,e){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},function(t,e,n){var r=n(9),o=n(149),i=n(34),a=n(12);t.exports=function(t,e,n){for(var l=o(e),u=a.f,c=i.f,s=0;s<l.length;s++){var f=l[s];r(t,f)||n&&r(n,f)||u(t,f,c(e,f))}}},function(t,e,n){var r=n(0),o=n(9),i=n(4),a=n(17),l=n(76),u=n(151),c=l("IE_PROTO"),s=r.Object,f=s.prototype;t.exports=u?s.getPrototypeOf:function(t){var e=a(t);if(o(e,c))return e[c];var n=e.constructor;return i(n)&&e instanceof n?n.prototype:e instanceof s?f:null}},function(t,e,n){var r=n(11),o=n(152),i=n(5)("species");t.exports=function(t,e){var n,a=r(t).constructor;return void 0===a||null==(n=r(a)[i])?e:o(n)}},function(t,e,n){var r={};r[n(5)("toStringTag")]="z",t.exports="[object z]"===String(r)},function(t,e){t.exports=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}}},function(t,e,n){var r=n(81),o=n(46),i=n(56),a=n(5)("iterator");t.exports=function(t){if(null!=t)return o(t,a)||o(t,"@@iterator")||i[r(t)]}},function(t,e,n){var r=n(1),o=n(7),i=n(12).f;r({target:"Object",stat:!0,forced:Object.defineProperty!==i,sham:!o},{defineProperty:i})},function(t,e,n){n(1)({target:"Object",stat:!0,sham:!n(7)},{create:n(27)})},function(t,e,n){var r=n(1),o=n(3),i=n(17),a=n(109),l=n(151);r({target:"Object",stat:!0,forced:o((function(){a(1)})),sham:!l},{getPrototypeOf:function(t){return a(i(t))}})},function(t,e,n){n(1)({target:"Object",stat:!0},{setPrototypeOf:n(57)})},function(t,e,n){var r=n(274),o=n(38),i=Object.prototype,a=i.hasOwnProperty,l=i.propertyIsEnumerable,u=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!l.call(t,"callee")};t.exports=u},function(t,e,n){var r=n(35)(n(24),"Map");t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(294),o=n(301),i=n(303),a=n(304),l=n(305);function u(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=a,u.prototype.set=l,t.exports=u},function(t,e){t.exports=function(t){var e=-1,n=Array(t.size);return t.forEach((function(t){n[++e]=t})),n}},function(t,e){t.exports=function(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=9007199254740991}},function(t,e,n){var r=n(21),o=n(125),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||(a.test(t)||!i.test(t)||null!=e&&t in Object(e))}},function(t,e,n){var r=n(49),o=n(38);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==r(t)}},function(t,e){t.exports=function(t){return t}},function(t,e,n){"use strict";n(32);var r,o,i=n(1),a=n(0),l=n(6),u=n(2),c=n(4),s=n(8),f=(r=!1,(o=/[ac]/).exec=function(){return r=!0,/./.exec.apply(this,arguments)},!0===o.test("abc")&&r),E=a.Error,p=u(/./.test);i({target:"RegExp",proto:!0,forced:!f},{test:function(t){var e=this.exec;if(!c(e))return p(this,t);var n=l(e,this,t);if(null!==n&&!s(n))throw new E("RegExp exec method returned something other than an Object or null");return!!n}})},function(t,e,n){"use strict";var r=n(1),o=n(48).some;r({target:"Array",proto:!0,forced:!n(64)("some")},{some:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){var r=n(1),o=n(17),i=n(74);r({target:"Object",stat:!0,forced:n(3)((function(){i(1)}))},{keys:function(t){return i(o(t))}})},function(t,e,n){n(1)({target:"Array",stat:!0},{isArray:n(44)})},function(t,e,n){var r=n(3),o=n(0).RegExp,i=r((function(){var t=o("a","y");return t.lastIndex=2,null!=t.exec("abcd")})),a=i||r((function(){return!o("a","y").sticky})),l=i||r((function(){var t=o("^r","gy");return t.lastIndex=2,null!=t.exec("str")}));t.exports={BROKEN_CARET:l,MISSED_STICKY:a,UNSUPPORTED_Y:i}},function(t,e,n){var r=n(5),o=n(27),i=n(12),a=r("unscopables"),l=Array.prototype;null==l[a]&&i.f(l,a,{configurable:!0,value:o(null)}),t.exports=function(t){l[a][t]=!0}},function(t,e,n){var r=n(4),o=n(8),i=n(57);t.exports=function(t,e,n){var a,l;return i&&r(a=e.constructor)&&a!==n&&o(l=a.prototype)&&l!==n.prototype&&i(t,l),t}},function(t,e,n){var r=n(0),o=n(135),i=r.TypeError;t.exports=function(t){if(o(t))throw i("The method doesn't accept regular expressions");return t}},function(t,e,n){var r=n(8),o=n(26),i=n(5)("match");t.exports=function(t){var e;return r(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==o(t))}},function(t,e,n){var r=n(5)("match");t.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[r]=!1,"/./"[t](e)}catch(t){}}return!1}},function(t,e,n){"use strict";n(32);var r=n(2),o=n(14),i=n(87),a=n(3),l=n(5),u=n(20),c=l("species"),s=RegExp.prototype;t.exports=function(t,e,n,f){var E=l(t),p=!a((function(){var e={};return e[E]=function(){return 7},7!=""[t](e)})),h=p&&!a((function(){var e=!1,n=/a/;return"split"===t&&((n={}).constructor={},n.constructor[c]=function(){return n},n.flags="",n[E]=/./[E]),n.exec=function(){return e=!0,null},n[E](""),!e}));if(!p||!h||n){var d=r(/./[E]),v=e(E,""[t],(function(t,e,n,o,a){var l=r(t),u=e.exec;return u===i||u===s.exec?p&&!a?{done:!0,value:d(e,n,o)}:{done:!0,value:l(n,e,o)}:{done:!1}}));o(String.prototype,t,v[0]),o(s,E,v[1])}f&&u(s[E],"sham",!0)}},function(t,e,n){"use strict";var r=n(168).charAt;t.exports=function(t,e,n){return e+(n?r(t,e).length:1)}},function(t,e,n){var r=n(0),o=n(6),i=n(11),a=n(4),l=n(26),u=n(87),c=r.TypeError;t.exports=function(t,e){var n=t.exec;if(a(n)){var r=o(n,t,e);return null!==r&&i(r),r}if("RegExp"===l(t))return o(u,t,e);throw c("RegExp#exec called on incompatible receiver")}},function(t,e,n){"use strict";var r=n(18),o=n(132),i=n(56),a=n(37),l=n(12).f,u=n(148),c=n(16),s=n(7),f=a.set,E=a.getterFor("Array Iterator");t.exports=u(Array,"Array",(function(t,e){f(this,{type:"Array Iterator",target:r(t),index:0,kind:e})}),(function(){var t=E(this),e=t.target,n=t.kind,r=t.index++;return!e||r>=e.length?(t.target=void 0,{value:void 0,done:!0}):"keys"==n?{value:r,done:!1}:"values"==n?{value:e[r],done:!1}:{value:[r,e[r]],done:!1}}),"values");var p=i.Arguments=i.Array;if(o("keys"),o("values"),o("entries"),!c&&s&&"values"!==p.name)try{l(p,"name",{value:"values"})}catch(t){}},function(t,e,n){var r=n(40);t.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},function(t,e,n){var r=n(7),o=n(143),i=n(12),a=n(11),l=n(18),u=n(74);e.f=r&&!o?Object.defineProperties:function(t,e){a(t);for(var n,r=l(e),o=u(e),c=o.length,s=0;c>s;)i.f(t,n=o[s++],r[n]);return t}},function(t,e,n){var r=n(7),o=n(3);t.exports=r&&o((function(){return 42!=Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},function(t,e,n){var r=n(7),o=n(3),i=n(72);t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){var r=n(0),o=n(6),i=n(8),a=n(53),l=n(46),u=n(221),c=n(5),s=r.TypeError,f=c("toPrimitive");t.exports=function(t,e){if(!i(t)||a(t))return t;var n,r=l(t,f);if(r){if(void 0===e&&(e="default"),n=o(r,t,e),!i(n)||a(n))return n;throw s("Can't convert object to primitive value")}return void 0===e&&(e="number"),u(t,e)}},function(t,e,n){var r=n(2),o=n(9),i=n(18),a=n(104).indexOf,l=n(55),u=r([].push);t.exports=function(t,e){var n,r=i(t),c=0,s=[];for(n in r)!o(l,n)&&o(r,n)&&u(s,n);for(;e.length>c;)o(r,n=e[c++])&&(~a(s,n)||u(s,n));return s}},function(t,e,n){var r=n(13);t.exports=r("document","documentElement")},function(t,e,n){"use strict";var r=n(1),o=n(6),i=n(16),a=n(98),l=n(4),u=n(223),c=n(109),s=n(57),f=n(29),E=n(20),p=n(14),h=n(5),d=n(56),v=n(150),A=a.PROPER,B=a.CONFIGURABLE,g=v.IteratorPrototype,m=v.BUGGY_SAFARI_ITERATORS,y=h("iterator"),b=function(){return this};t.exports=function(t,e,n,a,h,v,C){u(n,e,a);var x,F,w,_=function(t){if(t===h&&S)return S;if(!m&&t in k)return k[t];switch(t){case"keys":case"values":case"entries":return function(){return new n(this,t)}}return function(){return new n(this)}},P=e+" Iterator",O=!1,k=t.prototype,D=k[y]||k["@@iterator"]||h&&k[h],S=!m&&D||_(h),j="Array"==e&&k.entries||D;if(j&&(x=c(j.call(new t)))!==Object.prototype&&x.next&&(i||c(x)===g||(s?s(x,g):l(x[y])||p(x,y,b)),f(x,P,!0,!0),i&&(d[P]=b)),A&&"values"==h&&D&&"values"!==D.name&&(!i&&B?E(k,"name","values"):(O=!0,S=function(){return o(D,this)})),h)if(F={values:_("values"),keys:v?S:_("keys"),entries:_("entries")},C)for(w in F)(m||O||!(w in k))&&p(k,w,F[w]);else r({target:e,proto:!0,forced:m||O},F);return i&&!C||k[y]===S||p(k,y,S,{name:h}),d[e]=S,F}},function(t,e,n){var r=n(13),o=n(2),i=n(47),a=n(78),l=n(11),u=o([].concat);t.exports=r("Reflect","ownKeys")||function(t){var e=i.f(l(t)),n=a.f;return n?u(e,n(t)):e}},function(t,e,n){"use strict";var r,o,i,a=n(3),l=n(4),u=n(27),c=n(109),s=n(14),f=n(5),E=n(16),p=f("iterator"),h=!1;[].keys&&("next"in(i=[].keys())?(o=c(c(i)))!==Object.prototype&&(r=o):h=!0),null==r||a((function(){var t={};return r[p].call(t)!==t}))?r={}:E&&(r=u(r)),l(r[p])||s(r,p,(function(){return this})),t.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:h}},function(t,e,n){var r=n(3);t.exports=!r((function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype}))},function(t,e,n){var r=n(0),o=n(80),i=n(54),a=r.TypeError;t.exports=function(t){if(o(t))return t;throw a(i(t)+" is not a constructor")}},function(t,e,n){var r,o,i,a,l=n(0),u=n(42),c=n(58),s=n(4),f=n(9),E=n(3),p=n(147),h=n(82),d=n(72),v=n(228),A=n(154),B=n(79),g=l.setImmediate,m=l.clearImmediate,y=l.process,b=l.Dispatch,C=l.Function,x=l.MessageChannel,F=l.String,w=0,_={};try{r=l.location}catch(t){}var P=function(t){if(f(_,t)){var e=_[t];delete _[t],e()}},O=function(t){return function(){P(t)}},k=function(t){P(t.data)},D=function(t){l.postMessage(F(t),r.protocol+"//"+r.host)};g&&m||(g=function(t){v(arguments.length,1);var e=s(t)?t:C(t),n=h(arguments,1);return _[++w]=function(){u(e,void 0,n)},o(w),w},m=function(t){delete _[t]},B?o=function(t){y.nextTick(O(t))}:b&&b.now?o=function(t){b.now(O(t))}:x&&!A?(a=(i=new x).port2,i.port1.onmessage=k,o=c(a.postMessage,a)):l.addEventListener&&s(l.postMessage)&&!l.importScripts&&r&&"file:"!==r.protocol&&!E(D)?(o=D,l.addEventListener("message",k,!1)):o="onreadystatechange"in d("script")?function(t){p.appendChild(d("script")).onreadystatechange=function(){p.removeChild(this),P(t)}}:function(t){setTimeout(O(t),0)}),t.exports={set:g,clear:m}},function(t,e,n){var r=n(71);t.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(r)},function(t,e,n){var r=n(0),o=n(58),i=n(6),a=n(11),l=n(54),u=n(156),c=n(28),s=n(33),f=n(157),E=n(113),p=n(158),h=r.TypeError,d=function(t,e){this.stopped=t,this.result=e},v=d.prototype;t.exports=function(t,e,n){var r,A,B,g,m,y,b,C=n&&n.that,x=!(!n||!n.AS_ENTRIES),F=!(!n||!n.IS_ITERATOR),w=!(!n||!n.INTERRUPTED),_=o(e,C),P=function(t){return r&&p(r,"normal",t),new d(!0,t)},O=function(t){return x?(a(t),w?_(t[0],t[1],P):_(t[0],t[1])):w?_(t,P):_(t)};if(F)r=t;else{if(!(A=E(t)))throw h(l(t)+" is not iterable");if(u(A)){for(B=0,g=c(t);g>B;B++)if((m=O(t[B]))&&s(v,m))return m;return new d(!1)}r=f(t,A)}for(y=r.next;!(b=i(y,r)).done;){try{m=O(b.value)}catch(t){p(r,"throw",t)}if("object"==typeof m&&m&&s(v,m))return m}return new d(!1)}},function(t,e,n){var r=n(5),o=n(56),i=r("iterator"),a=Array.prototype;t.exports=function(t){return void 0!==t&&(o.Array===t||a[i]===t)}},function(t,e,n){var r=n(0),o=n(6),i=n(22),a=n(11),l=n(54),u=n(113),c=r.TypeError;t.exports=function(t,e){var n=arguments.length<2?u(t):e;if(i(n))return a(o(n,t));throw c(l(t)+" is not iterable")}},function(t,e,n){var r=n(6),o=n(11),i=n(46);t.exports=function(t,e,n){var a,l;o(t);try{if(!(a=i(t,"return"))){if("throw"===e)throw n;return n}a=r(a,t)}catch(t){l=!0,a=t}if("throw"===e)throw n;if(l)throw a;return o(a),n}},function(t,e,n){var r=n(43),o=n(160),i=n(59).CONSTRUCTOR;t.exports=i||!o((function(t){r.all(t).then(void 0,(function(){}))}))},function(t,e,n){var r=n(5)("iterator"),o=!1;try{var i=0,a={next:function(){return{done:!!i++}},return:function(){o=!0}};a[r]=function(){return this},Array.from(a,(function(){throw 2}))}catch(t){}t.exports=function(t,e){if(!e&&!o)return!1;var n=!1;try{var i={};i[r]=function(){return{next:function(){return{done:n=!0}}}},t(i)}catch(t){}return n}},function(t,e,n){var r=n(11),o=n(8),i=n(60);t.exports=function(t,e){if(r(t),o(e)&&e.constructor===t)return e;var n=i.f(t);return(0,n.resolve)(e),n.promise}},function(t,e,n){var r=n(26),o=n(18),i=n(47).f,a=n(163),l="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[];t.exports.f=function(t){return l&&"Window"==r(t)?function(t){try{return i(t)}catch(t){return a(l)}}(t):i(o(t))}},function(t,e,n){var r=n(0),o=n(105),i=n(28),a=n(62),l=r.Array,u=Math.max;t.exports=function(t,e,n){for(var r=i(t),c=o(e,r),s=o(void 0===n?r:n,r),f=l(u(s-c,0)),E=0;c<s;c++,E++)a(f,E,t[c]);return f.length=E,f}},function(t,e,n){var r=n(5);e.f=r},function(t,e,n){var r=n(246);t.exports=function(t,e){return new(r(t))(0===e?0:e)}},function(t,e,n){var r=n(40);t.exports=r&&!!Symbol.for&&!!Symbol.keyFor},function(t,e,n){var r=n(1),o=n(13),i=n(42),a=n(6),l=n(2),u=n(3),c=n(44),s=n(4),f=n(8),E=n(53),p=n(82),h=n(40),d=o("JSON","stringify"),v=l(/./.exec),A=l("".charAt),B=l("".charCodeAt),g=l("".replace),m=l(1..toString),y=/[\uD800-\uDFFF]/g,b=/^[\uD800-\uDBFF]$/,C=/^[\uDC00-\uDFFF]$/,x=!h||u((function(){var t=o("Symbol")();return"[null]"!=d([t])||"{}"!=d({a:t})||"{}"!=d(Object(t))})),F=u((function(){return'"\\udf06\\ud834"'!==d("\udf06\ud834")||'"\\udead"'!==d("\udead")})),w=function(t,e){var n=p(arguments),r=e;if((f(e)||void 0!==t)&&!E(t))return c(e)||(e=function(t,e){if(s(r)&&(e=a(r,this,t,e)),!E(e))return e}),n[1]=e,i(d,null,n)},_=function(t,e,n){var r=A(n,e-1),o=A(n,e+1);return v(b,t)&&!v(C,o)||v(C,t)&&!v(b,r)?"\\u"+m(B(t,0),16):t};d&&r({target:"JSON",stat:!0,arity:3,forced:x||F},{stringify:function(t,e,n){var r=p(arguments),o=i(x?w:d,null,r);return F&&"string"==typeof o?g(o,y,_):o}})},function(t,e,n){var r=n(2),o=n(75),i=n(15),a=n(25),l=r("".charAt),u=r("".charCodeAt),c=r("".slice),s=function(t){return function(e,n){var r,s,f=i(a(e)),E=o(n),p=f.length;return E<0||E>=p?t?"":void 0:(r=u(f,E))<55296||r>56319||E+1===p||(s=u(f,E+1))<56320||s>57343?t?l(f,E):r:t?c(f,E,E+2):s-56320+(r-55296<<10)+65536}};t.exports={codeAt:s(!1),charAt:s(!0)}},function(t,e){t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},function(t,e,n){var r=n(72)("span").classList,o=r&&r.constructor&&r.constructor.prototype;t.exports=o===Object.prototype?void 0:o},function(t,e,n){var r=n(15);t.exports=function(t,e){return void 0===t?arguments.length<2?"":e:r(t)}},function(t,e,n){"use strict";var r=n(48).forEach,o=n(64)("forEach");t.exports=o?[].forEach:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}},function(t,e,n){var r=n(3);t.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},function(t,e,n){var r=n(1),o=n(269);r({target:"Array",stat:!0,forced:!n(160)((function(t){Array.from(t)}))},{from:o})},function(t,e){t.exports=function(t,e){for(var n=-1,r=e.length,o=t.length;++n<r;)t[o+n]=e[n];return t}},function(t,e){var n="object"==typeof global&&global&&global.Object===Object&&global;t.exports=n},function(t,e,n){var r=n(88),o=n(285),i=n(286),a=n(287),l=n(288),u=n(289);function c(t){var e=this.__data__=new r(t);this.size=e.size}c.prototype.clear=o,c.prototype.delete=i,c.prototype.get=a,c.prototype.has=l,c.prototype.set=u,t.exports=c},function(t,e){t.exports=function(t,e){return t===e||t!=t&&e!=e}},function(t,e,n){var r=n(49),o=n(120);t.exports=function(t){if(!o(t))return!1;var e=r(t);return"[object Function]"==e||"[object GeneratorFunction]"==e||"[object AsyncFunction]"==e||"[object Proxy]"==e}},function(t,e){var n=Function.prototype.toString;t.exports=function(t){if(null!=t){try{return n.call(t)}catch(t){}try{return t+""}catch(t){}}return""}},function(t,e,n){var r=n(306),o=n(38);t.exports=function t(e,n,i,a,l){return e===n||(null==e||null==n||!o(e)&&!o(n)?e!=e&&n!=n:r(e,n,i,a,t,l))}},function(t,e,n){var r=n(183),o=n(309),i=n(184);t.exports=function(t,e,n,a,l,u){var c=1&n,s=t.length,f=e.length;if(s!=f&&!(c&&f>s))return!1;var E=u.get(t),p=u.get(e);if(E&&p)return E==e&&p==t;var h=-1,d=!0,v=2&n?new r:void 0;for(u.set(t,e),u.set(e,t);++h<s;){var A=t[h],B=e[h];if(a)var g=c?a(B,A,h,e,t,u):a(A,B,h,t,e,u);if(void 0!==g){if(g)continue;d=!1;break}if(v){if(!o(e,(function(t,e){if(!i(v,e)&&(A===t||l(A,t,n,a,u)))return v.push(e)}))){d=!1;break}}else if(A!==B&&!l(A,B,n,a,u)){d=!1;break}}return u.delete(t),u.delete(e),d}},function(t,e,n){var r=n(121),o=n(307),i=n(308);function a(t){var e=-1,n=null==t?0:t.length;for(this.__data__=new r;++e<n;)this.add(t[e])}a.prototype.add=a.prototype.push=o,a.prototype.has=i,t.exports=a},function(t,e){t.exports=function(t,e){return t.has(e)}},function(t,e,n){var r=n(319),o=n(325),i=n(190);t.exports=function(t){return i(t)?r(t):o(t)}},function(t,e,n){(function(t){var r=n(24),o=n(321),i=e&&!e.nodeType&&e,a=i&&"object"==typeof t&&t&&!t.nodeType&&t,l=a&&a.exports===i?r.Buffer:void 0,u=(l?l.isBuffer:void 0)||o;t.exports=u}).call(this,n(187)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e){var n=/^(?:0|[1-9]\d*)$/;t.exports=function(t,e){var r=typeof t;return!!(e=null==e?9007199254740991:e)&&("number"==r||"symbol"!=r&&n.test(t))&&t>-1&&t%1==0&&t<e}},function(t,e,n){var r=n(322),o=n(323),i=n(324),a=i&&i.isTypedArray,l=a?o(a):r;t.exports=l},function(t,e,n){var r=n(179),o=n(123);t.exports=function(t){return null!=t&&o(t.length)&&!r(t)}},function(t,e,n){var r=n(35)(n(24),"Set");t.exports=r},function(t,e,n){var r=n(120);t.exports=function(t){return t==t&&!r(t)}},function(t,e){t.exports=function(t,e){return function(n){return null!=n&&(n[t]===e&&(void 0!==e||t in Object(n)))}}},function(t,e,n){var r=n(195),o=n(92);t.exports=function(t,e){for(var n=0,i=(e=r(e,t)).length;null!=t&&n<i;)t=t[o(e[n++])];return n&&n==i?t:void 0}},function(t,e,n){var r=n(21),o=n(124),i=n(335),a=n(338);t.exports=function(t,e){return r(t)?t:o(t,e)?[t]:i(a(t))}},function(t,e,n){},function(t,e,n){var r=n(1),o=n(13),i=n(42),a=n(372),l=n(152),u=n(11),c=n(8),s=n(27),f=n(3),E=o("Reflect","construct"),p=Object.prototype,h=[].push,d=f((function(){function t(){}return!(E((function(){}),[],t)instanceof t)})),v=!f((function(){E((function(){}))})),A=d||v;r({target:"Reflect",stat:!0,forced:A,sham:A},{construct:function(t,e){l(t),u(e);var n=arguments.length<3?t:l(arguments[2]);if(v&&!d)return E(t,e,n);if(t==n){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var r=[null];return i(h,r,e),new(i(a,t,r))}var o=n.prototype,f=s(c(o)?o:p),A=i(t,f,e);return c(A)?A:f}})},function(t,e,n){var r=n(1),o=n(0),i=n(29);r({global:!0},{Reflect:{}}),i(o.Reflect,"Reflect",!0)},function(t,e,n){},function(t,e,n){},function(t,e,n){var r=n(272),o=n(277),i=n(347),a=n(355),l=n(364),u=n(219),c=i((function(t){var e=u(t);return l(e)&&(e=void 0),a(r(t,1,l,!0),o(e,2))}));t.exports=c},function(t,e,n){"use strict"; +/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var r=/["'&<>]/;t.exports=function(t){var e,n=""+t,o=r.exec(n);if(!o)return n;var i="",a=0,l=0;for(a=o.index;a<n.length;a++){switch(n.charCodeAt(a)){case 34:e=""";break;case 38:e="&";break;case 39:e="'";break;case 60:e="<";break;case 62:e=">";break;default:continue}l!==a&&(i+=n.substring(l,a)),l=a+1,i+=e}return l!==a?i+n.substring(l,a):i}},function(t,e,n){!function(){"use strict";t.exports={polyfill:function(){var t=window,e=document;if(!("scrollBehavior"in e.documentElement.style)||!0===t.__forceSmoothScrollPolyfill__){var n,r=t.HTMLElement||t.Element,o={scroll:t.scroll||t.scrollTo,scrollBy:t.scrollBy,elementScroll:r.prototype.scroll||l,scrollIntoView:r.prototype.scrollIntoView},i=t.performance&&t.performance.now?t.performance.now.bind(t.performance):Date.now,a=(n=t.navigator.userAgent,new RegExp(["MSIE ","Trident/","Edge/"].join("|")).test(n)?1:0);t.scroll=t.scrollTo=function(){void 0!==arguments[0]&&(!0!==u(arguments[0])?h.call(t,e.body,void 0!==arguments[0].left?~~arguments[0].left:t.scrollX||t.pageXOffset,void 0!==arguments[0].top?~~arguments[0].top:t.scrollY||t.pageYOffset):o.scroll.call(t,void 0!==arguments[0].left?arguments[0].left:"object"!=typeof arguments[0]?arguments[0]:t.scrollX||t.pageXOffset,void 0!==arguments[0].top?arguments[0].top:void 0!==arguments[1]?arguments[1]:t.scrollY||t.pageYOffset))},t.scrollBy=function(){void 0!==arguments[0]&&(u(arguments[0])?o.scrollBy.call(t,void 0!==arguments[0].left?arguments[0].left:"object"!=typeof arguments[0]?arguments[0]:0,void 0!==arguments[0].top?arguments[0].top:void 0!==arguments[1]?arguments[1]:0):h.call(t,e.body,~~arguments[0].left+(t.scrollX||t.pageXOffset),~~arguments[0].top+(t.scrollY||t.pageYOffset)))},r.prototype.scroll=r.prototype.scrollTo=function(){if(void 0!==arguments[0])if(!0!==u(arguments[0])){var t=arguments[0].left,e=arguments[0].top;h.call(this,this,void 0===t?this.scrollLeft:~~t,void 0===e?this.scrollTop:~~e)}else{if("number"==typeof arguments[0]&&void 0===arguments[1])throw new SyntaxError("Value could not be converted");o.elementScroll.call(this,void 0!==arguments[0].left?~~arguments[0].left:"object"!=typeof arguments[0]?~~arguments[0]:this.scrollLeft,void 0!==arguments[0].top?~~arguments[0].top:void 0!==arguments[1]?~~arguments[1]:this.scrollTop)}},r.prototype.scrollBy=function(){void 0!==arguments[0]&&(!0!==u(arguments[0])?this.scroll({left:~~arguments[0].left+this.scrollLeft,top:~~arguments[0].top+this.scrollTop,behavior:arguments[0].behavior}):o.elementScroll.call(this,void 0!==arguments[0].left?~~arguments[0].left+this.scrollLeft:~~arguments[0]+this.scrollLeft,void 0!==arguments[0].top?~~arguments[0].top+this.scrollTop:~~arguments[1]+this.scrollTop))},r.prototype.scrollIntoView=function(){if(!0!==u(arguments[0])){var n=E(this),r=n.getBoundingClientRect(),i=this.getBoundingClientRect();n!==e.body?(h.call(this,n,n.scrollLeft+i.left-r.left,n.scrollTop+i.top-r.top),"fixed"!==t.getComputedStyle(n).position&&t.scrollBy({left:r.left,top:r.top,behavior:"smooth"})):t.scrollBy({left:i.left,top:i.top,behavior:"smooth"})}else o.scrollIntoView.call(this,void 0===arguments[0]||arguments[0])}}function l(t,e){this.scrollLeft=t,this.scrollTop=e}function u(t){if(null===t||"object"!=typeof t||void 0===t.behavior||"auto"===t.behavior||"instant"===t.behavior)return!0;if("object"==typeof t&&"smooth"===t.behavior)return!1;throw new TypeError("behavior member of ScrollOptions "+t.behavior+" is not a valid value for enumeration ScrollBehavior.")}function c(t,e){return"Y"===e?t.clientHeight+a<t.scrollHeight:"X"===e?t.clientWidth+a<t.scrollWidth:void 0}function s(e,n){var r=t.getComputedStyle(e,null)["overflow"+n];return"auto"===r||"scroll"===r}function f(t){var e=c(t,"Y")&&s(t,"Y"),n=c(t,"X")&&s(t,"X");return e||n}function E(t){for(;t!==e.body&&!1===f(t);)t=t.parentNode||t.host;return t}function p(e){var n,r,o,a,l=(i()-e.startTime)/468;a=l=l>1?1:l,n=.5*(1-Math.cos(Math.PI*a)),r=e.startX+(e.x-e.startX)*n,o=e.startY+(e.y-e.startY)*n,e.method.call(e.scrollable,r,o),r===e.x&&o===e.y||t.requestAnimationFrame(p.bind(t,e))}function h(n,r,a){var u,c,s,f,E=i();n===e.body?(u=t,c=t.scrollX||t.pageXOffset,s=t.scrollY||t.pageYOffset,f=o.scroll):(u=n,c=n.scrollLeft,s=n.scrollTop,f=l),p({scrollable:u,method:f,startTime:E,startX:c,startY:s,x:r,y:a})}}}}()},function(t,e,n){"use strict";var r=n(1),o=n(2),i=n(104).indexOf,a=n(64),l=o([].indexOf),u=!!l&&1/l([1],1,-0)<0,c=a("indexOf");r({target:"Array",proto:!0,forced:u||!c},{indexOf:function(t){var e=arguments.length>1?arguments[1]:void 0;return u?l(this,t,e)||0:i(this,t,e)}})},function(t,e,n){var r=n(3),o=n(0).RegExp;t.exports=r((function(){var t=o(".","s");return!(t.dotAll&&t.exec("\n")&&"s"===t.flags)}))},function(t,e,n){"use strict";var r=n(1),o=n(2),i=n(50),a=n(18),l=n(64),u=o([].join),c=i!=Object,s=l("join",",");r({target:"Array",proto:!0,forced:c||!s},{join:function(t){return u(a(this),void 0===t?",":t)}})},function(t,e,n){var r=n(2),o=n(25),i=n(15),a=n(208),l=r("".replace),u="["+a+"]",c=RegExp("^"+u+u+"*"),s=RegExp(u+u+"*$"),f=function(t){return function(e){var n=i(o(e));return 1&t&&(n=l(n,c,"")),2&t&&(n=l(n,s,"")),n}};t.exports={start:f(1),end:f(2),trim:f(3)}},function(t,e){t.exports="\t\n\v\f\r \u2028\u2029\ufeff"},function(t,e,n){"use strict";var r=n(42),o=n(6),i=n(2),a=n(137),l=n(135),u=n(11),c=n(25),s=n(110),f=n(138),E=n(69),p=n(15),h=n(46),d=n(163),v=n(139),A=n(87),B=n(131),g=n(3),m=B.UNSUPPORTED_Y,y=Math.min,b=[].push,C=i(/./.exec),x=i(b),F=i("".slice);a("split",(function(t,e,n){var i;return i="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(t,n){var i=p(c(this)),a=void 0===n?4294967295:n>>>0;if(0===a)return[];if(void 0===t)return[i];if(!l(t))return o(e,i,t,a);for(var u,s,f,E=[],h=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),v=0,B=new RegExp(t.source,h+"g");(u=o(A,B,i))&&!((s=B.lastIndex)>v&&(x(E,F(i,v,u.index)),u.length>1&&u.index<i.length&&r(b,E,d(u,1)),f=u[0].length,v=s,E.length>=a));)B.lastIndex===u.index&&B.lastIndex++;return v===i.length?!f&&C(B,"")||x(E,""):x(E,F(i,v)),E.length>a?d(E,0,a):E}:"0".split(void 0,0).length?function(t,n){return void 0===t&&0===n?[]:o(e,this,t,n)}:e,[function(e,n){var r=c(this),a=null==e?void 0:h(e,t);return a?o(a,e,r,n):o(i,p(r),e,n)},function(t,r){var o=u(this),a=p(t),l=n(i,o,a,r,i!==e);if(l.done)return l.value;var c=s(o,RegExp),h=o.unicode,d=(o.ignoreCase?"i":"")+(o.multiline?"m":"")+(o.unicode?"u":"")+(m?"g":"y"),A=new c(m?"^(?:"+o.source+")":o,d),B=void 0===r?4294967295:r>>>0;if(0===B)return[];if(0===a.length)return null===v(A,a)?[a]:[];for(var g=0,b=0,C=[];b<a.length;){A.lastIndex=m?0:b;var w,_=v(A,m?F(a,b):a);if(null===_||(w=y(E(A.lastIndex+(m?b:0)),a.length))===g)b=f(a,b,h);else{if(x(C,F(a,g,b)),C.length===B)return C;for(var P=1;P<=_.length-1;P++)if(x(C,_[P]),C.length===B)return C;b=g=w}}return x(C,F(a,g)),C}]}),!!g((function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var n="ab".split(t);return 2!==n.length||"a"!==n[0]||"b"!==n[1]})),m)},function(t,e,n){var r=n(3),o=n(4),i=n(9),a=n(7),l=n(98).CONFIGURABLE,u=n(77),c=n(37),s=c.enforce,f=c.get,E=Object.defineProperty,p=a&&!r((function(){return 8!==E((function(){}),"length",{value:8}).length})),h=String(String).split("String"),d=t.exports=function(t,e,n){if("Symbol("===String(e).slice(0,7)&&(e="["+String(e).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),n&&n.getter&&(e="get "+e),n&&n.setter&&(e="set "+e),(!i(t,"name")||l&&t.name!==e)&&E(t,"name",{value:e,configurable:!0}),p&&n&&i(n,"arity")&&t.length!==n.arity&&E(t,"length",{value:n.arity}),n&&i(n,"constructor")&&n.constructor){if(a)try{E(t,"prototype",{writable:!1})}catch(t){}}else t.prototype=void 0;var r=s(t);return i(r,"source")||(r.source=h.join("string"==typeof e?e:"")),t};Function.prototype.toString=d((function(){return o(this)&&f(this).source||u(this)}),"toString")},function(t,e,n){"use strict";var r=n(13),o=n(12),i=n(5),a=n(7),l=i("species");t.exports=function(t){var e=r(t),n=o.f;a&&e&&!e[l]&&n(e,l,{configurable:!0,get:function(){return this}})}},function(t,e,n){var r=n(12).f;t.exports=function(t,e,n){n in t||r(t,n,{configurable:!0,get:function(){return e[n]},set:function(t){e[n]=t}})}},function(t,e,n){"use strict";var r=n(11);t.exports=function(){var t=r(this),e="";return t.hasIndices&&(e+="d"),t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.dotAll&&(e+="s"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},function(t,e,n){var r=n(3),o=n(0).RegExp;t.exports=r((function(){var t=o("(?<a>b)","g");return"b"!==t.exec("b").groups.a||"bc"!=="b".replace(t,"$<a>c")}))},function(t,e,n){"use strict";var r=n(1),o=n(104).includes,i=n(3),a=n(132);r({target:"Array",proto:!0,forced:i((function(){return!Array(1).includes()}))},{includes:function(t){return o(this,t,arguments.length>1?arguments[1]:void 0)}}),a("includes")},function(t,e,n){"use strict";var r=n(1),o=n(2),i=n(134),a=n(25),l=n(15),u=n(136),c=o("".indexOf);r({target:"String",proto:!0,forced:!u("includes")},{includes:function(t){return!!~c(l(a(this)),l(i(t)),arguments.length>1?arguments[1]:void 0)}})},function(t,e,n){"use strict";var r=n(1),o=n(0),i=n(3),a=n(44),l=n(8),u=n(17),c=n(28),s=n(62),f=n(165),E=n(86),p=n(5),h=n(52),d=p("isConcatSpreadable"),v=o.TypeError,A=h>=51||!i((function(){var t=[];return t[d]=!1,t.concat()[0]!==t})),B=E("concat"),g=function(t){if(!l(t))return!1;var e=t[d];return void 0!==e?!!e:a(t)};r({target:"Array",proto:!0,arity:1,forced:!A||!B},{concat:function(t){var e,n,r,o,i,a=u(this),l=f(a,0),E=0;for(e=-1,r=arguments.length;e<r;e++)if(g(i=-1===e?a:arguments[e])){if(E+(o=c(i))>9007199254740991)throw v("Maximum allowed index exceeded");for(n=0;n<o;n++,E++)n in i&&s(l,E,i[n])}else{if(E>=9007199254740991)throw v("Maximum allowed index exceeded");s(l,E++,i)}return l.length=E,l}})},function(t,e,n){var r=n(194);t.exports=function(t,e,n){var o=null==t?void 0:r(t,e);return void 0===o?n:o}},function(t,e){t.exports=function(t){var e=null==t?0:t.length;return e?t[e-1]:void 0}},function(t,e,n){t.exports=n(375)},function(t,e,n){var r=n(0),o=n(6),i=n(4),a=n(8),l=r.TypeError;t.exports=function(t,e){var n,r;if("string"===e&&i(n=t.toString)&&!a(r=o(n,t)))return r;if(i(n=t.valueOf)&&!a(r=o(n,t)))return r;if("string"!==e&&i(n=t.toString)&&!a(r=o(n,t)))return r;throw l("Can't convert object to primitive value")}},function(t,e,n){var r=n(0),o=n(4),i=n(77),a=r.WeakMap;t.exports=o(a)&&/native code/.test(i(a))},function(t,e,n){"use strict";var r=n(150).IteratorPrototype,o=n(27),i=n(41),a=n(29),l=n(56),u=function(){return this};t.exports=function(t,e,n,c){var s=e+" Iterator";return t.prototype=o(r,{next:i(+!c,n)}),a(t,s,!1,!0),l[s]=u,t}},function(t,e,n){var r=n(0),o=n(4),i=r.String,a=r.TypeError;t.exports=function(t){if("object"==typeof t||o(t))return t;throw a("Can't set "+i(t)+" as a prototype")}},function(t,e,n){n(226),n(235),n(236),n(237),n(238),n(239)},function(t,e,n){"use strict";var r,o,i,a=n(1),l=n(16),u=n(79),c=n(0),s=n(6),f=n(14),E=n(57),p=n(29),h=n(211),d=n(22),v=n(4),A=n(8),B=n(227),g=n(110),m=n(153).set,y=n(229),b=n(232),C=n(112),x=n(233),F=n(37),w=n(43),_=n(59),P=n(60),O=_.CONSTRUCTOR,k=_.REJECTION_EVENT,D=_.SUBCLASSING,S=F.getterFor("Promise"),j=F.set,T=w&&w.prototype,M=w,$=T,L=c.TypeError,U=c.document,R=c.process,I=P.f,N=I,z=!!(U&&U.createEvent&&c.dispatchEvent),V=function(t){var e;return!(!A(t)||!v(e=t.then))&&e},q=function(t,e){var n,r,o,i=e.value,a=1==e.state,l=a?t.ok:t.fail,u=t.resolve,c=t.reject,f=t.domain;try{l?(a||(2===e.rejection&&Y(e),e.rejection=1),!0===l?n=i:(f&&f.enter(),n=l(i),f&&(f.exit(),o=!0)),n===t.promise?c(L("Promise-chain cycle")):(r=V(n))?s(r,n,u,c):u(n)):c(i)}catch(t){f&&!o&&f.exit(),c(t)}},G=function(t,e){t.notified||(t.notified=!0,y((function(){for(var n,r=t.reactions;n=r.get();)q(n,t);t.notified=!1,e&&!t.rejection&&H(t)})))},W=function(t,e,n){var r,o;z?((r=U.createEvent("Event")).promise=e,r.reason=n,r.initEvent(t,!1,!0),c.dispatchEvent(r)):r={promise:e,reason:n},!k&&(o=c["on"+t])?o(r):"unhandledrejection"===t&&b("Unhandled promise rejection",n)},H=function(t){s(m,c,(function(){var e,n=t.facade,r=t.value;if(X(t)&&(e=C((function(){u?R.emit("unhandledRejection",r,n):W("unhandledrejection",n,r)})),t.rejection=u||X(t)?2:1,e.error))throw e.value}))},X=function(t){return 1!==t.rejection&&!t.parent},Y=function(t){s(m,c,(function(){var e=t.facade;u?R.emit("rejectionHandled",e):W("rejectionhandled",e,t.value)}))},K=function(t,e,n){return function(r){t(e,r,n)}},J=function(t,e,n){t.done||(t.done=!0,n&&(t=n),t.value=e,t.state=2,G(t,!0))},Q=function(t,e,n){if(!t.done){t.done=!0,n&&(t=n);try{if(t.facade===e)throw L("Promise can't be resolved itself");var r=V(e);r?y((function(){var n={done:!1};try{s(r,e,K(Q,n,t),K(J,n,t))}catch(e){J(n,e,t)}})):(t.value=e,t.state=1,G(t,!1))}catch(e){J({done:!1},e,t)}}};if(O&&($=(M=function(t){B(this,$),d(t),s(r,this);var e=S(this);try{t(K(Q,e),K(J,e))}catch(t){J(e,t)}}).prototype,(r=function(t){j(this,{type:"Promise",done:!1,notified:!1,parent:!1,reactions:new x,rejection:!1,state:0,value:void 0})}).prototype=f($,"then",(function(t,e){var n=S(this),r=I(g(this,M));return n.parent=!0,r.ok=!v(t)||t,r.fail=v(e)&&e,r.domain=u?R.domain:void 0,0==n.state?n.reactions.add(r):y((function(){q(r,n)})),r.promise})),o=function(){var t=new r,e=S(t);this.promise=t,this.resolve=K(Q,e),this.reject=K(J,e)},P.f=I=function(t){return t===M||void 0===t?new o(t):N(t)},!l&&v(w)&&T!==Object.prototype)){i=T.then,D||f(T,"then",(function(t,e){var n=this;return new M((function(t,e){s(i,n,t,e)})).then(t,e)}),{unsafe:!0});try{delete T.constructor}catch(t){}E&&E(T,$)}a({global:!0,constructor:!0,wrap:!0,forced:O},{Promise:M}),p(M,"Promise",!1,!0),h("Promise")},function(t,e,n){var r=n(0),o=n(33),i=r.TypeError;t.exports=function(t,e){if(o(e,t))return t;throw i("Incorrect invocation")}},function(t,e,n){var r=n(0).TypeError;t.exports=function(t,e){if(t<e)throw r("Not enough arguments");return t}},function(t,e,n){var r,o,i,a,l,u,c,s,f=n(0),E=n(58),p=n(34).f,h=n(153).set,d=n(154),v=n(230),A=n(231),B=n(79),g=f.MutationObserver||f.WebKitMutationObserver,m=f.document,y=f.process,b=f.Promise,C=p(f,"queueMicrotask"),x=C&&C.value;x||(r=function(){var t,e;for(B&&(t=y.domain)&&t.exit();o;){e=o.fn,o=o.next;try{e()}catch(t){throw o?a():i=void 0,t}}i=void 0,t&&t.enter()},d||B||A||!g||!m?!v&&b&&b.resolve?((c=b.resolve(void 0)).constructor=b,s=E(c.then,c),a=function(){s(r)}):B?a=function(){y.nextTick(r)}:(h=E(h,f),a=function(){h(r)}):(l=!0,u=m.createTextNode(""),new g(r).observe(u,{characterData:!0}),a=function(){u.data=l=!l})),t.exports=x||function(t){var e={fn:t,next:void 0};i&&(i.next=e),o||(o=e,a()),i=e}},function(t,e,n){var r=n(71),o=n(0);t.exports=/ipad|iphone|ipod/i.test(r)&&void 0!==o.Pebble},function(t,e,n){var r=n(71);t.exports=/web0s(?!.*chrome)/i.test(r)},function(t,e,n){var r=n(0);t.exports=function(t,e){var n=r.console;n&&n.error&&(1==arguments.length?n.error(t):n.error(t,e))}},function(t,e){var n=function(){this.head=null,this.tail=null};n.prototype={add:function(t){var e={item:t,next:null};this.head?this.tail.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return this.head=t.next,this.tail===t&&(this.tail=null),t.item}},t.exports=n},function(t,e){t.exports="object"==typeof window&&"object"!=typeof Deno},function(t,e,n){"use strict";var r=n(1),o=n(6),i=n(22),a=n(60),l=n(112),u=n(155);r({target:"Promise",stat:!0,forced:n(159)},{all:function(t){var e=this,n=a.f(e),r=n.resolve,c=n.reject,s=l((function(){var n=i(e.resolve),a=[],l=0,s=1;u(t,(function(t){var i=l++,u=!1;s++,o(n,e,t).then((function(t){u||(u=!0,a[i]=t,--s||r(a))}),c)})),--s||r(a)}));return s.error&&c(s.value),n.promise}})},function(t,e,n){"use strict";var r=n(1),o=n(16),i=n(59).CONSTRUCTOR,a=n(43),l=n(13),u=n(4),c=n(14),s=a&&a.prototype;if(r({target:"Promise",proto:!0,forced:i,real:!0},{catch:function(t){return this.then(void 0,t)}}),!o&&u(a)){var f=l("Promise").prototype.catch;s.catch!==f&&c(s,"catch",f,{unsafe:!0})}},function(t,e,n){"use strict";var r=n(1),o=n(6),i=n(22),a=n(60),l=n(112),u=n(155);r({target:"Promise",stat:!0,forced:n(159)},{race:function(t){var e=this,n=a.f(e),r=n.reject,c=l((function(){var a=i(e.resolve);u(t,(function(t){o(a,e,t).then(n.resolve,r)}))}));return c.error&&r(c.value),n.promise}})},function(t,e,n){"use strict";var r=n(1),o=n(6),i=n(60);r({target:"Promise",stat:!0,forced:n(59).CONSTRUCTOR},{reject:function(t){var e=i.f(this);return o(e.reject,void 0,t),e.promise}})},function(t,e,n){"use strict";var r=n(1),o=n(13),i=n(16),a=n(43),l=n(59).CONSTRUCTOR,u=n(161),c=o("Promise"),s=i&&!l;r({target:"Promise",stat:!0,forced:i||l},{resolve:function(t){return u(s&&this===c?a:this,t)}})},function(t,e,n){var r=n(1),o=n(241);r({target:"Object",stat:!0,arity:2,forced:Object.assign!==o},{assign:o})},function(t,e,n){"use strict";var r=n(7),o=n(2),i=n(6),a=n(3),l=n(74),u=n(78),c=n(107),s=n(17),f=n(50),E=Object.assign,p=Object.defineProperty,h=o([].concat);t.exports=!E||a((function(){if(r&&1!==E({b:1},E(p({},"a",{enumerable:!0,get:function(){p(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var t={},e={},n=Symbol();return t[n]=7,"abcdefghijklmnopqrst".split("").forEach((function(t){e[t]=t})),7!=E({},t)[n]||"abcdefghijklmnopqrst"!=l(E({},e)).join("")}))?function(t,e){for(var n=s(t),o=arguments.length,a=1,E=u.f,p=c.f;o>a;)for(var d,v=f(arguments[a++]),A=E?h(l(v),E(v)):l(v),B=A.length,g=0;B>g;)d=A[g++],r&&!i(p,v,d)||(n[d]=v[d]);return n}:E},function(t,e,n){"use strict";var r=n(1),o=n(16),i=n(43),a=n(3),l=n(13),u=n(4),c=n(110),s=n(161),f=n(14),E=i&&i.prototype;if(r({target:"Promise",proto:!0,real:!0,forced:!!i&&a((function(){E.finally.call({then:function(){}},(function(){}))}))},{finally:function(t){var e=c(this,l("Promise")),n=u(t);return this.then(n?function(n){return s(e,t()).then((function(){return n}))}:t,n?function(n){return s(e,t()).then((function(){throw n}))}:t)}}),!o&&u(i)){var p=l("Promise").prototype.finally;E.finally!==p&&f(E,"finally",p,{unsafe:!0})}},function(t,e,n){"use strict";var r=n(1),o=n(0),i=n(6),a=n(2),l=n(16),u=n(7),c=n(40),s=n(3),f=n(9),E=n(33),p=n(11),h=n(18),d=n(73),v=n(15),A=n(41),B=n(27),g=n(74),m=n(47),y=n(162),b=n(78),C=n(34),x=n(12),F=n(142),w=n(107),_=n(14),P=n(39),O=n(76),k=n(55),D=n(70),S=n(5),j=n(164),T=n(83),M=n(245),$=n(29),L=n(37),U=n(48).forEach,R=O("hidden"),I=L.set,N=L.getterFor("Symbol"),z=Object.prototype,V=o.Symbol,q=V&&V.prototype,G=o.TypeError,W=o.QObject,H=C.f,X=x.f,Y=y.f,K=w.f,J=a([].push),Q=P("symbols"),Z=P("op-symbols"),tt=P("wks"),et=!W||!W.prototype||!W.prototype.findChild,nt=u&&s((function(){return 7!=B(X({},"a",{get:function(){return X(this,"a",{value:7}).a}})).a}))?function(t,e,n){var r=H(z,e);r&&delete z[e],X(t,e,n),r&&t!==z&&X(z,e,r)}:X,rt=function(t,e){var n=Q[t]=B(q);return I(n,{type:"Symbol",tag:t,description:e}),u||(n.description=e),n},ot=function(t,e,n){t===z&&ot(Z,e,n),p(t);var r=d(e);return p(n),f(Q,r)?(n.enumerable?(f(t,R)&&t[R][r]&&(t[R][r]=!1),n=B(n,{enumerable:A(0,!1)})):(f(t,R)||X(t,R,A(1,{})),t[R][r]=!0),nt(t,r,n)):X(t,r,n)},it=function(t,e){p(t);var n=h(e),r=g(n).concat(ct(n));return U(r,(function(e){u&&!i(at,n,e)||ot(t,e,n[e])})),t},at=function(t){var e=d(t),n=i(K,this,e);return!(this===z&&f(Q,e)&&!f(Z,e))&&(!(n||!f(this,e)||!f(Q,e)||f(this,R)&&this[R][e])||n)},lt=function(t,e){var n=h(t),r=d(e);if(n!==z||!f(Q,r)||f(Z,r)){var o=H(n,r);return!o||!f(Q,r)||f(n,R)&&n[R][r]||(o.enumerable=!0),o}},ut=function(t){var e=Y(h(t)),n=[];return U(e,(function(t){f(Q,t)||f(k,t)||J(n,t)})),n},ct=function(t){var e=t===z,n=Y(e?Z:h(t)),r=[];return U(n,(function(t){!f(Q,t)||e&&!f(z,t)||J(r,Q[t])})),r};c||(_(q=(V=function(){if(E(q,this))throw G("Symbol is not a constructor");var t=arguments.length&&void 0!==arguments[0]?v(arguments[0]):void 0,e=D(t),n=function(t){this===z&&i(n,Z,t),f(this,R)&&f(this[R],e)&&(this[R][e]=!1),nt(this,e,A(1,t))};return u&&et&&nt(z,e,{configurable:!0,set:n}),rt(e,t)}).prototype,"toString",(function(){return N(this).tag})),_(V,"withoutSetter",(function(t){return rt(D(t),t)})),w.f=at,x.f=ot,F.f=it,C.f=lt,m.f=y.f=ut,b.f=ct,j.f=function(t){return rt(S(t),t)},u&&(X(q,"description",{configurable:!0,get:function(){return N(this).description}}),l||_(z,"propertyIsEnumerable",at,{unsafe:!0}))),r({global:!0,constructor:!0,wrap:!0,forced:!c,sham:!c},{Symbol:V}),U(g(tt),(function(t){T(t)})),r({target:"Symbol",stat:!0,forced:!c},{useSetter:function(){et=!0},useSimple:function(){et=!1}}),r({target:"Object",stat:!0,forced:!c,sham:!u},{create:function(t,e){return void 0===e?B(t):it(B(t),e)},defineProperty:ot,defineProperties:it,getOwnPropertyDescriptor:lt}),r({target:"Object",stat:!0,forced:!c},{getOwnPropertyNames:ut}),M(),$(V,"Symbol"),k[R]=!0},function(t,e,n){var r=n(0);t.exports=r},function(t,e,n){var r=n(6),o=n(13),i=n(5),a=n(14);t.exports=function(){var t=o("Symbol"),e=t&&t.prototype,n=e&&e.valueOf,l=i("toPrimitive");e&&!e[l]&&a(e,l,(function(t){return r(n,this)}),{arity:1})}},function(t,e,n){var r=n(0),o=n(44),i=n(80),a=n(8),l=n(5)("species"),u=r.Array;t.exports=function(t){var e;return o(t)&&(e=t.constructor,(i(e)&&(e===u||o(e.prototype))||a(e)&&null===(e=e[l]))&&(e=void 0)),void 0===e?u:e}},function(t,e,n){var r=n(1),o=n(13),i=n(9),a=n(15),l=n(39),u=n(166),c=l("string-to-symbol-registry"),s=l("symbol-to-string-registry");r({target:"Symbol",stat:!0,forced:!u},{for:function(t){var e=a(t);if(i(c,e))return c[e];var n=o("Symbol")(e);return c[e]=n,s[n]=e,n}})},function(t,e,n){var r=n(1),o=n(9),i=n(53),a=n(54),l=n(39),u=n(166),c=l("symbol-to-string-registry");r({target:"Symbol",stat:!0,forced:!u},{keyFor:function(t){if(!i(t))throw TypeError(a(t)+" is not a symbol");if(o(c,t))return c[t]}})},function(t,e,n){var r=n(1),o=n(40),i=n(3),a=n(78),l=n(17);r({target:"Object",stat:!0,forced:!o||i((function(){a.f(1)}))},{getOwnPropertySymbols:function(t){var e=a.f;return e?e(l(t)):[]}})},function(t,e,n){"use strict";var r=n(111),o=n(81);t.exports=r?{}.toString:function(){return"[object "+o(this)+"]"}},function(t,e,n){n(83)("asyncIterator")},function(t,e,n){var r=n(13),o=n(83),i=n(29);o("toStringTag"),i(r("Symbol"),"Symbol")},function(t,e,n){var r=n(0);n(29)(r.JSON,"JSON",!0)},function(t,e,n){n(29)(Math,"Math",!0)},function(t,e,n){"use strict";var r=n(13),o=n(9),i=n(20),a=n(33),l=n(57),u=n(108),c=n(212),s=n(133),f=n(171),E=n(256),p=n(257),h=n(258),d=n(7),v=n(16);t.exports=function(t,e,n,A){var B=A?2:1,g=t.split("."),m=g[g.length-1],y=r.apply(null,g);if(y){var b=y.prototype;if(!v&&o(b,"cause")&&delete b.cause,!n)return y;var C=r("Error"),x=e((function(t,e){var n=f(A?e:t,void 0),r=A?new y(t):new y;return void 0!==n&&i(r,"message",n),h&&i(r,"stack",p(r.stack,2)),this&&a(b,this)&&s(r,this,x),arguments.length>B&&E(r,arguments[B]),r}));if(x.prototype=b,"Error"!==m?l?l(x,C):u(x,C,{name:!0}):d&&"stackTraceLimit"in y&&(c(x,y,"stackTraceLimit"),c(x,y,"prepareStackTrace")),u(x,y),!v)try{b.name!==m&&i(b,"name",m),b.constructor=x}catch(t){}return x}}},function(t,e,n){var r=n(8),o=n(20);t.exports=function(t,e){r(e)&&"cause"in e&&o(t,"cause",e.cause)}},function(t,e,n){var r=n(2),o=Error,i=r("".replace),a=String(o("zxcasd").stack),l=/\n\s*at [^:]*:[^\n]*/,u=l.test(a);t.exports=function(t,e){if(u&&"string"==typeof t&&!o.prepareStackTrace)for(;e--;)t=i(t,l,"");return t}},function(t,e,n){var r=n(3),o=n(41);t.exports=!r((function(){var t=Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",o(1,7)),7!==t.stack)}))},function(t,e,n){"use strict";var r=n(7),o=n(3),i=n(11),a=n(27),l=n(171),u=Error.prototype.toString,c=o((function(){if(r){var t=a(Object.defineProperty({},"name",{get:function(){return this===t}}));if("true"!==u.call(t))return!0}return"2: 1"!==u.call({message:1,name:2})||"Error"!==u.call({})}));t.exports=c?function(){var t=i(this),e=l(t.name,"Error"),n=l(t.message);return e?n?e+": "+n:e:n}:u},function(t,e,n){"use strict";var r=n(1),o=n(2),i=n(44),a=o([].reverse),l=[1,2];r({target:"Array",proto:!0,forced:String(l)===String(l.reverse())},{reverse:function(){return i(this)&&(this.length=this.length),a(this)}})},function(t,e,n){var r=n(1),o=n(7),i=n(149),a=n(18),l=n(34),u=n(62);r({target:"Object",stat:!0,sham:!o},{getOwnPropertyDescriptors:function(t){for(var e,n,r=a(t),o=l.f,c=i(r),s={},f=0;c.length>f;)void 0!==(n=o(r,e=c[f++]))&&u(s,e,n);return s}})},function(t,e,n){"use strict";var r=n(1),o=n(263).left,i=n(64),a=n(52),l=n(79);r({target:"Array",proto:!0,forced:!i("reduce")||!l&&a>79&&a<83},{reduce:function(t){var e=arguments.length;return o(this,t,e,e>1?arguments[1]:void 0)}})},function(t,e,n){var r=n(0),o=n(22),i=n(17),a=n(50),l=n(28),u=r.TypeError,c=function(t){return function(e,n,r,c){o(n);var s=i(e),f=a(s),E=l(s),p=t?E-1:0,h=t?-1:1;if(r<2)for(;;){if(p in f){c=f[p],p+=h;break}if(p+=h,t?p<0:E<=p)throw u("Reduce of empty array with no initial value")}for(;t?p>=0:E>p;p+=h)p in f&&(c=n(c,f[p],p,s));return c}};t.exports={left:c(!1),right:c(!0)}},function(t,e,n){"use strict";var r,o=n(1),i=n(2),a=n(34).f,l=n(69),u=n(15),c=n(134),s=n(25),f=n(136),E=n(16),p=i("".startsWith),h=i("".slice),d=Math.min,v=f("startsWith");o({target:"String",proto:!0,forced:!!(E||v||(r=a(String.prototype,"startsWith"),!r||r.writable))&&!v},{startsWith:function(t){var e=u(s(this));c(t);var n=l(d(arguments.length>1?arguments[1]:void 0,e.length)),r=u(t);return p?p(e,r,n):h(e,n,n+r.length)===r}})},function(t,e,n){var r=n(1),o=n(173),i=n(3),a=n(8),l=n(266).onFreeze,u=Object.freeze;r({target:"Object",stat:!0,forced:i((function(){u(1)})),sham:!o},{freeze:function(t){return u&&a(t)?u(l(t)):t}})},function(t,e,n){var r=n(1),o=n(2),i=n(55),a=n(8),l=n(9),u=n(12).f,c=n(47),s=n(162),f=n(267),E=n(70),p=n(173),h=!1,d=E("meta"),v=0,A=function(t){u(t,d,{value:{objectID:"O"+v++,weakData:{}}})},B=t.exports={enable:function(){B.enable=function(){},h=!0;var t=c.f,e=o([].splice),n={};n[d]=1,t(n).length&&(c.f=function(n){for(var r=t(n),o=0,i=r.length;o<i;o++)if(r[o]===d){e(r,o,1);break}return r},r({target:"Object",stat:!0,forced:!0},{getOwnPropertyNames:s.f}))},fastKey:function(t,e){if(!a(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!l(t,d)){if(!f(t))return"F";if(!e)return"E";A(t)}return t[d].objectID},getWeakData:function(t,e){if(!l(t,d)){if(!f(t))return!0;if(!e)return!1;A(t)}return t[d].weakData},onFreeze:function(t){return p&&h&&f(t)&&!l(t,d)&&A(t),t}};i[d]=!0},function(t,e,n){var r=n(3),o=n(8),i=n(26),a=n(268),l=Object.isExtensible,u=r((function(){l(1)}));t.exports=u||a?function(t){return!!o(t)&&((!a||"ArrayBuffer"!=i(t))&&(!l||l(t)))}:l},function(t,e,n){var r=n(3);t.exports=r((function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}}))},function(t,e,n){"use strict";var r=n(0),o=n(58),i=n(6),a=n(17),l=n(270),u=n(156),c=n(80),s=n(28),f=n(62),E=n(157),p=n(113),h=r.Array;t.exports=function(t){var e=a(t),n=c(this),r=arguments.length,d=r>1?arguments[1]:void 0,v=void 0!==d;v&&(d=o(d,r>2?arguments[2]:void 0));var A,B,g,m,y,b,C=p(e),x=0;if(!C||this==h&&u(C))for(A=s(e),B=n?new this(A):h(A);A>x;x++)b=v?d(e[x],x):e[x],f(B,x,b);else for(y=(m=E(e,C)).next,B=n?new this:[];!(g=i(y,m)).done;x++)b=v?l(m,d,[g.value,x],!0):g.value,f(B,x,b);return B.length=x,B}},function(t,e,n){var r=n(11),o=n(158);t.exports=function(t,e,n,i){try{return i?e(r(n)[0],n[1]):e(n)}catch(e){o(t,"throw",e)}}},function(t,e,n){var r=n(2),o=n(17),i=Math.floor,a=r("".charAt),l=r("".replace),u=r("".slice),c=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,s=/\$([$&'`]|\d{1,2})/g;t.exports=function(t,e,n,r,f,E){var p=n+t.length,h=r.length,d=s;return void 0!==f&&(f=o(f),d=c),l(E,d,(function(o,l){var c;switch(a(l,0)){case"$":return"$";case"&":return t;case"`":return u(e,0,n);case"'":return u(e,p);case"<":c=f[u(l,1,-1)];break;default:var s=+l;if(0===s)return o;if(s>h){var E=i(s/10);return 0===E?o:E<=h?void 0===r[E-1]?a(l,1):r[E-1]+a(l,1):o}c=r[s-1]}return void 0===c?"":c}))}},function(t,e,n){var r=n(175),o=n(273);t.exports=function t(e,n,i,a,l){var u=-1,c=e.length;for(i||(i=o),l||(l=[]);++u<c;){var s=e[u];n>0&&i(s)?n>1?t(s,n-1,i,a,l):r(l,s):a||(l[l.length]=s)}return l}},function(t,e,n){var r=n(66),o=n(118),i=n(21),a=r?r.isConcatSpreadable:void 0;t.exports=function(t){return i(t)||o(t)||!!(a&&t&&t[a])}},function(t,e,n){var r=n(49),o=n(38);t.exports=function(t){return o(t)&&"[object Arguments]"==r(t)}},function(t,e,n){var r=n(66),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,l=r?r.toStringTag:void 0;t.exports=function(t){var e=i.call(t,l),n=t[l];try{t[l]=void 0;var r=!0}catch(t){}var o=a.call(t);return r&&(e?t[l]=n:delete t[l]),o}},function(t,e){var n=Object.prototype.toString;t.exports=function(t){return n.call(t)}},function(t,e,n){var r=n(278),o=n(334),i=n(126),a=n(21),l=n(344);t.exports=function(t){return"function"==typeof t?t:null==t?i:"object"==typeof t?a(t)?o(t[0],t[1]):r(t):l(t)}},function(t,e,n){var r=n(279),o=n(333),i=n(193);t.exports=function(t){var e=o(t);return 1==e.length&&e[0][2]?i(e[0][0],e[0][1]):function(n){return n===t||r(n,t,e)}}},function(t,e,n){var r=n(177),o=n(181);t.exports=function(t,e,n,i){var a=n.length,l=a,u=!i;if(null==t)return!l;for(t=Object(t);a--;){var c=n[a];if(u&&c[2]?c[1]!==t[c[0]]:!(c[0]in t))return!1}for(;++a<l;){var s=(c=n[a])[0],f=t[s],E=c[1];if(u&&c[2]){if(void 0===f&&!(s in t))return!1}else{var p=new r;if(i)var h=i(f,E,s,t,e,p);if(!(void 0===h?o(E,f,3,i,p):h))return!1}}return!0}},function(t,e){t.exports=function(){this.__data__=[],this.size=0}},function(t,e,n){var r=n(89),o=Array.prototype.splice;t.exports=function(t){var e=this.__data__,n=r(e,t);return!(n<0)&&(n==e.length-1?e.pop():o.call(e,n,1),--this.size,!0)}},function(t,e,n){var r=n(89);t.exports=function(t){var e=this.__data__,n=r(e,t);return n<0?void 0:e[n][1]}},function(t,e,n){var r=n(89);t.exports=function(t){return r(this.__data__,t)>-1}},function(t,e,n){var r=n(89);t.exports=function(t,e){var n=this.__data__,o=r(n,t);return o<0?(++this.size,n.push([t,e])):n[o][1]=e,this}},function(t,e,n){var r=n(88);t.exports=function(){this.__data__=new r,this.size=0}},function(t,e){t.exports=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n}},function(t,e){t.exports=function(t){return this.__data__.get(t)}},function(t,e){t.exports=function(t){return this.__data__.has(t)}},function(t,e,n){var r=n(88),o=n(119),i=n(121);t.exports=function(t,e){var n=this.__data__;if(n instanceof r){var a=n.__data__;if(!o||a.length<199)return a.push([t,e]),this.size=++n.size,this;n=this.__data__=new i(a)}return n.set(t,e),this.size=n.size,this}},function(t,e,n){var r=n(179),o=n(291),i=n(120),a=n(180),l=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,s=u.toString,f=c.hasOwnProperty,E=RegExp("^"+s.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(t){return!(!i(t)||o(t))&&(r(t)?E:l).test(a(t))}},function(t,e,n){var r,o=n(292),i=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";t.exports=function(t){return!!i&&i in t}},function(t,e,n){var r=n(24)["__core-js_shared__"];t.exports=r},function(t,e){t.exports=function(t,e){return null==t?void 0:t[e]}},function(t,e,n){var r=n(295),o=n(88),i=n(119);t.exports=function(){this.size=0,this.__data__={hash:new r,map:new(i||o),string:new r}}},function(t,e,n){var r=n(296),o=n(297),i=n(298),a=n(299),l=n(300);function u(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e<n;){var r=t[e];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=o,u.prototype.get=i,u.prototype.has=a,u.prototype.set=l,t.exports=u},function(t,e,n){var r=n(90);t.exports=function(){this.__data__=r?r(null):{},this.size=0}},function(t,e){t.exports=function(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}},function(t,e,n){var r=n(90),o=Object.prototype.hasOwnProperty;t.exports=function(t){var e=this.__data__;if(r){var n=e[t];return"__lodash_hash_undefined__"===n?void 0:n}return o.call(e,t)?e[t]:void 0}},function(t,e,n){var r=n(90),o=Object.prototype.hasOwnProperty;t.exports=function(t){var e=this.__data__;return r?void 0!==e[t]:o.call(e,t)}},function(t,e,n){var r=n(90);t.exports=function(t,e){var n=this.__data__;return this.size+=this.has(t)?0:1,n[t]=r&&void 0===e?"__lodash_hash_undefined__":e,this}},function(t,e,n){var r=n(91);t.exports=function(t){var e=r(this,t).delete(t);return this.size-=e?1:0,e}},function(t,e){t.exports=function(t){var e=typeof t;return"string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t}},function(t,e,n){var r=n(91);t.exports=function(t){return r(this,t).get(t)}},function(t,e,n){var r=n(91);t.exports=function(t){return r(this,t).has(t)}},function(t,e,n){var r=n(91);t.exports=function(t,e){var n=r(this,t),o=n.size;return n.set(t,e),this.size+=n.size==o?0:1,this}},function(t,e,n){var r=n(177),o=n(182),i=n(310),a=n(313),l=n(329),u=n(21),c=n(186),s=n(189),f="[object Object]",E=Object.prototype.hasOwnProperty;t.exports=function(t,e,n,p,h,d){var v=u(t),A=u(e),B=v?"[object Array]":l(t),g=A?"[object Array]":l(e),m=(B="[object Arguments]"==B?f:B)==f,y=(g="[object Arguments]"==g?f:g)==f,b=B==g;if(b&&c(t)){if(!c(e))return!1;v=!0,m=!1}if(b&&!m)return d||(d=new r),v||s(t)?o(t,e,n,p,h,d):i(t,e,B,n,p,h,d);if(!(1&n)){var C=m&&E.call(t,"__wrapped__"),x=y&&E.call(e,"__wrapped__");if(C||x){var F=C?t.value():t,w=x?e.value():e;return d||(d=new r),h(F,w,n,p,d)}}return!!b&&(d||(d=new r),a(t,e,n,p,h,d))}},function(t,e){t.exports=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this}},function(t,e){t.exports=function(t){return this.__data__.has(t)}},function(t,e){t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length;++n<r;)if(e(t[n],n,t))return!0;return!1}},function(t,e,n){var r=n(66),o=n(311),i=n(178),a=n(182),l=n(312),u=n(122),c=r?r.prototype:void 0,s=c?c.valueOf:void 0;t.exports=function(t,e,n,r,c,f,E){switch(n){case"[object DataView]":if(t.byteLength!=e.byteLength||t.byteOffset!=e.byteOffset)return!1;t=t.buffer,e=e.buffer;case"[object ArrayBuffer]":return!(t.byteLength!=e.byteLength||!f(new o(t),new o(e)));case"[object Boolean]":case"[object Date]":case"[object Number]":return i(+t,+e);case"[object Error]":return t.name==e.name&&t.message==e.message;case"[object RegExp]":case"[object String]":return t==e+"";case"[object Map]":var p=l;case"[object Set]":var h=1&r;if(p||(p=u),t.size!=e.size&&!h)return!1;var d=E.get(t);if(d)return d==e;r|=2,E.set(t,e);var v=a(p(t),p(e),r,c,f,E);return E.delete(t),v;case"[object Symbol]":if(s)return s.call(t)==s.call(e)}return!1}},function(t,e,n){var r=n(24).Uint8Array;t.exports=r},function(t,e){t.exports=function(t){var e=-1,n=Array(t.size);return t.forEach((function(t,r){n[++e]=[r,t]})),n}},function(t,e,n){var r=n(314),o=Object.prototype.hasOwnProperty;t.exports=function(t,e,n,i,a,l){var u=1&n,c=r(t),s=c.length;if(s!=r(e).length&&!u)return!1;for(var f=s;f--;){var E=c[f];if(!(u?E in e:o.call(e,E)))return!1}var p=l.get(t),h=l.get(e);if(p&&h)return p==e&&h==t;var d=!0;l.set(t,e),l.set(e,t);for(var v=u;++f<s;){var A=t[E=c[f]],B=e[E];if(i)var g=u?i(B,A,E,e,t,l):i(A,B,E,t,e,l);if(!(void 0===g?A===B||a(A,B,n,i,l):g)){d=!1;break}v||(v="constructor"==E)}if(d&&!v){var m=t.constructor,y=e.constructor;m==y||!("constructor"in t)||!("constructor"in e)||"function"==typeof m&&m instanceof m&&"function"==typeof y&&y instanceof y||(d=!1)}return l.delete(t),l.delete(e),d}},function(t,e,n){var r=n(315),o=n(316),i=n(185);t.exports=function(t){return r(t,i,o)}},function(t,e,n){var r=n(175),o=n(21);t.exports=function(t,e,n){var i=e(t);return o(t)?i:r(i,n(t))}},function(t,e,n){var r=n(317),o=n(318),i=Object.prototype.propertyIsEnumerable,a=Object.getOwnPropertySymbols,l=a?function(t){return null==t?[]:(t=Object(t),r(a(t),(function(e){return i.call(t,e)})))}:o;t.exports=l},function(t,e){t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,o=0,i=[];++n<r;){var a=t[n];e(a,n,t)&&(i[o++]=a)}return i}},function(t,e){t.exports=function(){return[]}},function(t,e,n){var r=n(320),o=n(118),i=n(21),a=n(186),l=n(188),u=n(189),c=Object.prototype.hasOwnProperty;t.exports=function(t,e){var n=i(t),s=!n&&o(t),f=!n&&!s&&a(t),E=!n&&!s&&!f&&u(t),p=n||s||f||E,h=p?r(t.length,String):[],d=h.length;for(var v in t)!e&&!c.call(t,v)||p&&("length"==v||f&&("offset"==v||"parent"==v)||E&&("buffer"==v||"byteLength"==v||"byteOffset"==v)||l(v,d))||h.push(v);return h}},function(t,e){t.exports=function(t,e){for(var n=-1,r=Array(t);++n<t;)r[n]=e(n);return r}},function(t,e){t.exports=function(){return!1}},function(t,e,n){var r=n(49),o=n(123),i=n(38),a={};a["[object Float32Array]"]=a["[object Float64Array]"]=a["[object Int8Array]"]=a["[object Int16Array]"]=a["[object Int32Array]"]=a["[object Uint8Array]"]=a["[object Uint8ClampedArray]"]=a["[object Uint16Array]"]=a["[object Uint32Array]"]=!0,a["[object Arguments]"]=a["[object Array]"]=a["[object ArrayBuffer]"]=a["[object Boolean]"]=a["[object DataView]"]=a["[object Date]"]=a["[object Error]"]=a["[object Function]"]=a["[object Map]"]=a["[object Number]"]=a["[object Object]"]=a["[object RegExp]"]=a["[object Set]"]=a["[object String]"]=a["[object WeakMap]"]=!1,t.exports=function(t){return i(t)&&o(t.length)&&!!a[r(t)]}},function(t,e){t.exports=function(t){return function(e){return t(e)}}},function(t,e,n){(function(t){var r=n(176),o=e&&!e.nodeType&&e,i=o&&"object"==typeof t&&t&&!t.nodeType&&t,a=i&&i.exports===o&&r.process,l=function(){try{var t=i&&i.require&&i.require("util").types;return t||a&&a.binding&&a.binding("util")}catch(t){}}();t.exports=l}).call(this,n(187)(t))},function(t,e,n){var r=n(326),o=n(327),i=Object.prototype.hasOwnProperty;t.exports=function(t){if(!r(t))return o(t);var e=[];for(var n in Object(t))i.call(t,n)&&"constructor"!=n&&e.push(n);return e}},function(t,e){var n=Object.prototype;t.exports=function(t){var e=t&&t.constructor;return t===("function"==typeof e&&e.prototype||n)}},function(t,e,n){var r=n(328)(Object.keys,Object);t.exports=r},function(t,e){t.exports=function(t,e){return function(n){return t(e(n))}}},function(t,e,n){var r=n(330),o=n(119),i=n(331),a=n(191),l=n(332),u=n(49),c=n(180),s=c(r),f=c(o),E=c(i),p=c(a),h=c(l),d=u;(r&&"[object DataView]"!=d(new r(new ArrayBuffer(1)))||o&&"[object Map]"!=d(new o)||i&&"[object Promise]"!=d(i.resolve())||a&&"[object Set]"!=d(new a)||l&&"[object WeakMap]"!=d(new l))&&(d=function(t){var e=u(t),n="[object Object]"==e?t.constructor:void 0,r=n?c(n):"";if(r)switch(r){case s:return"[object DataView]";case f:return"[object Map]";case E:return"[object Promise]";case p:return"[object Set]";case h:return"[object WeakMap]"}return e}),t.exports=d},function(t,e,n){var r=n(35)(n(24),"DataView");t.exports=r},function(t,e,n){var r=n(35)(n(24),"Promise");t.exports=r},function(t,e,n){var r=n(35)(n(24),"WeakMap");t.exports=r},function(t,e,n){var r=n(192),o=n(185);t.exports=function(t){for(var e=o(t),n=e.length;n--;){var i=e[n],a=t[i];e[n]=[i,a,r(a)]}return e}},function(t,e,n){var r=n(181),o=n(218),i=n(341),a=n(124),l=n(192),u=n(193),c=n(92);t.exports=function(t,e){return a(t)&&l(e)?u(c(t),e):function(n){var a=o(n,t);return void 0===a&&a===e?i(n,t):r(e,a,3)}}},function(t,e,n){var r=n(336),o=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,i=/\\(\\)?/g,a=r((function(t){var e=[];return 46===t.charCodeAt(0)&&e.push(""),t.replace(o,(function(t,n,r,o){e.push(r?o.replace(i,"$1"):n||t)})),e}));t.exports=a},function(t,e,n){var r=n(337);t.exports=function(t){var e=r(t,(function(t){return 500===n.size&&n.clear(),t})),n=e.cache;return e}},function(t,e,n){var r=n(121);function o(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new TypeError("Expected a function");var n=function(){var r=arguments,o=e?e.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=t.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(o.Cache||r),n}o.Cache=r,t.exports=o},function(t,e,n){var r=n(339);t.exports=function(t){return null==t?"":r(t)}},function(t,e,n){var r=n(66),o=n(340),i=n(21),a=n(125),l=r?r.prototype:void 0,u=l?l.toString:void 0;t.exports=function t(e){if("string"==typeof e)return e;if(i(e))return o(e,t)+"";if(a(e))return u?u.call(e):"";var n=e+"";return"0"==n&&1/e==-1/0?"-0":n}},function(t,e){t.exports=function(t,e){for(var n=-1,r=null==t?0:t.length,o=Array(r);++n<r;)o[n]=e(t[n],n,t);return o}},function(t,e,n){var r=n(342),o=n(343);t.exports=function(t,e){return null!=t&&o(t,e,r)}},function(t,e){t.exports=function(t,e){return null!=t&&e in Object(t)}},function(t,e,n){var r=n(195),o=n(118),i=n(21),a=n(188),l=n(123),u=n(92);t.exports=function(t,e,n){for(var c=-1,s=(e=r(e,t)).length,f=!1;++c<s;){var E=u(e[c]);if(!(f=null!=t&&n(t,E)))break;t=t[E]}return f||++c!=s?f:!!(s=null==t?0:t.length)&&l(s)&&a(E,s)&&(i(t)||o(t))}},function(t,e,n){var r=n(345),o=n(346),i=n(124),a=n(92);t.exports=function(t){return i(t)?r(a(t)):o(t)}},function(t,e){t.exports=function(t){return function(e){return null==e?void 0:e[t]}}},function(t,e,n){var r=n(194);t.exports=function(t){return function(e){return r(e,t)}}},function(t,e,n){var r=n(126),o=n(348),i=n(350);t.exports=function(t,e){return i(o(t,e,r),t+"")}},function(t,e,n){var r=n(349),o=Math.max;t.exports=function(t,e,n){return e=o(void 0===e?t.length-1:e,0),function(){for(var i=arguments,a=-1,l=o(i.length-e,0),u=Array(l);++a<l;)u[a]=i[e+a];a=-1;for(var c=Array(e+1);++a<e;)c[a]=i[a];return c[e]=n(u),r(t,this,c)}}},function(t,e){t.exports=function(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}},function(t,e,n){var r=n(351),o=n(354)(r);t.exports=o},function(t,e,n){var r=n(352),o=n(353),i=n(126),a=o?function(t,e){return o(t,"toString",{configurable:!0,enumerable:!1,value:r(e),writable:!0})}:i;t.exports=a},function(t,e){t.exports=function(t){return function(){return t}}},function(t,e,n){var r=n(35),o=function(){try{var t=r(Object,"defineProperty");return t({},"",{}),t}catch(t){}}();t.exports=o},function(t,e){var n=Date.now;t.exports=function(t){var e=0,r=0;return function(){var o=n(),i=16-(o-r);if(r=o,i>0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}},function(t,e,n){var r=n(183),o=n(356),i=n(361),a=n(184),l=n(362),u=n(122);t.exports=function(t,e,n){var c=-1,s=o,f=t.length,E=!0,p=[],h=p;if(n)E=!1,s=i;else if(f>=200){var d=e?null:l(t);if(d)return u(d);E=!1,s=a,h=new r}else h=e?[]:p;t:for(;++c<f;){var v=t[c],A=e?e(v):v;if(v=n||0!==v?v:0,E&&A==A){for(var B=h.length;B--;)if(h[B]===A)continue t;e&&h.push(A),p.push(v)}else s(h,A,n)||(h!==p&&h.push(A),p.push(v))}return p}},function(t,e,n){var r=n(357);t.exports=function(t,e){return!!(null==t?0:t.length)&&r(t,e,0)>-1}},function(t,e,n){var r=n(358),o=n(359),i=n(360);t.exports=function(t,e,n){return e==e?i(t,e,n):r(t,o,n)}},function(t,e){t.exports=function(t,e,n,r){for(var o=t.length,i=n+(r?1:-1);r?i--:++i<o;)if(e(t[i],i,t))return i;return-1}},function(t,e){t.exports=function(t){return t!=t}},function(t,e){t.exports=function(t,e,n){for(var r=n-1,o=t.length;++r<o;)if(t[r]===e)return r;return-1}},function(t,e){t.exports=function(t,e,n){for(var r=-1,o=null==t?0:t.length;++r<o;)if(n(e,t[r]))return!0;return!1}},function(t,e,n){var r=n(191),o=n(363),i=n(122),a=r&&1/i(new r([,-0]))[1]==1/0?function(t){return new r(t)}:o;t.exports=a},function(t,e){t.exports=function(){}},function(t,e,n){var r=n(190),o=n(38);t.exports=function(t){return o(t)&&r(t)}},function(t,e,n){},function(t,e,n){},function(t,e,n){var r=n(2),o=n(14),i=Date.prototype,a=r(i.toString),l=r(i.getTime);"Invalid Date"!=String(new Date(NaN))&&o(i,"toString",(function(){var t=l(this);return t==t?a(this):"Invalid Date"}))},function(t,e,n){"use strict";var r=n(7),o=n(0),i=n(2),a=n(101),l=n(14),u=n(9),c=n(133),s=n(33),f=n(53),E=n(145),p=n(3),h=n(47).f,d=n(34).f,v=n(12).f,A=n(369),B=n(207).trim,g=o.Number,m=g.prototype,y=o.TypeError,b=i("".slice),C=i("".charCodeAt),x=function(t){var e=E(t,"number");return"bigint"==typeof e?e:F(e)},F=function(t){var e,n,r,o,i,a,l,u,c=E(t,"number");if(f(c))throw y("Cannot convert a Symbol value to a number");if("string"==typeof c&&c.length>2)if(c=B(c),43===(e=C(c,0))||45===e){if(88===(n=C(c,2))||120===n)return NaN}else if(48===e){switch(C(c,1)){case 66:case 98:r=2,o=49;break;case 79:case 111:r=8,o=55;break;default:return+c}for(a=(i=b(c,2)).length,l=0;l<a;l++)if((u=C(i,l))<48||u>o)return NaN;return parseInt(i,r)}return+c};if(a("Number",!g(" 0o1")||!g("0b1")||g("+0x1"))){for(var w,_=function(t){var e=arguments.length<1?0:g(x(t)),n=this;return s(m,n)&&p((function(){A(n)}))?c(Object(e),n,_):e},P=r?h(g):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,fromString,range".split(","),O=0;P.length>O;O++)u(g,w=P[O])&&!u(_,w)&&v(_,w,d(g,w));_.prototype=m,m.constructor=_,l(o,"Number",_,{constructor:!0})}},function(t,e,n){var r=n(2);t.exports=r(1..valueOf)},function(t,e,n){"use strict";n(196)},function(t,e,n){},function(t,e,n){"use strict";var r=n(0),o=n(2),i=n(22),a=n(8),l=n(9),u=n(82),c=n(51),s=r.Function,f=o([].concat),E=o([].join),p={},h=function(t,e,n){if(!l(p,e)){for(var r=[],o=0;o<e;o++)r[o]="a["+o+"]";p[e]=s("C,a","return new C("+E(r,",")+")")}return p[e](t,n)};t.exports=c?s.bind:function(t){var e=i(this),n=e.prototype,r=u(arguments,1),o=function(){var n=f(r,u(arguments));return this instanceof o?h(e,n.length,n):e.apply(t,n)};return a(n)&&(o.prototype=n),o}},function(t,e,n){"use strict";n(199)},function(t,e,n){"use strict";n(200)},function(t,e,n){"use strict";n.r(e);n(140),n(225),n(240),n(242),n(61),n(63),n(10),n(84),n(19),n(23),n(251),n(252),n(253),n(254),n(114),n(115),n(30),n(31),n(116),n(99),n(100),n(85),n(117),n(260),n(65);function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(){ +/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ +o=function(){return t};var t={},e=Object.prototype,n=e.hasOwnProperty,i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",l=i.asyncIterator||"@@asyncIterator",u=i.toStringTag||"@@toStringTag";function c(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,n){return t[e]=n}}function s(t,e,n,r){var o=e&&e.prototype instanceof p?e:p,i=Object.create(o.prototype),a=new F(r||[]);return i._invoke=function(t,e,n){var r="suspendedStart";return function(o,i){if("executing"===r)throw new Error("Generator is already running");if("completed"===r){if("throw"===o)throw i;return _()}for(n.method=o,n.arg=i;;){var a=n.delegate;if(a){var l=b(a,n);if(l){if(l===E)continue;return l}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if("suspendedStart"===r)throw r="completed",n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);r="executing";var u=f(t,e,n);if("normal"===u.type){if(r=n.done?"completed":"suspendedYield",u.arg===E)continue;return{value:u.arg,done:n.done}}"throw"===u.type&&(r="completed",n.method="throw",n.arg=u.arg)}}}(t,n,a),i}function f(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}t.wrap=s;var E={};function p(){}function h(){}function d(){}var v={};c(v,a,(function(){return this}));var A=Object.getPrototypeOf,B=A&&A(A(w([])));B&&B!==e&&n.call(B,a)&&(v=B);var g=d.prototype=p.prototype=Object.create(v);function m(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function y(t,e){var o;this._invoke=function(i,a){function l(){return new e((function(o,l){!function o(i,a,l,u){var c=f(t[i],t,a);if("throw"!==c.type){var s=c.arg,E=s.value;return E&&"object"==r(E)&&n.call(E,"__await")?e.resolve(E.__await).then((function(t){o("next",t,l,u)}),(function(t){o("throw",t,l,u)})):e.resolve(E).then((function(t){s.value=t,l(s)}),(function(t){return o("throw",t,l,u)}))}u(c.arg)}(i,a,o,l)}))}return o=o?o.then(l,l):l()}}function b(t,e){var n=t.iterator[e.method];if(void 0===n){if(e.delegate=null,"throw"===e.method){if(t.iterator.return&&(e.method="return",e.arg=void 0,b(t,e),"throw"===e.method))return E;e.method="throw",e.arg=new TypeError("The iterator does not provide a 'throw' method")}return E}var r=f(n,t.iterator,e.arg);if("throw"===r.type)return e.method="throw",e.arg=r.arg,e.delegate=null,E;var o=r.arg;return o?o.done?(e[t.resultName]=o.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=void 0),e.delegate=null,E):o:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,E)}function C(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function x(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function F(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(C,this),this.reset(!0)}function w(t){if(t){var e=t[a];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,o=function e(){for(;++r<t.length;)if(n.call(t,r))return e.value=t[r],e.done=!1,e;return e.value=void 0,e.done=!0,e};return o.next=o}}return{next:_}}function _(){return{value:void 0,done:!0}}return h.prototype=d,c(g,"constructor",d),c(d,"constructor",h),h.displayName=c(d,u,"GeneratorFunction"),t.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===h||"GeneratorFunction"===(e.displayName||e.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,d):(t.__proto__=d,c(t,u,"GeneratorFunction")),t.prototype=Object.create(g),t},t.awrap=function(t){return{__await:t}},m(y.prototype),c(y.prototype,l,(function(){return this})),t.AsyncIterator=y,t.async=function(e,n,r,o,i){void 0===i&&(i=Promise);var a=new y(s(e,n,r,o),i);return t.isGeneratorFunction(n)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},m(g),c(g,u,"Generator"),c(g,a,(function(){return this})),c(g,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var e=[];for(var n in t)e.push(n);return e.reverse(),function n(){for(;e.length;){var r=e.pop();if(r in t)return n.value=r,n.done=!1,n}return n.done=!0,n}},t.values=w,F.prototype={constructor:F,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=void 0,this.done=!1,this.delegate=null,this.method="next",this.arg=void 0,this.tryEntries.forEach(x),!t)for(var e in this)"t"===e.charAt(0)&&n.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=void 0)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function r(n,r){return a.type="throw",a.arg=t,e.next=n,r&&(e.method="next",e.arg=void 0),!!r}for(var o=this.tryEntries.length-1;o>=0;--o){var i=this.tryEntries[o],a=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var l=n.call(i,"catchLoc"),u=n.call(i,"finallyLoc");if(l&&u){if(this.prev<i.catchLoc)return r(i.catchLoc,!0);if(this.prev<i.finallyLoc)return r(i.finallyLoc)}else if(l){if(this.prev<i.catchLoc)return r(i.catchLoc,!0)}else{if(!u)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return r(i.finallyLoc)}}}},abrupt:function(t,e){for(var r=this.tryEntries.length-1;r>=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,E):this.complete(a)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),E},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),x(n),E}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var r=n.completion;if("throw"===r.type){var o=r.arg;x(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:w(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=void 0),E}},t}function i(t,e,n,r,o,i,a){try{var l=t[i](a),u=l.value}catch(t){return void n(t)}l.done?e(u):Promise.resolve(u).then(r,o)}function a(t){return function(){var e=this,n=arguments;return new Promise((function(r,o){var a=t.apply(e,n);function l(t){i(a,r,o,l,u,"next",t)}function u(t){i(a,r,o,l,u,"throw",t)}l(void 0)}))}}n(96),n(45);var l=Object.freeze({});function u(t){return null==t}function c(t){return null!=t}function s(t){return!0===t}function f(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function E(t){return null!==t&&"object"==typeof t}var p=Object.prototype.toString;function h(t){return"[object Object]"===p.call(t)}function d(t){return"[object RegExp]"===p.call(t)}function v(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function A(t){return c(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function B(t){return null==t?"":Array.isArray(t)||h(t)&&t.toString===p?JSON.stringify(t,null,2):String(t)}function g(t){var e=parseFloat(t);return isNaN(e)?t:e}function m(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o<r.length;o++)n[r[o]]=!0;return e?function(t){return n[t.toLowerCase()]}:function(t){return n[t]}}m("slot,component",!0);var y=m("key,ref,slot,slot-scope,is");function b(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(n,1)}}var C=Object.prototype.hasOwnProperty;function x(t,e){return C.call(t,e)}function F(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var w=/-(\w)/g,_=F((function(t){return t.replace(w,(function(t,e){return e?e.toUpperCase():""}))})),P=F((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),O=/\B([A-Z])/g,k=F((function(t){return t.replace(O,"-$1").toLowerCase()}));var D=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function S(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function j(t,e){for(var n in e)t[n]=e[n];return t}function T(t){for(var e={},n=0;n<t.length;n++)t[n]&&j(e,t[n]);return e}function M(t,e,n){}var $=function(t,e,n){return!1},L=function(t){return t};function U(t,e){if(t===e)return!0;var n=E(t),r=E(e);if(!n||!r)return!n&&!r&&String(t)===String(e);try{var o=Array.isArray(t),i=Array.isArray(e);if(o&&i)return t.length===e.length&&t.every((function(t,n){return U(t,e[n])}));if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(o||i)return!1;var a=Object.keys(t),l=Object.keys(e);return a.length===l.length&&a.every((function(n){return U(t[n],e[n])}))}catch(t){return!1}}function R(t,e){for(var n=0;n<t.length;n++)if(U(t[n],e))return n;return-1}function I(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments))}}var N=["component","directive","filter"],z=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured","serverPrefetch"],V={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:$,isReservedAttr:$,isUnknownElement:$,getTagNamespace:M,parsePlatformTagName:L,mustUseProp:$,async:!0,_lifecycleHooks:z},q=/a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;function G(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,writable:!0,configurable:!0})}var W=new RegExp("[^"+q.source+".$_\\d]");var H,X="__proto__"in{},Y="undefined"!=typeof window,K="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,J=K&&WXEnvironment.platform.toLowerCase(),Q=Y&&window.navigator.userAgent.toLowerCase(),Z=Q&&/msie|trident/.test(Q),tt=Q&&Q.indexOf("msie 9.0")>0,et=Q&&Q.indexOf("edge/")>0,nt=(Q&&Q.indexOf("android"),Q&&/iphone|ipad|ipod|ios/.test(Q)||"ios"===J),rt=(Q&&/chrome\/\d+/.test(Q),Q&&/phantomjs/.test(Q),Q&&Q.match(/firefox\/(\d+)/)),ot={}.watch,it=!1;if(Y)try{var at={};Object.defineProperty(at,"passive",{get:function(){it=!0}}),window.addEventListener("test-passive",null,at)}catch(t){}var lt=function(){return void 0===H&&(H=!Y&&!K&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),H},ut=Y&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ct(t){return"function"==typeof t&&/native code/.test(t.toString())}var st,ft="undefined"!=typeof Symbol&&ct(Symbol)&&"undefined"!=typeof Reflect&&ct(Reflect.ownKeys);st="undefined"!=typeof Set&&ct(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var Et=M,pt=0,ht=function(){this.id=pt++,this.subs=[]};ht.prototype.addSub=function(t){this.subs.push(t)},ht.prototype.removeSub=function(t){b(this.subs,t)},ht.prototype.depend=function(){ht.target&&ht.target.addDep(this)},ht.prototype.notify=function(){var t=this.subs.slice();for(var e=0,n=t.length;e<n;e++)t[e].update()},ht.target=null;var dt=[];function vt(t){dt.push(t),ht.target=t}function At(){dt.pop(),ht.target=dt[dt.length-1]}var Bt=function(t,e,n,r,o,i,a,l){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=l,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},gt={child:{configurable:!0}};gt.child.get=function(){return this.componentInstance},Object.defineProperties(Bt.prototype,gt);var mt=function(t){void 0===t&&(t="");var e=new Bt;return e.text=t,e.isComment=!0,e};function yt(t){return new Bt(void 0,void 0,void 0,String(t))}function bt(t){var e=new Bt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}var Ct=Array.prototype,xt=Object.create(Ct);["push","pop","shift","unshift","splice","sort","reverse"].forEach((function(t){var e=Ct[t];G(xt,t,(function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var o,i=e.apply(this,n),a=this.__ob__;switch(t){case"push":case"unshift":o=n;break;case"splice":o=n.slice(2)}return o&&a.observeArray(o),a.dep.notify(),i}))}));var Ft=Object.getOwnPropertyNames(xt),wt=!0;function _t(t){wt=t}var Pt=function(t){this.value=t,this.dep=new ht,this.vmCount=0,G(t,"__ob__",this),Array.isArray(t)?(X?function(t,e){t.__proto__=e}(t,xt):function(t,e,n){for(var r=0,o=n.length;r<o;r++){var i=n[r];G(t,i,e[i])}}(t,xt,Ft),this.observeArray(t)):this.walk(t)};function Ot(t,e){var n;if(E(t)&&!(t instanceof Bt))return x(t,"__ob__")&&t.__ob__ instanceof Pt?n=t.__ob__:wt&&!lt()&&(Array.isArray(t)||h(t))&&Object.isExtensible(t)&&!t._isVue&&(n=new Pt(t)),e&&n&&n.vmCount++,n}function kt(t,e,n,r,o){var i=new ht,a=Object.getOwnPropertyDescriptor(t,e);if(!a||!1!==a.configurable){var l=a&&a.get,u=a&&a.set;l&&!u||2!==arguments.length||(n=t[e]);var c=!o&&Ot(n);Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){var e=l?l.call(t):n;return ht.target&&(i.depend(),c&&(c.dep.depend(),Array.isArray(e)&&jt(e))),e},set:function(e){var r=l?l.call(t):n;e===r||e!=e&&r!=r||l&&!u||(u?u.call(t,e):n=e,c=!o&&Ot(e),i.notify())}})}}function Dt(t,e,n){if(Array.isArray(t)&&v(e))return t.length=Math.max(t.length,e),t.splice(e,1,n),n;if(e in t&&!(e in Object.prototype))return t[e]=n,n;var r=t.__ob__;return t._isVue||r&&r.vmCount?n:r?(kt(r.value,e,n),r.dep.notify(),n):(t[e]=n,n)}function St(t,e){if(Array.isArray(t)&&v(e))t.splice(e,1);else{var n=t.__ob__;t._isVue||n&&n.vmCount||x(t,e)&&(delete t[e],n&&n.dep.notify())}}function jt(t){for(var e=void 0,n=0,r=t.length;n<r;n++)(e=t[n])&&e.__ob__&&e.__ob__.dep.depend(),Array.isArray(e)&&jt(e)}Pt.prototype.walk=function(t){for(var e=Object.keys(t),n=0;n<e.length;n++)kt(t,e[n])},Pt.prototype.observeArray=function(t){for(var e=0,n=t.length;e<n;e++)Ot(t[e])};var Tt=V.optionMergeStrategies;function Mt(t,e){if(!e)return t;for(var n,r,o,i=ft?Reflect.ownKeys(e):Object.keys(e),a=0;a<i.length;a++)"__ob__"!==(n=i[a])&&(r=t[n],o=e[n],x(t,n)?r!==o&&h(r)&&h(o)&&Mt(r,o):Dt(t,n,o));return t}function $t(t,e,n){return n?function(){var r="function"==typeof e?e.call(n,n):e,o="function"==typeof t?t.call(n,n):t;return r?Mt(r,o):o}:e?t?function(){return Mt("function"==typeof e?e.call(this,this):e,"function"==typeof t?t.call(this,this):t)}:e:t}function Lt(t,e){var n=e?t?t.concat(e):Array.isArray(e)?e:[e]:t;return n?function(t){for(var e=[],n=0;n<t.length;n++)-1===e.indexOf(t[n])&&e.push(t[n]);return e}(n):n}function Ut(t,e,n,r){var o=Object.create(t||null);return e?j(o,e):o}Tt.data=function(t,e,n){return n?$t(t,e,n):e&&"function"!=typeof e?t:$t(t,e)},z.forEach((function(t){Tt[t]=Lt})),N.forEach((function(t){Tt[t+"s"]=Ut})),Tt.watch=function(t,e,n,r){if(t===ot&&(t=void 0),e===ot&&(e=void 0),!e)return Object.create(t||null);if(!t)return e;var o={};for(var i in j(o,t),e){var a=o[i],l=e[i];a&&!Array.isArray(a)&&(a=[a]),o[i]=a?a.concat(l):Array.isArray(l)?l:[l]}return o},Tt.props=Tt.methods=Tt.inject=Tt.computed=function(t,e,n,r){if(!t)return e;var o=Object.create(null);return j(o,t),e&&j(o,e),o},Tt.provide=$t;var Rt=function(t,e){return void 0===e?t:e};function It(t,e,n){if("function"==typeof e&&(e=e.options),function(t,e){var n=t.props;if(n){var r,o,i={};if(Array.isArray(n))for(r=n.length;r--;)"string"==typeof(o=n[r])&&(i[_(o)]={type:null});else if(h(n))for(var a in n)o=n[a],i[_(a)]=h(o)?o:{type:o};else 0;t.props=i}}(e),function(t,e){var n=t.inject;if(n){var r=t.inject={};if(Array.isArray(n))for(var o=0;o<n.length;o++)r[n[o]]={from:n[o]};else if(h(n))for(var i in n){var a=n[i];r[i]=h(a)?j({from:i},a):{from:a}}else 0}}(e),function(t){var e=t.directives;if(e)for(var n in e){var r=e[n];"function"==typeof r&&(e[n]={bind:r,update:r})}}(e),!e._base&&(e.extends&&(t=It(t,e.extends,n)),e.mixins))for(var r=0,o=e.mixins.length;r<o;r++)t=It(t,e.mixins[r],n);var i,a={};for(i in t)l(i);for(i in e)x(t,i)||l(i);function l(r){var o=Tt[r]||Rt;a[r]=o(t[r],e[r],n,r)}return a}function Nt(t,e,n,r){if("string"==typeof n){var o=t[e];if(x(o,n))return o[n];var i=_(n);if(x(o,i))return o[i];var a=P(i);return x(o,a)?o[a]:o[n]||o[i]||o[a]}}function zt(t,e,n,r){var o=e[t],i=!x(n,t),a=n[t],l=Wt(Boolean,o.type);if(l>-1)if(i&&!x(o,"default"))a=!1;else if(""===a||a===k(t)){var u=Wt(String,o.type);(u<0||l<u)&&(a=!0)}if(void 0===a){a=function(t,e,n){if(!x(e,"default"))return;var r=e.default;0;if(t&&t.$options.propsData&&void 0===t.$options.propsData[n]&&void 0!==t._props[n])return t._props[n];return"function"==typeof r&&"Function"!==qt(e.type)?r.call(t):r}(r,o,t);var c=wt;_t(!0),Ot(a),_t(c)}return a}var Vt=/^\s*function (\w+)/;function qt(t){var e=t&&t.toString().match(Vt);return e?e[1]:""}function Gt(t,e){return qt(t)===qt(e)}function Wt(t,e){if(!Array.isArray(e))return Gt(e,t)?0:-1;for(var n=0,r=e.length;n<r;n++)if(Gt(e[n],t))return n;return-1}function Ht(t,e,n){vt();try{if(e)for(var r=e;r=r.$parent;){var o=r.$options.errorCaptured;if(o)for(var i=0;i<o.length;i++)try{if(!1===o[i].call(r,t,e,n))return}catch(t){Yt(t,r,"errorCaptured hook")}}Yt(t,e,n)}finally{At()}}function Xt(t,e,n,r,o){var i;try{(i=n?t.apply(e,n):t.call(e))&&!i._isVue&&A(i)&&!i._handled&&(i.catch((function(t){return Ht(t,r,o+" (Promise/async)")})),i._handled=!0)}catch(t){Ht(t,r,o)}return i}function Yt(t,e,n){if(V.errorHandler)try{return V.errorHandler.call(null,t,e,n)}catch(e){e!==t&&Kt(e,null,"config.errorHandler")}Kt(t,e,n)}function Kt(t,e,n){if(!Y&&!K||"undefined"==typeof console)throw t;console.error(t)}var Jt,Qt=!1,Zt=[],te=!1;function ee(){te=!1;var t=Zt.slice(0);Zt.length=0;for(var e=0;e<t.length;e++)t[e]()}if("undefined"!=typeof Promise&&ct(Promise)){var ne=Promise.resolve();Jt=function(){ne.then(ee),nt&&setTimeout(M)},Qt=!0}else if(Z||"undefined"==typeof MutationObserver||!ct(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())Jt="undefined"!=typeof setImmediate&&ct(setImmediate)?function(){setImmediate(ee)}:function(){setTimeout(ee,0)};else{var re=1,oe=new MutationObserver(ee),ie=document.createTextNode(String(re));oe.observe(ie,{characterData:!0}),Jt=function(){re=(re+1)%2,ie.data=String(re)},Qt=!0}function ae(t,e){var n;if(Zt.push((function(){if(t)try{t.call(e)}catch(t){Ht(t,e,"nextTick")}else n&&n(e)})),te||(te=!0,Jt()),!t&&"undefined"!=typeof Promise)return new Promise((function(t){n=t}))}var le=new st;function ue(t){!function t(e,n){var r,o,i=Array.isArray(e);if(!i&&!E(e)||Object.isFrozen(e)||e instanceof Bt)return;if(e.__ob__){var a=e.__ob__.dep.id;if(n.has(a))return;n.add(a)}if(i)for(r=e.length;r--;)t(e[r],n);else for(o=Object.keys(e),r=o.length;r--;)t(e[o[r]],n)}(t,le),le.clear()}var ce=F((function(t){var e="&"===t.charAt(0),n="~"===(t=e?t.slice(1):t).charAt(0),r="!"===(t=n?t.slice(1):t).charAt(0);return{name:t=r?t.slice(1):t,once:n,capture:r,passive:e}}));function se(t,e){function n(){var t=arguments,r=n.fns;if(!Array.isArray(r))return Xt(r,null,arguments,e,"v-on handler");for(var o=r.slice(),i=0;i<o.length;i++)Xt(o[i],null,t,e,"v-on handler")}return n.fns=t,n}function fe(t,e,n,r,o,i){var a,l,c,f;for(a in t)l=t[a],c=e[a],f=ce(a),u(l)||(u(c)?(u(l.fns)&&(l=t[a]=se(l,i)),s(f.once)&&(l=t[a]=o(f.name,l,f.capture)),n(f.name,l,f.capture,f.passive,f.params)):l!==c&&(c.fns=l,t[a]=c));for(a in e)u(t[a])&&r((f=ce(a)).name,e[a],f.capture)}function Ee(t,e,n){var r;t instanceof Bt&&(t=t.data.hook||(t.data.hook={}));var o=t[e];function i(){n.apply(this,arguments),b(r.fns,i)}u(o)?r=se([i]):c(o.fns)&&s(o.merged)?(r=o).fns.push(i):r=se([o,i]),r.merged=!0,t[e]=r}function pe(t,e,n,r,o){if(c(e)){if(x(e,n))return t[n]=e[n],o||delete e[n],!0;if(x(e,r))return t[n]=e[r],o||delete e[r],!0}return!1}function he(t){return f(t)?[yt(t)]:Array.isArray(t)?function t(e,n){var r,o,i,a,l=[];for(r=0;r<e.length;r++)u(o=e[r])||"boolean"==typeof o||(i=l.length-1,a=l[i],Array.isArray(o)?o.length>0&&(de((o=t(o,(n||"")+"_"+r))[0])&&de(a)&&(l[i]=yt(a.text+o[0].text),o.shift()),l.push.apply(l,o)):f(o)?de(a)?l[i]=yt(a.text+o):""!==o&&l.push(yt(o)):de(o)&&de(a)?l[i]=yt(a.text+o.text):(s(e._isVList)&&c(o.tag)&&u(o.key)&&c(n)&&(o.key="__vlist"+n+"_"+r+"__"),l.push(o)));return l}(t):void 0}function de(t){return c(t)&&c(t.text)&&!1===t.isComment}function ve(t,e){if(t){for(var n=Object.create(null),r=ft?Reflect.ownKeys(t):Object.keys(t),o=0;o<r.length;o++){var i=r[o];if("__ob__"!==i){for(var a=t[i].from,l=e;l;){if(l._provided&&x(l._provided,a)){n[i]=l._provided[a];break}l=l.$parent}if(!l)if("default"in t[i]){var u=t[i].default;n[i]="function"==typeof u?u.call(e):u}else 0}}return n}}function Ae(t,e){if(!t||!t.length)return{};for(var n={},r=0,o=t.length;r<o;r++){var i=t[r],a=i.data;if(a&&a.attrs&&a.attrs.slot&&delete a.attrs.slot,i.context!==e&&i.fnContext!==e||!a||null==a.slot)(n.default||(n.default=[])).push(i);else{var l=a.slot,u=n[l]||(n[l]=[]);"template"===i.tag?u.push.apply(u,i.children||[]):u.push(i)}}for(var c in n)n[c].every(Be)&&delete n[c];return n}function Be(t){return t.isComment&&!t.asyncFactory||" "===t.text}function ge(t){return t.isComment&&t.asyncFactory}function me(t,e,n){var r,o=Object.keys(e).length>0,i=t?!!t.$stable:!o,a=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(i&&n&&n!==l&&a===n.$key&&!o&&!n.$hasNormal)return n;for(var u in r={},t)t[u]&&"$"!==u[0]&&(r[u]=ye(e,u,t[u]))}else r={};for(var c in e)c in r||(r[c]=be(e,c));return t&&Object.isExtensible(t)&&(t._normalized=r),G(r,"$stable",i),G(r,"$key",a),G(r,"$hasNormal",o),r}function ye(t,e,n){var r=function(){var t=arguments.length?n.apply(null,arguments):n({}),e=(t=t&&"object"==typeof t&&!Array.isArray(t)?[t]:he(t))&&t[0];return t&&(!e||1===t.length&&e.isComment&&!ge(e))?void 0:t};return n.proxy&&Object.defineProperty(t,e,{get:r,enumerable:!0,configurable:!0}),r}function be(t,e){return function(){return t[e]}}function Ce(t,e){var n,r,o,i,a;if(Array.isArray(t)||"string"==typeof t)for(n=new Array(t.length),r=0,o=t.length;r<o;r++)n[r]=e(t[r],r);else if("number"==typeof t)for(n=new Array(t),r=0;r<t;r++)n[r]=e(r+1,r);else if(E(t))if(ft&&t[Symbol.iterator]){n=[];for(var l=t[Symbol.iterator](),u=l.next();!u.done;)n.push(e(u.value,n.length)),u=l.next()}else for(i=Object.keys(t),n=new Array(i.length),r=0,o=i.length;r<o;r++)a=i[r],n[r]=e(t[a],a,r);return c(n)||(n=[]),n._isVList=!0,n}function xe(t,e,n,r){var o,i=this.$scopedSlots[t];i?(n=n||{},r&&(n=j(j({},r),n)),o=i(n)||("function"==typeof e?e():e)):o=this.$slots[t]||("function"==typeof e?e():e);var a=n&&n.slot;return a?this.$createElement("template",{slot:a},o):o}function Fe(t){return Nt(this.$options,"filters",t)||L}function we(t,e){return Array.isArray(t)?-1===t.indexOf(e):t!==e}function _e(t,e,n,r,o){var i=V.keyCodes[e]||n;return o&&r&&!V.keyCodes[e]?we(o,r):i?we(i,t):r?k(r)!==e:void 0===t}function Pe(t,e,n,r,o){if(n)if(E(n)){var i;Array.isArray(n)&&(n=T(n));var a=function(a){if("class"===a||"style"===a||y(a))i=t;else{var l=t.attrs&&t.attrs.type;i=r||V.mustUseProp(e,l,a)?t.domProps||(t.domProps={}):t.attrs||(t.attrs={})}var u=_(a),c=k(a);u in i||c in i||(i[a]=n[a],o&&((t.on||(t.on={}))["update:"+a]=function(t){n[a]=t}))};for(var l in n)a(l)}else;return t}function Oe(t,e){var n=this._staticTrees||(this._staticTrees=[]),r=n[t];return r&&!e||De(r=n[t]=this.$options.staticRenderFns[t].call(this._renderProxy,null,this),"__static__"+t,!1),r}function ke(t,e,n){return De(t,"__once__"+e+(n?"_"+n:""),!0),t}function De(t,e,n){if(Array.isArray(t))for(var r=0;r<t.length;r++)t[r]&&"string"!=typeof t[r]&&Se(t[r],e+"_"+r,n);else Se(t,e,n)}function Se(t,e,n){t.isStatic=!0,t.key=e,t.isOnce=n}function je(t,e){if(e)if(h(e)){var n=t.on=t.on?j({},t.on):{};for(var r in e){var o=n[r],i=e[r];n[r]=o?[].concat(o,i):i}}else;return t}function Te(t,e,n,r){e=e||{$stable:!n};for(var o=0;o<t.length;o++){var i=t[o];Array.isArray(i)?Te(i,e,n):i&&(i.proxy&&(i.fn.proxy=!0),e[i.key]=i.fn)}return r&&(e.$key=r),e}function Me(t,e){for(var n=0;n<e.length;n+=2){var r=e[n];"string"==typeof r&&r&&(t[e[n]]=e[n+1])}return t}function $e(t,e){return"string"==typeof t?e+t:t}function Le(t){t._o=ke,t._n=g,t._s=B,t._l=Ce,t._t=xe,t._q=U,t._i=R,t._m=Oe,t._f=Fe,t._k=_e,t._b=Pe,t._v=yt,t._e=mt,t._u=Te,t._g=je,t._d=Me,t._p=$e}function Ue(t,e,n,r,o){var i,a=this,u=o.options;x(r,"_uid")?(i=Object.create(r))._original=r:(i=r,r=r._original);var c=s(u._compiled),f=!c;this.data=t,this.props=e,this.children=n,this.parent=r,this.listeners=t.on||l,this.injections=ve(u.inject,r),this.slots=function(){return a.$slots||me(t.scopedSlots,a.$slots=Ae(n,r)),a.$slots},Object.defineProperty(this,"scopedSlots",{enumerable:!0,get:function(){return me(t.scopedSlots,this.slots())}}),c&&(this.$options=u,this.$slots=this.slots(),this.$scopedSlots=me(t.scopedSlots,this.$slots)),u._scopeId?this._c=function(t,e,n,o){var a=Ge(i,t,e,n,o,f);return a&&!Array.isArray(a)&&(a.fnScopeId=u._scopeId,a.fnContext=r),a}:this._c=function(t,e,n,r){return Ge(i,t,e,n,r,f)}}function Re(t,e,n,r,o){var i=bt(t);return i.fnContext=n,i.fnOptions=r,e.slot&&((i.data||(i.data={})).slot=e.slot),i}function Ie(t,e){for(var n in e)t[_(n)]=e[n]}Le(Ue.prototype);var Ne={init:function(t,e){if(t.componentInstance&&!t.componentInstance._isDestroyed&&t.data.keepAlive){var n=t;Ne.prepatch(n,n)}else{(t.componentInstance=function(t,e){var n={_isComponent:!0,_parentVnode:t,parent:e},r=t.data.inlineTemplate;c(r)&&(n.render=r.render,n.staticRenderFns=r.staticRenderFns);return new t.componentOptions.Ctor(n)}(t,tn)).$mount(e?t.elm:void 0,e)}},prepatch:function(t,e){var n=e.componentOptions;!function(t,e,n,r,o){0;var i=r.data.scopedSlots,a=t.$scopedSlots,u=!!(i&&!i.$stable||a!==l&&!a.$stable||i&&t.$scopedSlots.$key!==i.$key||!i&&t.$scopedSlots.$key),c=!!(o||t.$options._renderChildren||u);t.$options._parentVnode=r,t.$vnode=r,t._vnode&&(t._vnode.parent=r);if(t.$options._renderChildren=o,t.$attrs=r.data.attrs||l,t.$listeners=n||l,e&&t.$options.props){_t(!1);for(var s=t._props,f=t.$options._propKeys||[],E=0;E<f.length;E++){var p=f[E],h=t.$options.props;s[p]=zt(p,h,e,t)}_t(!0),t.$options.propsData=e}n=n||l;var d=t.$options._parentListeners;t.$options._parentListeners=n,Ze(t,n,d),c&&(t.$slots=Ae(o,r.context),t.$forceUpdate());0}(e.componentInstance=t.componentInstance,n.propsData,n.listeners,e,n.children)},insert:function(t){var e,n=t.context,r=t.componentInstance;r._isMounted||(r._isMounted=!0,on(r,"mounted")),t.data.keepAlive&&(n._isMounted?((e=r)._inactive=!1,ln.push(e)):rn(r,!0))},destroy:function(t){var e=t.componentInstance;e._isDestroyed||(t.data.keepAlive?function t(e,n){if(n&&(e._directInactive=!0,nn(e)))return;if(!e._inactive){e._inactive=!0;for(var r=0;r<e.$children.length;r++)t(e.$children[r]);on(e,"deactivated")}}(e,!0):e.$destroy())}},ze=Object.keys(Ne);function Ve(t,e,n,r,o){if(!u(t)){var i=n.$options._base;if(E(t)&&(t=i.extend(t)),"function"==typeof t){var a;if(u(t.cid)&&void 0===(t=function(t,e){if(s(t.error)&&c(t.errorComp))return t.errorComp;if(c(t.resolved))return t.resolved;var n=He;n&&c(t.owners)&&-1===t.owners.indexOf(n)&&t.owners.push(n);if(s(t.loading)&&c(t.loadingComp))return t.loadingComp;if(n&&!c(t.owners)){var r=t.owners=[n],o=!0,i=null,a=null;n.$on("hook:destroyed",(function(){return b(r,n)}));var l=function(t){for(var e=0,n=r.length;e<n;e++)r[e].$forceUpdate();t&&(r.length=0,null!==i&&(clearTimeout(i),i=null),null!==a&&(clearTimeout(a),a=null))},f=I((function(n){t.resolved=Xe(n,e),o?r.length=0:l(!0)})),p=I((function(e){c(t.errorComp)&&(t.error=!0,l(!0))})),h=t(f,p);return E(h)&&(A(h)?u(t.resolved)&&h.then(f,p):A(h.component)&&(h.component.then(f,p),c(h.error)&&(t.errorComp=Xe(h.error,e)),c(h.loading)&&(t.loadingComp=Xe(h.loading,e),0===h.delay?t.loading=!0:i=setTimeout((function(){i=null,u(t.resolved)&&u(t.error)&&(t.loading=!0,l(!1))}),h.delay||200)),c(h.timeout)&&(a=setTimeout((function(){a=null,u(t.resolved)&&p(null)}),h.timeout)))),o=!1,t.loading?t.loadingComp:t.resolved}}(a=t,i)))return function(t,e,n,r,o){var i=mt();return i.asyncFactory=t,i.asyncMeta={data:e,context:n,children:r,tag:o},i}(a,e,n,r,o);e=e||{},_n(t),c(e.model)&&function(t,e){var n=t.model&&t.model.prop||"value",r=t.model&&t.model.event||"input";(e.attrs||(e.attrs={}))[n]=e.model.value;var o=e.on||(e.on={}),i=o[r],a=e.model.callback;c(i)?(Array.isArray(i)?-1===i.indexOf(a):i!==a)&&(o[r]=[a].concat(i)):o[r]=a}(t.options,e);var f=function(t,e,n){var r=e.options.props;if(!u(r)){var o={},i=t.attrs,a=t.props;if(c(i)||c(a))for(var l in r){var s=k(l);pe(o,a,l,s,!0)||pe(o,i,l,s,!1)}return o}}(e,t);if(s(t.options.functional))return function(t,e,n,r,o){var i=t.options,a={},u=i.props;if(c(u))for(var s in u)a[s]=zt(s,u,e||l);else c(n.attrs)&&Ie(a,n.attrs),c(n.props)&&Ie(a,n.props);var f=new Ue(n,a,o,r,t),E=i.render.call(null,f._c,f);if(E instanceof Bt)return Re(E,n,f.parent,i,f);if(Array.isArray(E)){for(var p=he(E)||[],h=new Array(p.length),d=0;d<p.length;d++)h[d]=Re(p[d],n,f.parent,i,f);return h}}(t,f,e,n,r);var p=e.on;if(e.on=e.nativeOn,s(t.options.abstract)){var h=e.slot;e={},h&&(e.slot=h)}!function(t){for(var e=t.hook||(t.hook={}),n=0;n<ze.length;n++){var r=ze[n],o=e[r],i=Ne[r];o===i||o&&o._merged||(e[r]=o?qe(i,o):i)}}(e);var d=t.options.name||o;return new Bt("vue-component-"+t.cid+(d?"-"+d:""),e,void 0,void 0,void 0,n,{Ctor:t,propsData:f,listeners:p,tag:o,children:r},a)}}}function qe(t,e){var n=function(n,r){t(n,r),e(n,r)};return n._merged=!0,n}function Ge(t,e,n,r,o,i){return(Array.isArray(n)||f(n))&&(o=r,r=n,n=void 0),s(i)&&(o=2),function(t,e,n,r,o){if(c(n)&&c(n.__ob__))return mt();c(n)&&c(n.is)&&(e=n.is);if(!e)return mt();0;Array.isArray(r)&&"function"==typeof r[0]&&((n=n||{}).scopedSlots={default:r[0]},r.length=0);2===o?r=he(r):1===o&&(r=function(t){for(var e=0;e<t.length;e++)if(Array.isArray(t[e]))return Array.prototype.concat.apply([],t);return t}(r));var i,a;if("string"==typeof e){var l;a=t.$vnode&&t.$vnode.ns||V.getTagNamespace(e),i=V.isReservedTag(e)?new Bt(V.parsePlatformTagName(e),n,r,void 0,void 0,t):n&&n.pre||!c(l=Nt(t.$options,"components",e))?new Bt(e,n,r,void 0,void 0,t):Ve(l,n,t,r,e)}else i=Ve(e,n,t,r);return Array.isArray(i)?i:c(i)?(c(a)&&function t(e,n,r){e.ns=n,"foreignObject"===e.tag&&(n=void 0,r=!0);if(c(e.children))for(var o=0,i=e.children.length;o<i;o++){var a=e.children[o];c(a.tag)&&(u(a.ns)||s(r)&&"svg"!==a.tag)&&t(a,n,r)}}(i,a),c(n)&&function(t){E(t.style)&&ue(t.style);E(t.class)&&ue(t.class)}(n),i):mt()}(t,e,n,r,o)}var We,He=null;function Xe(t,e){return(t.__esModule||ft&&"Module"===t[Symbol.toStringTag])&&(t=t.default),E(t)?e.extend(t):t}function Ye(t){if(Array.isArray(t))for(var e=0;e<t.length;e++){var n=t[e];if(c(n)&&(c(n.componentOptions)||ge(n)))return n}}function Ke(t,e){We.$on(t,e)}function Je(t,e){We.$off(t,e)}function Qe(t,e){var n=We;return function r(){var o=e.apply(null,arguments);null!==o&&n.$off(t,r)}}function Ze(t,e,n){We=t,fe(e,n||{},Ke,Je,Qe,t),We=void 0}var tn=null;function en(t){var e=tn;return tn=t,function(){tn=e}}function nn(t){for(;t&&(t=t.$parent);)if(t._inactive)return!0;return!1}function rn(t,e){if(e){if(t._directInactive=!1,nn(t))return}else if(t._directInactive)return;if(t._inactive||null===t._inactive){t._inactive=!1;for(var n=0;n<t.$children.length;n++)rn(t.$children[n]);on(t,"activated")}}function on(t,e){vt();var n=t.$options[e],r=e+" hook";if(n)for(var o=0,i=n.length;o<i;o++)Xt(n[o],t,null,t,r);t._hasHookEvent&&t.$emit("hook:"+e),At()}var an=[],ln=[],un={},cn=!1,sn=!1,fn=0;var En=0,pn=Date.now;if(Y&&!Z){var hn=window.performance;hn&&"function"==typeof hn.now&&pn()>document.createEvent("Event").timeStamp&&(pn=function(){return hn.now()})}function dn(){var t,e;for(En=pn(),sn=!0,an.sort((function(t,e){return t.id-e.id})),fn=0;fn<an.length;fn++)(t=an[fn]).before&&t.before(),e=t.id,un[e]=null,t.run();var n=ln.slice(),r=an.slice();fn=an.length=ln.length=0,un={},cn=sn=!1,function(t){for(var e=0;e<t.length;e++)t[e]._inactive=!0,rn(t[e],!0)}(n),function(t){var e=t.length;for(;e--;){var n=t[e],r=n.vm;r._watcher===n&&r._isMounted&&!r._isDestroyed&&on(r,"updated")}}(r),ut&&V.devtools&&ut.emit("flush")}var vn=0,An=function(t,e,n,r,o){this.vm=t,o&&(t._watcher=this),t._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++vn,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new st,this.newDepIds=new st,this.expression="","function"==typeof e?this.getter=e:(this.getter=function(t){if(!W.test(t)){var e=t.split(".");return function(t){for(var n=0;n<e.length;n++){if(!t)return;t=t[e[n]]}return t}}}(e),this.getter||(this.getter=M)),this.value=this.lazy?void 0:this.get()};An.prototype.get=function(){var t;vt(this);var e=this.vm;try{t=this.getter.call(e,e)}catch(t){if(!this.user)throw t;Ht(t,e,'getter for watcher "'+this.expression+'"')}finally{this.deep&&ue(t),At(),this.cleanupDeps()}return t},An.prototype.addDep=function(t){var e=t.id;this.newDepIds.has(e)||(this.newDepIds.add(e),this.newDeps.push(t),this.depIds.has(e)||t.addSub(this))},An.prototype.cleanupDeps=function(){for(var t=this.deps.length;t--;){var e=this.deps[t];this.newDepIds.has(e.id)||e.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},An.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():function(t){var e=t.id;if(null==un[e]){if(un[e]=!0,sn){for(var n=an.length-1;n>fn&&an[n].id>t.id;)n--;an.splice(n+1,0,t)}else an.push(t);cn||(cn=!0,ae(dn))}}(this)},An.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||E(t)||this.deep){var e=this.value;if(this.value=t,this.user){var n='callback for watcher "'+this.expression+'"';Xt(this.cb,this.vm,[t,e],this.vm,n)}else this.cb.call(this.vm,t,e)}}},An.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},An.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},An.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||b(this.vm._watchers,this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1}};var Bn={enumerable:!0,configurable:!0,get:M,set:M};function gn(t,e,n){Bn.get=function(){return this[e][n]},Bn.set=function(t){this[e][n]=t},Object.defineProperty(t,n,Bn)}function mn(t){t._watchers=[];var e=t.$options;e.props&&function(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[];t.$parent&&_t(!1);var i=function(i){o.push(i);var a=zt(i,e,n,t);kt(r,i,a),i in t||gn(t,"_props",i)};for(var a in e)i(a);_t(!0)}(t,e.props),e.methods&&function(t,e){t.$options.props;for(var n in e)t[n]="function"!=typeof e[n]?M:D(e[n],t)}(t,e.methods),e.data?function(t){var e=t.$options.data;h(e=t._data="function"==typeof e?function(t,e){vt();try{return t.call(e,e)}catch(t){return Ht(t,e,"data()"),{}}finally{At()}}(e,t):e||{})||(e={});var n=Object.keys(e),r=t.$options.props,o=(t.$options.methods,n.length);for(;o--;){var i=n[o];0,r&&x(r,i)||(a=void 0,36!==(a=(i+"").charCodeAt(0))&&95!==a&&gn(t,"_data",i))}var a;Ot(e,!0)}(t):Ot(t._data={},!0),e.computed&&function(t,e){var n=t._computedWatchers=Object.create(null),r=lt();for(var o in e){var i=e[o],a="function"==typeof i?i:i.get;0,r||(n[o]=new An(t,a||M,M,yn)),o in t||bn(t,o,i)}}(t,e.computed),e.watch&&e.watch!==ot&&function(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o<r.length;o++)Fn(t,n,r[o]);else Fn(t,n,r)}}(t,e.watch)}var yn={lazy:!0};function bn(t,e,n){var r=!lt();"function"==typeof n?(Bn.get=r?Cn(e):xn(n),Bn.set=M):(Bn.get=n.get?r&&!1!==n.cache?Cn(e):xn(n.get):M,Bn.set=n.set||M),Object.defineProperty(t,e,Bn)}function Cn(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),ht.target&&e.depend(),e.value}}function xn(t){return function(){return t.call(this,this)}}function Fn(t,e,n,r){return h(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=t[n]),t.$watch(e,n,r)}var wn=0;function _n(t){var e=t.options;if(t.super){var n=_n(t.super);if(n!==t.superOptions){t.superOptions=n;var r=function(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!==r[o]&&(e||(e={}),e[o]=n[o]);return e}(t);r&&j(t.extendOptions,r),(e=t.options=It(n,t.extendOptions)).name&&(e.components[e.name]=t)}}return e}function Pn(t){this._init(t)}function On(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];var i=t.name||n.options.name;var a=function(t){this._init(t)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=e++,a.options=It(n.options,t),a.super=n,a.options.props&&function(t){var e=t.options.props;for(var n in e)gn(t.prototype,"_props",n)}(a),a.options.computed&&function(t){var e=t.options.computed;for(var n in e)bn(t.prototype,n,e[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,N.forEach((function(t){a[t]=n[t]})),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=j({},a.options),o[r]=a,a}}function kn(t){return t&&(t.Ctor.options.name||t.tag)}function Dn(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Sn(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a=n[i];if(a){var l=a.name;l&&!e(l)&&jn(n,i,r,o)}}}function jn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,b(n,e)}Pn.prototype._init=function(t){var e=this;e._uid=wn++,e._isVue=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=It(_n(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Ze(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,r=n&&n.context;t.$slots=Ae(e._renderChildren,r),t.$scopedSlots=l,t._c=function(e,n,r,o){return Ge(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return Ge(t,e,n,r,o,!0)};var o=n&&n.data;kt(t,"$attrs",o&&o.attrs||l,null,!0),kt(t,"$listeners",e._parentListeners||l,null,!0)}(e),on(e,"beforeCreate"),function(t){var e=ve(t.$options.inject,t);e&&(_t(!1),Object.keys(e).forEach((function(n){kt(t,n,e[n])})),_t(!0))}(e),mn(e),function(t){var e=t.$options.provide;e&&(t._provided="function"==typeof e?e.call(t):e)}(e),on(e,"created"),e.$options.el&&e.$mount(e.$options.el)},function(t){var e={get:function(){return this._data}},n={get:function(){return this._props}};Object.defineProperty(t.prototype,"$data",e),Object.defineProperty(t.prototype,"$props",n),t.prototype.$set=Dt,t.prototype.$delete=St,t.prototype.$watch=function(t,e,n){if(h(e))return Fn(this,t,e,n);(n=n||{}).user=!0;var r=new An(this,t,e,n);if(n.immediate){var o='callback for immediate watcher "'+r.expression+'"';vt(),Xt(e,this,[r.value],this,o),At()}return function(){r.teardown()}}}(Pn),function(t){var e=/^hook:/;t.prototype.$on=function(t,n){var r=this;if(Array.isArray(t))for(var o=0,i=t.length;o<i;o++)r.$on(t[o],n);else(r._events[t]||(r._events[t]=[])).push(n),e.test(t)&&(r._hasHookEvent=!0);return r},t.prototype.$once=function(t,e){var n=this;function r(){n.$off(t,r),e.apply(n,arguments)}return r.fn=e,n.$on(t,r),n},t.prototype.$off=function(t,e){var n=this;if(!arguments.length)return n._events=Object.create(null),n;if(Array.isArray(t)){for(var r=0,o=t.length;r<o;r++)n.$off(t[r],e);return n}var i,a=n._events[t];if(!a)return n;if(!e)return n._events[t]=null,n;for(var l=a.length;l--;)if((i=a[l])===e||i.fn===e){a.splice(l,1);break}return n},t.prototype.$emit=function(t){var e=this,n=e._events[t];if(n){n=n.length>1?S(n):n;for(var r=S(arguments,1),o='event handler for "'+t+'"',i=0,a=n.length;i<a;i++)Xt(n[i],e,r,e,o)}return e}}(Pn),function(t){t.prototype._update=function(t,e){var n=this,r=n.$el,o=n._vnode,i=en(n);n._vnode=t,n.$el=o?n.__patch__(o,t):n.__patch__(n.$el,t,e,!1),i(),r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},t.prototype.$forceUpdate=function(){this._watcher&&this._watcher.update()},t.prototype.$destroy=function(){var t=this;if(!t._isBeingDestroyed){on(t,"beforeDestroy"),t._isBeingDestroyed=!0;var e=t.$parent;!e||e._isBeingDestroyed||t.$options.abstract||b(e.$children,t),t._watcher&&t._watcher.teardown();for(var n=t._watchers.length;n--;)t._watchers[n].teardown();t._data.__ob__&&t._data.__ob__.vmCount--,t._isDestroyed=!0,t.__patch__(t._vnode,null),on(t,"destroyed"),t.$off(),t.$el&&(t.$el.__vue__=null),t.$vnode&&(t.$vnode.parent=null)}}}(Pn),function(t){Le(t.prototype),t.prototype.$nextTick=function(t){return ae(t,this)},t.prototype._render=function(){var t,e=this,n=e.$options,r=n.render,o=n._parentVnode;o&&(e.$scopedSlots=me(o.data.scopedSlots,e.$slots,e.$scopedSlots)),e.$vnode=o;try{He=e,t=r.call(e._renderProxy,e.$createElement)}catch(n){Ht(n,e,"render"),t=e._vnode}finally{He=null}return Array.isArray(t)&&1===t.length&&(t=t[0]),t instanceof Bt||(t=mt()),t.parent=o,t}}(Pn);var Tn=[String,RegExp,Array],Mn={KeepAlive:{name:"keep-alive",abstract:!0,props:{include:Tn,exclude:Tn,max:[String,Number]},methods:{cacheVNode:function(){var t=this.cache,e=this.keys,n=this.vnodeToCache,r=this.keyToCache;if(n){var o=n.tag,i=n.componentInstance,a=n.componentOptions;t[r]={name:kn(a),tag:o,componentInstance:i},e.push(r),this.max&&e.length>parseInt(this.max)&&jn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)jn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Sn(t,(function(t){return Dn(e,t)}))})),this.$watch("exclude",(function(e){Sn(t,(function(t){return!Dn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Ye(t),n=e&&e.componentOptions;if(n){var r=kn(n),o=this.include,i=this.exclude;if(o&&(!r||!Dn(o,r))||i&&r&&Dn(i,r))return e;var a=this.cache,l=this.keys,u=null==e.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):e.key;a[u]?(e.componentInstance=a[u].componentInstance,b(l,u),l.push(u)):(this.vnodeToCache=e,this.keyToCache=u),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return V}};Object.defineProperty(t,"config",e),t.util={warn:Et,extend:j,mergeOptions:It,defineReactive:kt},t.set=Dt,t.delete=St,t.nextTick=ae,t.observable=function(t){return Ot(t),t},t.options=Object.create(null),N.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,j(t.options.components,Mn),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=S(arguments,1);return n.unshift(this),"function"==typeof t.install?t.install.apply(t,n):"function"==typeof t&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=It(this.options,t),this}}(t),On(t),function(t){N.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&h(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Pn),Object.defineProperty(Pn.prototype,"$isServer",{get:lt}),Object.defineProperty(Pn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Pn,"FunctionalRenderContext",{value:Ue}),Pn.version="2.6.14";var $n=m("style,class"),Ln=m("input,textarea,option,select,progress"),Un=m("contenteditable,draggable,spellcheck"),Rn=m("events,caret,typing,plaintext-only"),In=m("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),Nn="http://www.w3.org/1999/xlink",zn=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},Vn=function(t){return zn(t)?t.slice(6,t.length):""},qn=function(t){return null==t||!1===t};function Gn(t){for(var e=t.data,n=t,r=t;c(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=Wn(r.data,e));for(;c(n=n.parent);)n&&n.data&&(e=Wn(e,n.data));return function(t,e){if(c(t)||c(e))return Hn(t,Xn(e));return""}(e.staticClass,e.class)}function Wn(t,e){return{staticClass:Hn(t.staticClass,e.staticClass),class:c(t.class)?[t.class,e.class]:e.class}}function Hn(t,e){return t?e?t+" "+e:t:e||""}function Xn(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r<o;r++)c(e=Xn(t[r]))&&""!==e&&(n&&(n+=" "),n+=e);return n}(t):E(t)?function(t){var e="";for(var n in t)t[n]&&(e&&(e+=" "),e+=n);return e}(t):"string"==typeof t?t:""}var Yn={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},Kn=m("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),Jn=m("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignobject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),Qn=function(t){return Kn(t)||Jn(t)};var Zn=Object.create(null);var tr=m("text,number,password,search,email,tel,url");var er=Object.freeze({createElement:function(t,e){var n=document.createElement(t);return"select"!==t||e.data&&e.data.attrs&&void 0!==e.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n},createElementNS:function(t,e){return document.createElementNS(Yn[t],e)},createTextNode:function(t){return document.createTextNode(t)},createComment:function(t){return document.createComment(t)},insertBefore:function(t,e,n){t.insertBefore(e,n)},removeChild:function(t,e){t.removeChild(e)},appendChild:function(t,e){t.appendChild(e)},parentNode:function(t){return t.parentNode},nextSibling:function(t){return t.nextSibling},tagName:function(t){return t.tagName},setTextContent:function(t,e){t.textContent=e},setStyleScope:function(t,e){t.setAttribute(e,"")}}),nr={create:function(t,e){rr(e)},update:function(t,e){t.data.ref!==e.data.ref&&(rr(t,!0),rr(e))},destroy:function(t){rr(t,!0)}};function rr(t,e){var n=t.data.ref;if(c(n)){var r=t.context,o=t.componentInstance||t.elm,i=r.$refs;e?Array.isArray(i[n])?b(i[n],o):i[n]===o&&(i[n]=void 0):t.data.refInFor?Array.isArray(i[n])?i[n].indexOf(o)<0&&i[n].push(o):i[n]=[o]:i[n]=o}}var or=new Bt("",{},[]),ir=["create","activate","update","remove","destroy"];function ar(t,e){return t.key===e.key&&t.asyncFactory===e.asyncFactory&&(t.tag===e.tag&&t.isComment===e.isComment&&c(t.data)===c(e.data)&&function(t,e){if("input"!==t.tag)return!0;var n,r=c(n=t.data)&&c(n=n.attrs)&&n.type,o=c(n=e.data)&&c(n=n.attrs)&&n.type;return r===o||tr(r)&&tr(o)}(t,e)||s(t.isAsyncPlaceholder)&&u(e.asyncFactory.error))}function lr(t,e,n){var r,o,i={};for(r=e;r<=n;++r)c(o=t[r].key)&&(i[o]=r);return i}var ur={create:cr,update:cr,destroy:function(t){cr(t,or)}};function cr(t,e){(t.data.directives||e.data.directives)&&function(t,e){var n,r,o,i=t===or,a=e===or,l=fr(t.data.directives,t.context),u=fr(e.data.directives,e.context),c=[],s=[];for(n in u)r=l[n],o=u[n],r?(o.oldValue=r.value,o.oldArg=r.arg,pr(o,"update",e,t),o.def&&o.def.componentUpdated&&s.push(o)):(pr(o,"bind",e,t),o.def&&o.def.inserted&&c.push(o));if(c.length){var f=function(){for(var n=0;n<c.length;n++)pr(c[n],"inserted",e,t)};i?Ee(e,"insert",f):f()}s.length&&Ee(e,"postpatch",(function(){for(var n=0;n<s.length;n++)pr(s[n],"componentUpdated",e,t)}));if(!i)for(n in l)u[n]||pr(l[n],"unbind",t,t,a)}(t,e)}var sr=Object.create(null);function fr(t,e){var n,r,o=Object.create(null);if(!t)return o;for(n=0;n<t.length;n++)(r=t[n]).modifiers||(r.modifiers=sr),o[Er(r)]=r,r.def=Nt(e.$options,"directives",r.name);return o}function Er(t){return t.rawName||t.name+"."+Object.keys(t.modifiers||{}).join(".")}function pr(t,e,n,r,o){var i=t.def&&t.def[e];if(i)try{i(n.elm,t,n,r,o)}catch(r){Ht(r,n.context,"directive "+t.name+" "+e+" hook")}}var hr=[nr,ur];function dr(t,e){var n=e.componentOptions;if(!(c(n)&&!1===n.Ctor.options.inheritAttrs||u(t.data.attrs)&&u(e.data.attrs))){var r,o,i=e.elm,a=t.data.attrs||{},l=e.data.attrs||{};for(r in c(l.__ob__)&&(l=e.data.attrs=j({},l)),l)o=l[r],a[r]!==o&&vr(i,r,o,e.data.pre);for(r in(Z||et)&&l.value!==a.value&&vr(i,"value",l.value),a)u(l[r])&&(zn(r)?i.removeAttributeNS(Nn,Vn(r)):Un(r)||i.removeAttribute(r))}}function vr(t,e,n,r){r||t.tagName.indexOf("-")>-1?Ar(t,e,n):In(e)?qn(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):Un(e)?t.setAttribute(e,function(t,e){return qn(e)||"false"===e?"false":"contenteditable"===t&&Rn(e)?e:"true"}(e,n)):zn(e)?qn(n)?t.removeAttributeNS(Nn,Vn(e)):t.setAttributeNS(Nn,e,n):Ar(t,e,n)}function Ar(t,e,n){if(qn(n))t.removeAttribute(e);else{if(Z&&!tt&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Br={create:dr,update:dr};function gr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(u(r.staticClass)&&u(r.class)&&(u(o)||u(o.staticClass)&&u(o.class)))){var i=Gn(e),a=n._transitionClasses;c(a)&&(i=Hn(i,Xn(a))),i!==n._prevClass&&(n.setAttribute("class",i),n._prevClass=i)}}var mr,yr={create:gr,update:gr};function br(t,e,n){var r=mr;return function o(){var i=e.apply(null,arguments);null!==i&&Fr(t,o,n,r)}}var Cr=Qt&&!(rt&&Number(rt[1])<=53);function xr(t,e,n,r){if(Cr){var o=En,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}mr.addEventListener(t,e,it?{capture:n,passive:r}:n)}function Fr(t,e,n,r){(r||mr).removeEventListener(t,e._wrapper||e,n)}function wr(t,e){if(!u(t.data.on)||!u(e.data.on)){var n=e.data.on||{},r=t.data.on||{};mr=e.elm,function(t){if(c(t.__r)){var e=Z?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}c(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),fe(n,r,xr,Fr,br,e.context),mr=void 0}}var _r,Pr={create:wr,update:wr};function Or(t,e){if(!u(t.data.domProps)||!u(e.data.domProps)){var n,r,o=e.elm,i=t.data.domProps||{},a=e.data.domProps||{};for(n in c(a.__ob__)&&(a=e.data.domProps=j({},a)),i)n in a||(o[n]="");for(n in a){if(r=a[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===i[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var l=u(r)?"":String(r);kr(o,l)&&(o.value=l)}else if("innerHTML"===n&&Jn(o.tagName)&&u(o.innerHTML)){(_r=_r||document.createElement("div")).innerHTML="<svg>"+r+"</svg>";for(var s=_r.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;s.firstChild;)o.appendChild(s.firstChild)}else if(r!==i[n])try{o[n]=r}catch(t){}}}}function kr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(c(r)){if(r.number)return g(n)!==g(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Dr={create:Or,update:Or},Sr=F((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function jr(t){var e=Tr(t.style);return t.staticStyle?j(t.staticStyle,e):e}function Tr(t){return Array.isArray(t)?T(t):"string"==typeof t?Sr(t):t}var Mr,$r=/^--/,Lr=/\s*!important$/,Ur=function(t,e,n){if($r.test(e))t.style.setProperty(e,n);else if(Lr.test(n))t.style.setProperty(k(e),n.replace(Lr,""),"important");else{var r=Ir(e);if(Array.isArray(n))for(var o=0,i=n.length;o<i;o++)t.style[r]=n[o];else t.style[r]=n}},Rr=["Webkit","Moz","ms"],Ir=F((function(t){if(Mr=Mr||document.createElement("div").style,"filter"!==(t=_(t))&&t in Mr)return t;for(var e=t.charAt(0).toUpperCase()+t.slice(1),n=0;n<Rr.length;n++){var r=Rr[n]+e;if(r in Mr)return r}}));function Nr(t,e){var n=e.data,r=t.data;if(!(u(n.staticStyle)&&u(n.style)&&u(r.staticStyle)&&u(r.style))){var o,i,a=e.elm,l=r.staticStyle,s=r.normalizedStyle||r.style||{},f=l||s,E=Tr(e.data.style)||{};e.data.normalizedStyle=c(E.__ob__)?j({},E):E;var p=function(t,e){var n,r={};if(e)for(var o=t;o.componentInstance;)(o=o.componentInstance._vnode)&&o.data&&(n=jr(o.data))&&j(r,n);(n=jr(t.data))&&j(r,n);for(var i=t;i=i.parent;)i.data&&(n=jr(i.data))&&j(r,n);return r}(e,!0);for(i in f)u(p[i])&&Ur(a,i,"");for(i in p)(o=p[i])!==f[i]&&Ur(a,i,null==o?"":o)}}var zr={create:Nr,update:Nr},Vr=/\s+/;function qr(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(Vr).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function Gr(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(Vr).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function Wr(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&j(e,Hr(t.name||"v")),j(e,t),e}return"string"==typeof t?Hr(t):void 0}}var Hr=F((function(t){return{enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"}})),Xr=Y&&!tt,Yr="transition",Kr="transitionend",Jr="animation",Qr="animationend";Xr&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(Yr="WebkitTransition",Kr="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Jr="WebkitAnimation",Qr="webkitAnimationEnd"));var Zr=Y?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function to(t){Zr((function(){Zr(t)}))}function eo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),qr(t,e))}function no(t,e){t._transitionClasses&&b(t._transitionClasses,e),Gr(t,e)}function ro(t,e,n){var r=io(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var l="transition"===o?Kr:Qr,u=0,c=function(){t.removeEventListener(l,s),n()},s=function(e){e.target===t&&++u>=a&&c()};setTimeout((function(){u<a&&c()}),i+1),t.addEventListener(l,s)}var oo=/\b(transform|all)(,|$)/;function io(t,e){var n,r=window.getComputedStyle(t),o=(r[Yr+"Delay"]||"").split(", "),i=(r[Yr+"Duration"]||"").split(", "),a=ao(o,i),l=(r[Jr+"Delay"]||"").split(", "),u=(r[Jr+"Duration"]||"").split(", "),c=ao(l,u),s=0,f=0;return"transition"===e?a>0&&(n="transition",s=a,f=i.length):"animation"===e?c>0&&(n="animation",s=c,f=u.length):f=(n=(s=Math.max(a,c))>0?a>c?"transition":"animation":null)?"transition"===n?i.length:u.length:0,{type:n,timeout:s,propCount:f,hasTransform:"transition"===n&&oo.test(r[Yr+"Property"])}}function ao(t,e){for(;t.length<e.length;)t=t.concat(t);return Math.max.apply(null,e.map((function(e,n){return lo(e)+lo(t[n])})))}function lo(t){return 1e3*Number(t.slice(0,-1).replace(",","."))}function uo(t,e){var n=t.elm;c(n._leaveCb)&&(n._leaveCb.cancelled=!0,n._leaveCb());var r=Wr(t.data.transition);if(!u(r)&&!c(n._enterCb)&&1===n.nodeType){for(var o=r.css,i=r.type,a=r.enterClass,l=r.enterToClass,s=r.enterActiveClass,f=r.appearClass,p=r.appearToClass,h=r.appearActiveClass,d=r.beforeEnter,v=r.enter,A=r.afterEnter,B=r.enterCancelled,m=r.beforeAppear,y=r.appear,b=r.afterAppear,C=r.appearCancelled,x=r.duration,F=tn,w=tn.$vnode;w&&w.parent;)F=w.context,w=w.parent;var _=!F._isMounted||!t.isRootInsert;if(!_||y||""===y){var P=_&&f?f:a,O=_&&h?h:s,k=_&&p?p:l,D=_&&m||d,S=_&&"function"==typeof y?y:v,j=_&&b||A,T=_&&C||B,M=g(E(x)?x.enter:x);0;var $=!1!==o&&!tt,L=fo(S),U=n._enterCb=I((function(){$&&(no(n,k),no(n,O)),U.cancelled?($&&no(n,P),T&&T(n)):j&&j(n),n._enterCb=null}));t.data.show||Ee(t,"insert",(function(){var e=n.parentNode,r=e&&e._pending&&e._pending[t.key];r&&r.tag===t.tag&&r.elm._leaveCb&&r.elm._leaveCb(),S&&S(n,U)})),D&&D(n),$&&(eo(n,P),eo(n,O),to((function(){no(n,P),U.cancelled||(eo(n,k),L||(so(M)?setTimeout(U,M):ro(n,i,U)))}))),t.data.show&&(e&&e(),S&&S(n,U)),$||L||U()}}}function co(t,e){var n=t.elm;c(n._enterCb)&&(n._enterCb.cancelled=!0,n._enterCb());var r=Wr(t.data.transition);if(u(r)||1!==n.nodeType)return e();if(!c(n._leaveCb)){var o=r.css,i=r.type,a=r.leaveClass,l=r.leaveToClass,s=r.leaveActiveClass,f=r.beforeLeave,p=r.leave,h=r.afterLeave,d=r.leaveCancelled,v=r.delayLeave,A=r.duration,B=!1!==o&&!tt,m=fo(p),y=g(E(A)?A.leave:A);0;var b=n._leaveCb=I((function(){n.parentNode&&n.parentNode._pending&&(n.parentNode._pending[t.key]=null),B&&(no(n,l),no(n,s)),b.cancelled?(B&&no(n,a),d&&d(n)):(e(),h&&h(n)),n._leaveCb=null}));v?v(C):C()}function C(){b.cancelled||(!t.data.show&&n.parentNode&&((n.parentNode._pending||(n.parentNode._pending={}))[t.key]=t),f&&f(n),B&&(eo(n,a),eo(n,s),to((function(){no(n,a),b.cancelled||(eo(n,l),m||(so(y)?setTimeout(b,y):ro(n,i,b)))}))),p&&p(n,b),B||m||b())}}function so(t){return"number"==typeof t&&!isNaN(t)}function fo(t){if(u(t))return!1;var e=t.fns;return c(e)?fo(Array.isArray(e)?e[0]:e):(t._length||t.length)>1}function Eo(t,e){!0!==e.data.show&&uo(e)}var po=function(t){var e,n,r={},o=t.modules,i=t.nodeOps;for(e=0;e<ir.length;++e)for(r[ir[e]]=[],n=0;n<o.length;++n)c(o[n][ir[e]])&&r[ir[e]].push(o[n][ir[e]]);function a(t){var e=i.parentNode(t);c(e)&&i.removeChild(e,t)}function l(t,e,n,o,a,l,u){if(c(t.elm)&&c(l)&&(t=l[u]=bt(t)),t.isRootInsert=!a,!function(t,e,n,o){var i=t.data;if(c(i)){var a=c(t.componentInstance)&&i.keepAlive;if(c(i=i.hook)&&c(i=i.init)&&i(t,!1),c(t.componentInstance))return E(t,e),p(n,t.elm,o),s(a)&&function(t,e,n,o){var i,a=t;for(;a.componentInstance;)if(a=a.componentInstance._vnode,c(i=a.data)&&c(i=i.transition)){for(i=0;i<r.activate.length;++i)r.activate[i](or,a);e.push(a);break}p(n,t.elm,o)}(t,e,n,o),!0}}(t,e,n,o)){var f=t.data,d=t.children,B=t.tag;c(B)?(t.elm=t.ns?i.createElementNS(t.ns,B):i.createElement(B,t),A(t),h(t,d,e),c(f)&&v(t,e),p(n,t.elm,o)):s(t.isComment)?(t.elm=i.createComment(t.text),p(n,t.elm,o)):(t.elm=i.createTextNode(t.text),p(n,t.elm,o))}}function E(t,e){c(t.data.pendingInsert)&&(e.push.apply(e,t.data.pendingInsert),t.data.pendingInsert=null),t.elm=t.componentInstance.$el,d(t)?(v(t,e),A(t)):(rr(t),e.push(t))}function p(t,e,n){c(t)&&(c(n)?i.parentNode(n)===t&&i.insertBefore(t,e,n):i.appendChild(t,e))}function h(t,e,n){if(Array.isArray(e)){0;for(var r=0;r<e.length;++r)l(e[r],n,t.elm,null,!0,e,r)}else f(t.text)&&i.appendChild(t.elm,i.createTextNode(String(t.text)))}function d(t){for(;t.componentInstance;)t=t.componentInstance._vnode;return c(t.tag)}function v(t,n){for(var o=0;o<r.create.length;++o)r.create[o](or,t);c(e=t.data.hook)&&(c(e.create)&&e.create(or,t),c(e.insert)&&n.push(t))}function A(t){var e;if(c(e=t.fnScopeId))i.setStyleScope(t.elm,e);else for(var n=t;n;)c(e=n.context)&&c(e=e.$options._scopeId)&&i.setStyleScope(t.elm,e),n=n.parent;c(e=tn)&&e!==t.context&&e!==t.fnContext&&c(e=e.$options._scopeId)&&i.setStyleScope(t.elm,e)}function B(t,e,n,r,o,i){for(;r<=o;++r)l(n[r],i,t,e,!1,n,r)}function g(t){var e,n,o=t.data;if(c(o))for(c(e=o.hook)&&c(e=e.destroy)&&e(t),e=0;e<r.destroy.length;++e)r.destroy[e](t);if(c(e=t.children))for(n=0;n<t.children.length;++n)g(t.children[n])}function y(t,e,n){for(;e<=n;++e){var r=t[e];c(r)&&(c(r.tag)?(b(r),g(r)):a(r.elm))}}function b(t,e){if(c(e)||c(t.data)){var n,o=r.remove.length+1;for(c(e)?e.listeners+=o:e=function(t,e){function n(){0==--n.listeners&&a(t)}return n.listeners=e,n}(t.elm,o),c(n=t.componentInstance)&&c(n=n._vnode)&&c(n.data)&&b(n,e),n=0;n<r.remove.length;++n)r.remove[n](t,e);c(n=t.data.hook)&&c(n=n.remove)?n(t,e):e()}else a(t.elm)}function C(t,e,n,r){for(var o=n;o<r;o++){var i=e[o];if(c(i)&&ar(t,i))return o}}function x(t,e,n,o,a,f){if(t!==e){c(e.elm)&&c(o)&&(e=o[a]=bt(e));var E=e.elm=t.elm;if(s(t.isAsyncPlaceholder))c(e.asyncFactory.resolved)?_(t.elm,e,n):e.isAsyncPlaceholder=!0;else if(s(e.isStatic)&&s(t.isStatic)&&e.key===t.key&&(s(e.isCloned)||s(e.isOnce)))e.componentInstance=t.componentInstance;else{var p,h=e.data;c(h)&&c(p=h.hook)&&c(p=p.prepatch)&&p(t,e);var v=t.children,A=e.children;if(c(h)&&d(e)){for(p=0;p<r.update.length;++p)r.update[p](t,e);c(p=h.hook)&&c(p=p.update)&&p(t,e)}u(e.text)?c(v)&&c(A)?v!==A&&function(t,e,n,r,o){var a,s,f,E=0,p=0,h=e.length-1,d=e[0],v=e[h],A=n.length-1,g=n[0],m=n[A],b=!o;for(0;E<=h&&p<=A;)u(d)?d=e[++E]:u(v)?v=e[--h]:ar(d,g)?(x(d,g,r,n,p),d=e[++E],g=n[++p]):ar(v,m)?(x(v,m,r,n,A),v=e[--h],m=n[--A]):ar(d,m)?(x(d,m,r,n,A),b&&i.insertBefore(t,d.elm,i.nextSibling(v.elm)),d=e[++E],m=n[--A]):ar(v,g)?(x(v,g,r,n,p),b&&i.insertBefore(t,v.elm,d.elm),v=e[--h],g=n[++p]):(u(a)&&(a=lr(e,E,h)),u(s=c(g.key)?a[g.key]:C(g,e,E,h))?l(g,r,t,d.elm,!1,n,p):ar(f=e[s],g)?(x(f,g,r,n,p),e[s]=void 0,b&&i.insertBefore(t,f.elm,d.elm)):l(g,r,t,d.elm,!1,n,p),g=n[++p]);E>h?B(t,u(n[A+1])?null:n[A+1].elm,n,p,A,r):p>A&&y(e,E,h)}(E,v,A,n,f):c(A)?(c(t.text)&&i.setTextContent(E,""),B(E,null,A,0,A.length-1,n)):c(v)?y(v,0,v.length-1):c(t.text)&&i.setTextContent(E,""):t.text!==e.text&&i.setTextContent(E,e.text),c(h)&&c(p=h.hook)&&c(p=p.postpatch)&&p(t,e)}}}function F(t,e,n){if(s(n)&&c(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r<e.length;++r)e[r].data.hook.insert(e[r])}var w=m("attrs,class,staticClass,staticStyle,key");function _(t,e,n,r){var o,i=e.tag,a=e.data,l=e.children;if(r=r||a&&a.pre,e.elm=t,s(e.isComment)&&c(e.asyncFactory))return e.isAsyncPlaceholder=!0,!0;if(c(a)&&(c(o=a.hook)&&c(o=o.init)&&o(e,!0),c(o=e.componentInstance)))return E(e,n),!0;if(c(i)){if(c(l))if(t.hasChildNodes())if(c(o=a)&&c(o=o.domProps)&&c(o=o.innerHTML)){if(o!==t.innerHTML)return!1}else{for(var u=!0,f=t.firstChild,p=0;p<l.length;p++){if(!f||!_(f,l[p],n,r)){u=!1;break}f=f.nextSibling}if(!u||f)return!1}else h(e,l,n);if(c(a)){var d=!1;for(var A in a)if(!w(A)){d=!0,v(e,n);break}!d&&a.class&&ue(a.class)}}else t.data!==e.text&&(t.data=e.text);return!0}return function(t,e,n,o){if(!u(e)){var a,f=!1,E=[];if(u(t))f=!0,l(e,E);else{var p=c(t.nodeType);if(!p&&ar(t,e))x(t,e,E,null,null,o);else{if(p){if(1===t.nodeType&&t.hasAttribute("data-server-rendered")&&(t.removeAttribute("data-server-rendered"),n=!0),s(n)&&_(t,e,E))return F(e,E,!0),t;a=t,t=new Bt(i.tagName(a).toLowerCase(),{},[],void 0,a)}var h=t.elm,v=i.parentNode(h);if(l(e,E,h._leaveCb?null:v,i.nextSibling(h)),c(e.parent))for(var A=e.parent,B=d(e);A;){for(var m=0;m<r.destroy.length;++m)r.destroy[m](A);if(A.elm=e.elm,B){for(var b=0;b<r.create.length;++b)r.create[b](or,A);var C=A.data.hook.insert;if(C.merged)for(var w=1;w<C.fns.length;w++)C.fns[w]()}else rr(A);A=A.parent}c(v)?y([t],0,0):c(t.tag)&&g(t)}}return F(e,E,f),e.elm}c(t)&&g(t)}}({nodeOps:er,modules:[Br,yr,Pr,Dr,zr,Y?{create:Eo,activate:Eo,remove:function(t,e){!0!==t.data.show?co(t,e):e()}}:{}].concat(hr)});tt&&document.addEventListener("selectionchange",(function(){var t=document.activeElement;t&&t.vmodel&&bo(t,"input")}));var ho={inserted:function(t,e,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?Ee(n,"postpatch",(function(){ho.componentUpdated(t,e,n)})):vo(t,e,n.context),t._vOptions=[].map.call(t.options,go)):("textarea"===n.tag||tr(t.type))&&(t._vModifiers=e.modifiers,e.modifiers.lazy||(t.addEventListener("compositionstart",mo),t.addEventListener("compositionend",yo),t.addEventListener("change",yo),tt&&(t.vmodel=!0)))},componentUpdated:function(t,e,n){if("select"===n.tag){vo(t,e,n.context);var r=t._vOptions,o=t._vOptions=[].map.call(t.options,go);if(o.some((function(t,e){return!U(t,r[e])})))(t.multiple?e.value.some((function(t){return Bo(t,o)})):e.value!==e.oldValue&&Bo(e.value,o))&&bo(t,"change")}}};function vo(t,e,n){Ao(t,e,n),(Z||et)&&setTimeout((function(){Ao(t,e,n)}),0)}function Ao(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){for(var i,a,l=0,u=t.options.length;l<u;l++)if(a=t.options[l],o)i=R(r,go(a))>-1,a.selected!==i&&(a.selected=i);else if(U(go(a),r))return void(t.selectedIndex!==l&&(t.selectedIndex=l));o||(t.selectedIndex=-1)}}function Bo(t,e){return e.every((function(e){return!U(e,t)}))}function go(t){return"_value"in t?t._value:t.value}function mo(t){t.target.composing=!0}function yo(t){t.target.composing&&(t.target.composing=!1,bo(t.target,"input"))}function bo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function Co(t){return!t.componentInstance||t.data&&t.data.transition?t:Co(t.componentInstance._vnode)}var xo={model:ho,show:{bind:function(t,e,n){var r=e.value,o=(n=Co(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,uo(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=Co(n)).data&&n.data.transition?(n.data.show=!0,r?uo(n,(function(){t.style.display=t.__vOriginalDisplay})):co(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Fo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?wo(Ye(e.children)):t}function _o(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var i in o)e[_(i)]=o[i];return e}function Po(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Oo=function(t){return t.tag||ge(t)},ko=function(t){return"show"===t.name},Do={name:"transition",props:Fo,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Oo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=wo(o);if(!i)return o;if(this._leaving)return Po(t,o);var a="__transition-"+this._uid+"-";i.key=null==i.key?i.isComment?a+"comment":a+i.tag:f(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var l=(i.data||(i.data={})).transition=_o(this),u=this._vnode,c=wo(u);if(i.data.directives&&i.data.directives.some(ko)&&(i.data.show=!0),c&&c.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,c)&&!ge(c)&&(!c.componentInstance||!c.componentInstance._vnode.isComment)){var s=c.data.transition=j({},l);if("out-in"===r)return this._leaving=!0,Ee(s,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Po(t,o);if("in-out"===r){if(ge(i))return u;var E,p=function(){E()};Ee(l,"afterEnter",p),Ee(l,"enterCancelled",p),Ee(s,"delayLeave",(function(t){E=t}))}}return o}}},So=j({tag:String,moveClass:String},Fo);function jo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function To(t){t.data.newPos=t.elm.getBoundingClientRect()}function Mo(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate("+r+"px,"+o+"px)",i.transitionDuration="0s"}}delete So.mode;var $o={Transition:Do,TransitionGroup:{props:So,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=en(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=_o(this),l=0;l<o.length;l++){var u=o[l];if(u.tag)if(null!=u.key&&0!==String(u.key).indexOf("__vlist"))i.push(u),n[u.key]=u,(u.data||(u.data={})).transition=a;else;}if(r){for(var c=[],s=[],f=0;f<r.length;f++){var E=r[f];E.data.transition=a,E.data.pos=E.elm.getBoundingClientRect(),n[E.key]?c.push(E):s.push(E)}this.kept=t(e,null,c),this.removed=s}return t(e,null,i)},updated:function(){var t=this.prevChildren,e=this.moveClass||(this.name||"v")+"-move";t.length&&this.hasMove(t[0].elm,e)&&(t.forEach(jo),t.forEach(To),t.forEach(Mo),this._reflow=document.body.offsetHeight,t.forEach((function(t){if(t.data.moved){var n=t.elm,r=n.style;eo(n,e),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(Kr,n._moveCb=function t(r){r&&r.target!==n||r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(Kr,t),n._moveCb=null,no(n,e))})}})))},methods:{hasMove:function(t,e){if(!Xr)return!1;if(this._hasMove)return this._hasMove;var n=t.cloneNode();t._transitionClasses&&t._transitionClasses.forEach((function(t){Gr(n,t)})),qr(n,e),n.style.display="none",this.$el.appendChild(n);var r=io(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}}};Pn.config.mustUseProp=function(t,e,n){return"value"===n&&Ln(t)&&"button"!==e||"selected"===n&&"option"===t||"checked"===n&&"input"===t||"muted"===n&&"video"===t},Pn.config.isReservedTag=Qn,Pn.config.isReservedAttr=$n,Pn.config.getTagNamespace=function(t){return Jn(t)?"svg":"math"===t?"math":void 0},Pn.config.isUnknownElement=function(t){if(!Y)return!0;if(Qn(t))return!1;if(t=t.toLowerCase(),null!=Zn[t])return Zn[t];var e=document.createElement(t);return t.indexOf("-")>-1?Zn[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Zn[t]=/HTMLUnknownElement/.test(e.toString())},j(Pn.options.directives,xo),j(Pn.options.components,$o),Pn.prototype.__patch__=Y?po:M,Pn.prototype.$mount=function(t,e){return function(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.render=mt),on(t,"beforeMount"),r=function(){t._update(t._render(),n)},new An(t,r,M,{before:function(){t._isMounted&&!t._isDestroyed&&on(t,"beforeUpdate")}},!0),n=!1,null==t.$vnode&&(t._isMounted=!0,on(t,"mounted")),t}(this,t=t&&Y?function(t){if("string"==typeof t){var e=document.querySelector(t);return e||document.createElement("div")}return t}(t):void 0,e)},Y&&setTimeout((function(){V.devtools&&ut&&ut.emit("init",Pn)}),0);var Lo=Pn; +/*! + * vue-router v3.5.4 + * (c) 2022 Evan You + * @license MIT + */function Uo(t,e){for(var n in e)t[n]=e[n];return t}var Ro=/[!'()*]/g,Io=function(t){return"%"+t.charCodeAt(0).toString(16)},No=/%2C/g,zo=function(t){return encodeURIComponent(t).replace(Ro,Io).replace(No,",")};function Vo(t){try{return decodeURIComponent(t)}catch(t){0}return t}var qo=function(t){return null==t||"object"==typeof t?t:String(t)};function Go(t){var e={};return(t=t.trim().replace(/^(\?|#|&)/,""))?(t.split("&").forEach((function(t){var n=t.replace(/\+/g," ").split("="),r=Vo(n.shift()),o=n.length>0?Vo(n.join("=")):null;void 0===e[r]?e[r]=o:Array.isArray(e[r])?e[r].push(o):e[r]=[e[r],o]})),e):e}function Wo(t){var e=t?Object.keys(t).map((function(e){var n=t[e];if(void 0===n)return"";if(null===n)return zo(e);if(Array.isArray(n)){var r=[];return n.forEach((function(t){void 0!==t&&(null===t?r.push(zo(e)):r.push(zo(e)+"="+zo(t)))})),r.join("&")}return zo(e)+"="+zo(n)})).filter((function(t){return t.length>0})).join("&"):null;return e?"?"+e:""}var Ho=/\/?$/;function Xo(t,e,n,r){var o=r&&r.options.stringifyQuery,i=e.query||{};try{i=Yo(i)}catch(t){}var a={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:i,params:e.params||{},fullPath:Qo(e,o),matched:t?Jo(t):[]};return n&&(a.redirectedFrom=Qo(n,o)),Object.freeze(a)}function Yo(t){if(Array.isArray(t))return t.map(Yo);if(t&&"object"==typeof t){var e={};for(var n in t)e[n]=Yo(t[n]);return e}return t}var Ko=Xo(null,{path:"/"});function Jo(t){for(var e=[];t;)e.unshift(t),t=t.parent;return e}function Qo(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var o=t.hash;return void 0===o&&(o=""),(n||"/")+(e||Wo)(r)+o}function Zo(t,e,n){return e===Ko?t===e:!!e&&(t.path&&e.path?t.path.replace(Ho,"")===e.path.replace(Ho,"")&&(n||t.hash===e.hash&&ti(t.query,e.query)):!(!t.name||!e.name)&&(t.name===e.name&&(n||t.hash===e.hash&&ti(t.query,e.query)&&ti(t.params,e.params))))}function ti(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t===e;var n=Object.keys(t).sort(),r=Object.keys(e).sort();return n.length===r.length&&n.every((function(n,o){var i=t[n];if(r[o]!==n)return!1;var a=e[n];return null==i||null==a?i===a:"object"==typeof i&&"object"==typeof a?ti(i,a):String(i)===String(a)}))}function ei(t){for(var e=0;e<t.matched.length;e++){var n=t.matched[e];for(var r in n.instances){var o=n.instances[r],i=n.enteredCbs[r];if(o&&i){delete n.enteredCbs[r];for(var a=0;a<i.length;a++)o._isBeingDestroyed||i[a](o)}}}}var ni={name:"RouterView",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,o=e.parent,i=e.data;i.routerView=!0;for(var a=o.$createElement,l=n.name,u=o.$route,c=o._routerViewCache||(o._routerViewCache={}),s=0,f=!1;o&&o._routerRoot!==o;){var E=o.$vnode?o.$vnode.data:{};E.routerView&&s++,E.keepAlive&&o._directInactive&&o._inactive&&(f=!0),o=o.$parent}if(i.routerViewDepth=s,f){var p=c[l],h=p&&p.component;return h?(p.configProps&&ri(h,i,p.route,p.configProps),a(h,i,r)):a()}var d=u.matched[s],v=d&&d.components[l];if(!d||!v)return c[l]=null,a();c[l]={component:v},i.registerRouteInstance=function(t,e){var n=d.instances[l];(e&&n!==t||!e&&n===t)&&(d.instances[l]=e)},(i.hook||(i.hook={})).prepatch=function(t,e){d.instances[l]=e.componentInstance},i.hook.init=function(t){t.data.keepAlive&&t.componentInstance&&t.componentInstance!==d.instances[l]&&(d.instances[l]=t.componentInstance),ei(u)};var A=d.props&&d.props[l];return A&&(Uo(c[l],{route:u,configProps:A}),ri(v,i,u,A)),a(v,i,r)}};function ri(t,e,n,r){var o=e.props=function(t,e){switch(typeof e){case"undefined":return;case"object":return e;case"function":return e(t);case"boolean":return e?t.params:void 0;default:0}}(n,r);if(o){o=e.props=Uo({},o);var i=e.attrs=e.attrs||{};for(var a in o)t.props&&a in t.props||(i[a]=o[a],delete o[a])}}function oi(t,e,n){var r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return e+t;var o=e.split("/");n&&o[o.length-1]||o.pop();for(var i=t.replace(/^\//,"").split("/"),a=0;a<i.length;a++){var l=i[a];".."===l?o.pop():"."!==l&&o.push(l)}return""!==o[0]&&o.unshift(""),o.join("/")}function ii(t){return t.replace(/\/(?:\s*\/)+/g,"/")}var ai=Array.isArray||function(t){return"[object Array]"==Object.prototype.toString.call(t)},li=yi,ui=pi,ci=function(t,e){return di(pi(t,e),e)},si=di,fi=mi,Ei=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function pi(t,e){for(var n,r=[],o=0,i=0,a="",l=e&&e.delimiter||"/";null!=(n=Ei.exec(t));){var u=n[0],c=n[1],s=n.index;if(a+=t.slice(i,s),i=s+u.length,c)a+=c[1];else{var f=t[i],E=n[2],p=n[3],h=n[4],d=n[5],v=n[6],A=n[7];a&&(r.push(a),a="");var B=null!=E&&null!=f&&f!==E,g="+"===v||"*"===v,m="?"===v||"*"===v,y=n[2]||l,b=h||d;r.push({name:p||o++,prefix:E||"",delimiter:y,optional:m,repeat:g,partial:B,asterisk:!!A,pattern:b?Ai(b):A?".*":"[^"+vi(y)+"]+?"})}}return i<t.length&&(a+=t.substr(i)),a&&r.push(a),r}function hi(t){return encodeURI(t).replace(/[\/?#]/g,(function(t){return"%"+t.charCodeAt(0).toString(16).toUpperCase()}))}function di(t,e){for(var n=new Array(t.length),r=0;r<t.length;r++)"object"==typeof t[r]&&(n[r]=new RegExp("^(?:"+t[r].pattern+")$",gi(e)));return function(e,r){for(var o="",i=e||{},a=(r||{}).pretty?hi:encodeURIComponent,l=0;l<t.length;l++){var u=t[l];if("string"!=typeof u){var c,s=i[u.name];if(null==s){if(u.optional){u.partial&&(o+=u.prefix);continue}throw new TypeError('Expected "'+u.name+'" to be defined')}if(ai(s)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but received `'+JSON.stringify(s)+"`");if(0===s.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var f=0;f<s.length;f++){if(c=a(s[f]),!n[l].test(c))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'", but received `'+JSON.stringify(c)+"`");o+=(0===f?u.prefix:u.delimiter)+c}}else{if(c=u.asterisk?encodeURI(s).replace(/[?#]/g,(function(t){return"%"+t.charCodeAt(0).toString(16).toUpperCase()})):a(s),!n[l].test(c))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but received "'+c+'"');o+=u.prefix+c}}else o+=u}return o}}function vi(t){return t.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function Ai(t){return t.replace(/([=!:$\/()])/g,"\\$1")}function Bi(t,e){return t.keys=e,t}function gi(t){return t&&t.sensitive?"":"i"}function mi(t,e,n){ai(e)||(n=e||n,e=[]);for(var r=(n=n||{}).strict,o=!1!==n.end,i="",a=0;a<t.length;a++){var l=t[a];if("string"==typeof l)i+=vi(l);else{var u=vi(l.prefix),c="(?:"+l.pattern+")";e.push(l),l.repeat&&(c+="(?:"+u+c+")*"),i+=c=l.optional?l.partial?u+"("+c+")?":"(?:"+u+"("+c+"))?":u+"("+c+")"}}var s=vi(n.delimiter||"/"),f=i.slice(-s.length)===s;return r||(i=(f?i.slice(0,-s.length):i)+"(?:"+s+"(?=$))?"),i+=o?"$":r&&f?"":"(?="+s+"|$)",Bi(new RegExp("^"+i,gi(n)),e)}function yi(t,e,n){return ai(e)||(n=e||n,e=[]),n=n||{},t instanceof RegExp?function(t,e){var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)e.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return Bi(t,e)}(t,e):ai(t)?function(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(yi(t[o],e,n).source);return Bi(new RegExp("(?:"+r.join("|")+")",gi(n)),e)}(t,e,n):function(t,e,n){return mi(pi(t,n),e,n)}(t,e,n)}li.parse=ui,li.compile=ci,li.tokensToFunction=si,li.tokensToRegExp=fi;var bi=Object.create(null);function Ci(t,e,n){e=e||{};try{var r=bi[t]||(bi[t]=li.compile(t));return"string"==typeof e.pathMatch&&(e[0]=e.pathMatch),r(e,{pretty:!0})}catch(t){return""}finally{delete e[0]}}function xi(t,e,n,r){var o="string"==typeof t?{path:t}:t;if(o._normalized)return o;if(o.name){var i=(o=Uo({},t)).params;return i&&"object"==typeof i&&(o.params=Uo({},i)),o}if(!o.path&&o.params&&e){(o=Uo({},o))._normalized=!0;var a=Uo(Uo({},e.params),o.params);if(e.name)o.name=e.name,o.params=a;else if(e.matched.length){var l=e.matched[e.matched.length-1].path;o.path=Ci(l,a,e.path)}else 0;return o}var u=function(t){var e="",n="",r=t.indexOf("#");r>=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),c=e&&e.path||"/",s=u.path?oi(u.path,c,n||o.append):c,f=function(t,e,n){void 0===e&&(e={});var r,o=n||Go;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(qo):qo(a)}return r}(u.query,o.query,r&&r.options.parseQuery),E=o.hash||u.hash;return E&&"#"!==E.charAt(0)&&(E="#"+E),{_normalized:!0,path:s,query:f,hash:E}}var Fi,wi=function(){},_i={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,l=o.href,u={},c=n.options.linkActiveClass,s=n.options.linkExactActiveClass,f=null==c?"router-link-active":c,E=null==s?"router-link-exact-active":s,p=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?E:this.exactActiveClass,d=a.redirectedFrom?Xo(null,xi(a.redirectedFrom),null,n):a;u[h]=Zo(r,d,this.exactPath),u[p]=this.exact||this.exactPath?u[h]:function(t,e){return 0===t.path.replace(Ho,"/").indexOf(e.path.replace(Ho,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,d);var v=u[h]?this.ariaCurrentValue:null,A=function(t){Pi(t)&&(e.replace?n.replace(i,wi):n.push(i,wi))},B={click:Pi};Array.isArray(this.event)?this.event.forEach((function(t){B[t]=A})):B[this.event]=A;var g={class:u},m=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:l,route:a,navigate:A,isActive:u[p],isExactActive:u[h]});if(m){if(1===m.length)return m[0];if(m.length>1||!m.length)return 0===m.length?t():t("span",{},m)}if("a"===this.tag)g.on=B,g.attrs={href:l,"aria-current":v};else{var y=function t(e){var n;if(e)for(var r=0;r<e.length;r++){if("a"===(n=e[r]).tag)return n;if(n.children&&(n=t(n.children)))return n}}(this.$slots.default);if(y){y.isStatic=!1;var b=y.data=Uo({},y.data);for(var C in b.on=b.on||{},b.on){var x=b.on[C];C in B&&(b.on[C]=Array.isArray(x)?x:[x])}for(var F in B)F in b.on?b.on[F].push(B[F]):b.on[F]=A;var w=y.data.attrs=Uo({},y.data.attrs);w.href=l,w["aria-current"]=v}else g.on=B}return t(this.tag,g,this.$slots.default)}};function Pi(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey||t.defaultPrevented||void 0!==t.button&&0!==t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){var e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}var Oi="undefined"!=typeof window;function ki(t,e,n,r,o){var i=e||[],a=n||Object.create(null),l=r||Object.create(null);t.forEach((function(t){!function t(e,n,r,o,i,a){var l=o.path,u=o.name;0;var c=o.pathToRegexpOptions||{},s=function(t,e,n){n||(t=t.replace(/\/$/,""));if("/"===t[0])return t;if(null==e)return t;return ii(e.path+"/"+t)}(l,i,c.strict);"boolean"==typeof o.caseSensitive&&(c.sensitive=o.caseSensitive);var f={path:s,regex:Di(s,c),components:o.components||{default:o.component},alias:o.alias?"string"==typeof o.alias?[o.alias]:o.alias:[],instances:{},enteredCbs:{},name:u,parent:i,matchAs:a,redirect:o.redirect,beforeEnter:o.beforeEnter,meta:o.meta||{},props:null==o.props?{}:o.components?o.props:{default:o.props}};o.children&&o.children.forEach((function(o){var i=a?ii(a+"/"+o.path):void 0;t(e,n,r,o,f,i)}));n[f.path]||(e.push(f.path),n[f.path]=f);if(void 0!==o.alias)for(var E=Array.isArray(o.alias)?o.alias:[o.alias],p=0;p<E.length;++p){0;var h={path:E[p],children:o.children};t(e,n,r,h,i,f.path||"/")}u&&(r[u]||(r[u]=f))}(i,a,l,t,o)}));for(var u=0,c=i.length;u<c;u++)"*"===i[u]&&(i.push(i.splice(u,1)[0]),c--,u--);return{pathList:i,pathMap:a,nameMap:l}}function Di(t,e){return li(t,[],e)}function Si(t,e){var n=ki(t),r=n.pathList,o=n.pathMap,i=n.nameMap;function a(t,n,a){var l=xi(t,n,!1,e),c=l.name;if(c){var s=i[c];if(!s)return u(null,l);var f=s.regex.keys.filter((function(t){return!t.optional})).map((function(t){return t.name}));if("object"!=typeof l.params&&(l.params={}),n&&"object"==typeof n.params)for(var E in n.params)!(E in l.params)&&f.indexOf(E)>-1&&(l.params[E]=n.params[E]);return l.path=Ci(s.path,l.params),u(s,l,a)}if(l.path){l.params={};for(var p=0;p<r.length;p++){var h=r[p],d=o[h];if(ji(d.regex,l.path,l.params))return u(d,l,a)}}return u(null,l)}function l(t,n){var r=t.redirect,o="function"==typeof r?r(Xo(t,n,null,e)):r;if("string"==typeof o&&(o={path:o}),!o||"object"!=typeof o)return u(null,n);var l=o,c=l.name,s=l.path,f=n.query,E=n.hash,p=n.params;if(f=l.hasOwnProperty("query")?l.query:f,E=l.hasOwnProperty("hash")?l.hash:E,p=l.hasOwnProperty("params")?l.params:p,c){i[c];return a({_normalized:!0,name:c,query:f,hash:E,params:p},void 0,n)}if(s){var h=function(t,e){return oi(t,e.parent?e.parent.path:"/",!0)}(s,t);return a({_normalized:!0,path:Ci(h,p),query:f,hash:E},void 0,n)}return u(null,n)}function u(t,n,r){return t&&t.redirect?l(t,r||n):t&&t.matchAs?function(t,e,n){var r=a({_normalized:!0,path:Ci(n,e.params)});if(r){var o=r.matched,i=o[o.length-1];return e.params=r.params,u(i,e)}return u(null,e)}(0,n,t.matchAs):Xo(t,n,r,e)}return{match:a,addRoute:function(t,e){var n="object"!=typeof t?i[t]:void 0;ki([e||t],r,o,i,n),n&&n.alias.length&&ki(n.alias.map((function(t){return{path:t,children:[e]}})),r,o,i,n)},getRoutes:function(){return r.map((function(t){return o[t]}))},addRoutes:function(t){ki(t,r,o,i)}}}function ji(t,e,n){var r=e.match(t);if(!r)return!1;if(!n)return!0;for(var o=1,i=r.length;o<i;++o){var a=t.keys[o-1];a&&(n[a.name||"pathMatch"]="string"==typeof r[o]?Vo(r[o]):r[o])}return!0}var Ti=Oi&&window.performance&&window.performance.now?window.performance:Date;function Mi(){return Ti.now().toFixed(3)}var $i=Mi();function Li(){return $i}function Ui(t){return $i=t}var Ri=Object.create(null);function Ii(){"scrollRestoration"in window.history&&(window.history.scrollRestoration="manual");var t=window.location.protocol+"//"+window.location.host,e=window.location.href.replace(t,""),n=Uo({},window.history.state);return n.key=Li(),window.history.replaceState(n,"",e),window.addEventListener("popstate",Vi),function(){window.removeEventListener("popstate",Vi)}}function Ni(t,e,n,r){if(t.app){var o=t.options.scrollBehavior;o&&t.app.$nextTick((function(){var i=function(){var t=Li();if(t)return Ri[t]}(),a=o.call(t,e,n,r?i:null);a&&("function"==typeof a.then?a.then((function(t){Xi(t,i)})).catch((function(t){0})):Xi(a,i))}))}}function zi(){var t=Li();t&&(Ri[t]={x:window.pageXOffset,y:window.pageYOffset})}function Vi(t){zi(),t.state&&t.state.key&&Ui(t.state.key)}function qi(t){return Wi(t.x)||Wi(t.y)}function Gi(t){return{x:Wi(t.x)?t.x:window.pageXOffset,y:Wi(t.y)?t.y:window.pageYOffset}}function Wi(t){return"number"==typeof t}var Hi=/^#\d/;function Xi(t,e){var n,r="object"==typeof t;if(r&&"string"==typeof t.selector){var o=Hi.test(t.selector)?document.getElementById(t.selector.slice(1)):document.querySelector(t.selector);if(o){var i=t.offset&&"object"==typeof t.offset?t.offset:{};e=function(t,e){var n=document.documentElement.getBoundingClientRect(),r=t.getBoundingClientRect();return{x:r.left-n.left-e.x,y:r.top-n.top-e.y}}(o,i={x:Wi((n=i).x)?n.x:0,y:Wi(n.y)?n.y:0})}else qi(t)&&(e=Gi(t))}else r&&qi(t)&&(e=Gi(t));e&&("scrollBehavior"in document.documentElement.style?window.scrollTo({left:e.x,top:e.y,behavior:t.behavior}):window.scrollTo(e.x,e.y))}var Yi,Ki=Oi&&((-1===(Yi=window.navigator.userAgent).indexOf("Android 2.")&&-1===Yi.indexOf("Android 4.0")||-1===Yi.indexOf("Mobile Safari")||-1!==Yi.indexOf("Chrome")||-1!==Yi.indexOf("Windows Phone"))&&window.history&&"function"==typeof window.history.pushState);function Ji(t,e){zi();var n=window.history;try{if(e){var r=Uo({},n.state);r.key=Li(),n.replaceState(r,"",t)}else n.pushState({key:Ui(Mi())},"",t)}catch(n){window.location[e?"replace":"assign"](t)}}function Qi(t){Ji(t,!0)}function Zi(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}var ta={redirected:2,aborted:4,cancelled:8,duplicated:16};function ea(t,e){return ra(t,e,ta.redirected,'Redirected when going from "'+t.fullPath+'" to "'+function(t){if("string"==typeof t)return t;if("path"in t)return t.path;var e={};return oa.forEach((function(n){n in t&&(e[n]=t[n])})),JSON.stringify(e,null,2)}(e)+'" via a navigation guard.')}function na(t,e){return ra(t,e,ta.cancelled,'Navigation cancelled from "'+t.fullPath+'" to "'+e.fullPath+'" with a new navigation.')}function ra(t,e,n,r){var o=new Error(r);return o._isRouter=!0,o.from=t,o.to=e,o.type=n,o}var oa=["params","query","hash"];function ia(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}function aa(t,e){return ia(t)&&t._isRouter&&(null==e||t.type===e)}function la(t){return function(e,n,r){var o=!1,i=0,a=null;ua(t,(function(t,e,n,l){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var u,c=fa((function(e){var o;((o=e).__esModule||sa&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:Fi.extend(e),n.components[l]=e,--i<=0&&r()})),s=fa((function(t){var e="Failed to resolve async component "+l+": "+t;a||(a=ia(t)?t:new Error(e),r(a))}));try{u=t(c,s)}catch(t){s(t)}if(u)if("function"==typeof u.then)u.then(c,s);else{var f=u.component;f&&"function"==typeof f.then&&f.then(c,s)}}})),o||r()}}function ua(t,e){return ca(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function ca(t){return Array.prototype.concat.apply([],t)}var sa="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function fa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Ea=function(t,e){this.router=t,this.base=function(t){if(!t)if(Oi){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=Ko,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function pa(t,e,n,r){var o=ua(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=Fi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return ca(r?o.reverse():o)}function ha(t,e){if(e)return function(){return t.apply(e,arguments)}}Ea.prototype.listen=function(t){this.cb=t},Ea.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Ea.prototype.onError=function(t){this.errorCbs.push(t)},Ea.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&(aa(t,ta.redirected)&&i===Ko||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Ea.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,l=function(t){!aa(t)&&ia(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},u=t.matched.length-1,c=o.matched.length-1;if(Zo(t,o)&&u===c&&t.matched[u]===o.matched[c])return this.ensureURL(),t.hash&&Ni(this.router,o,t,!1),l(((a=ra(i=o,t,ta.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var s=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n<r&&t[n]===e[n];n++);return{updated:e.slice(0,n),activated:e.slice(n),deactivated:t.slice(n)}}(this.current.matched,t.matched),f=s.updated,E=s.deactivated,p=s.activated,h=[].concat(function(t){return pa(t,"beforeRouteLeave",ha,!0)}(E),this.router.beforeHooks,function(t){return pa(t,"beforeRouteUpdate",ha)}(f),p.map((function(t){return t.beforeEnter})),la(p)),d=function(e,n){if(r.pending!==t)return l(na(o,t));try{e(t,o,(function(e){!1===e?(r.ensureURL(!0),l(function(t,e){return ra(t,e,ta.aborted,'Navigation aborted from "'+t.fullPath+'" to "'+e.fullPath+'" via a navigation guard.')}(o,t))):ia(e)?(r.ensureURL(!0),l(e)):"string"==typeof e||"object"==typeof e&&("string"==typeof e.path||"string"==typeof e.name)?(l(ea(o,t)),"object"==typeof e&&e.replace?r.replace(e):r.push(e)):n(e)}))}catch(t){l(t)}};Zi(h,d,(function(){Zi(function(t){return pa(t,"beforeRouteEnter",(function(t,e,n,r){return function(t,e,n){return function(r,o,i){return t(r,o,(function(t){"function"==typeof t&&(e.enteredCbs[n]||(e.enteredCbs[n]=[]),e.enteredCbs[n].push(t)),i(t)}))}}(t,n,r)}))}(p).concat(r.router.resolveHooks),d,(function(){if(r.pending!==t)return l(na(o,t));r.pending=null,e(t),r.router.app&&r.router.app.$nextTick((function(){ei(t)}))}))}))},Ea.prototype.updateRoute=function(t){this.current=t,this.cb&&this.cb(t)},Ea.prototype.setupListeners=function(){},Ea.prototype.teardown=function(){this.listeners.forEach((function(t){t()})),this.listeners=[],this.current=Ko,this.pending=null};var da=function(t){function e(e,n){t.call(this,e,n),this._startLocation=va(this.base)}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router,n=e.options.scrollBehavior,r=Ki&&n;r&&this.listeners.push(Ii());var o=function(){var n=t.current,o=va(t.base);t.current===Ko&&o===t._startLocation||t.transitionTo(o,(function(t){r&&Ni(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ji(ii(r.base+t.fullPath)),Ni(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Qi(ii(r.base+t.fullPath)),Ni(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(va(this.base)!==this.current.fullPath){var e=ii(this.base+this.current.fullPath);t?Ji(e):Qi(e)}},e.prototype.getCurrentLocation=function(){return va(this.base)},e}(Ea);function va(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(ii(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Aa=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=va(t);if(!/^\/#/.test(e))return window.location.replace(ii(t+"/#"+e)),!0}(this.base)||Ba()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=Ki&&e;n&&this.listeners.push(Ii());var r=function(){var e=t.current;Ba()&&t.transitionTo(ma(),(function(r){n&&Ni(t.router,r,e,!0),Ki||Ca(r.fullPath)}))},o=Ki?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ba(t.fullPath),Ni(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ca(t.fullPath),Ni(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;ma()!==e&&(t?ba(e):Ca(e))},e.prototype.getCurrentLocation=function(){return ma()},e}(Ea);function Ba(){var t=ma();return"/"===t.charAt(0)||(Ca("/"+t),!1)}function ma(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function ya(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function ba(t){Ki?Ji(ya(t)):window.location.hash=t}function Ca(t){Ki?Qi(ya(t)):window.location.replace(ya(t))}var xa=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){aa(t,ta.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Ea),Fa=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Si(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!Ki&&!1!==t.fallback,this.fallback&&(e="hash"),Oi||(e="abstract"),this.mode=e,e){case"history":this.history=new da(this,t.base);break;case"hash":this.history=new Aa(this,t.base,this.fallback);break;case"abstract":this.history=new xa(this,t.base);break;default:0}},wa={currentRoute:{configurable:!0}};function _a(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}Fa.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},wa.currentRoute.get=function(){return this.history&&this.history.current},Fa.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof da||n instanceof Aa){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;Ki&&o&&"fullPath"in t&&Ni(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},Fa.prototype.beforeEach=function(t){return _a(this.beforeHooks,t)},Fa.prototype.beforeResolve=function(t){return _a(this.resolveHooks,t)},Fa.prototype.afterEach=function(t){return _a(this.afterHooks,t)},Fa.prototype.onReady=function(t,e){this.history.onReady(t,e)},Fa.prototype.onError=function(t){this.history.onError(t)},Fa.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},Fa.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},Fa.prototype.go=function(t){this.history.go(t)},Fa.prototype.back=function(){this.go(-1)},Fa.prototype.forward=function(){this.go(1)},Fa.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},Fa.prototype.resolve=function(t,e,n){var r=xi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?ii(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},Fa.prototype.getRoutes=function(){return this.matcher.getRoutes()},Fa.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==Ko&&this.history.transitionTo(this.history.getCurrentLocation())},Fa.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==Ko&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(Fa.prototype,wa),Fa.install=function t(e){if(!t.installed||Fi!==e){t.installed=!0,Fi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",ni),e.component("RouterLink",_i);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},Fa.version="3.5.4",Fa.isNavigationFailure=aa,Fa.NavigationFailureType=ta,Fa.START_LOCATION=Ko,Oi&&window.Vue&&window.Vue.use(Fa);var Pa=Fa;n(261),n(262),n(129),n(264),n(265);function Oa(t){t.locales&&Object.keys(t.locales).forEach((function(e){t.locales[e].path=e})),Object.freeze(t)}var ka=n(67),Da=(n(32),n(97),n(215),n(216),{NotFound:function(){return n.e(12).then(n.bind(null,436))},Layout:function(){return Promise.all([n.e(0),n.e(2)]).then(n.bind(null,435))}}),Sa={"v-71a99e66":function(){return n.e(13).then(n.bind(null,439))},"v-a20b36e4":function(){return n.e(6).then(n.bind(null,440))},"v-ee79e108":function(){return n.e(14).then(n.bind(null,441))},"v-fda368f4":function(){return n.e(15).then(n.bind(null,442))},"v-61978e6d":function(){return n.e(17).then(n.bind(null,443))},"v-329e7f28":function(){return n.e(16).then(n.bind(null,444))},"v-1a70ad84":function(){return n.e(18).then(n.bind(null,445))},"v-62caf5b5":function(){return n.e(19).then(n.bind(null,446))},"v-1deba43b":function(){return n.e(20).then(n.bind(null,447))},"v-611574e1":function(){return n.e(21).then(n.bind(null,448))},"v-2ef128a8":function(){return n.e(22).then(n.bind(null,449))},"v-6ab2a0ec":function(){return n.e(23).then(n.bind(null,450))},"v-5a0d1bac":function(){return n.e(24).then(n.bind(null,451))},"v-45cc1068":function(){return n.e(25).then(n.bind(null,452))},"v-55499b6c":function(){return n.e(26).then(n.bind(null,453))},"v-2c2b04e8":function(){return n.e(7).then(n.bind(null,454))},"v-64b7cefe":function(){return n.e(27).then(n.bind(null,455))},"v-3fd2593f":function(){return n.e(28).then(n.bind(null,456))},"v-0047918d":function(){return n.e(29).then(n.bind(null,457))},"v-44843426":function(){return n.e(30).then(n.bind(null,458))},"v-89978b66":function(){return n.e(31).then(n.bind(null,459))},"v-ceaae2a6":function(){return n.e(32).then(n.bind(null,460))},"v-7620e30d":function(){return n.e(33).then(n.bind(null,461))},"v-5397376d":function(){return n.e(34).then(n.bind(null,462))},"v-310d8bcd":function(){return n.e(35).then(n.bind(null,463))},"v-0e83e02d":function(){return n.e(36).then(n.bind(null,464))},"v-14ebc3a2":function(){return n.e(37).then(n.bind(null,465))},"v-7467f5c8":function(){return n.e(8).then(n.bind(null,466))},"v-3a83efec":function(){return n.e(38).then(n.bind(null,467))},"v-782b6871":function(){return n.e(39).then(n.bind(null,468))},"v-1770fb24":function(){return n.e(40).then(n.bind(null,469))},"v-227dcdbc":function(){return n.e(9).then(n.bind(null,470))},"v-57547db7":function(){return n.e(41).then(n.bind(null,471))},"v-6c8c3522":function(){return n.e(43).then(n.bind(null,472))},"v-2c445ed2":function(){return n.e(42).then(n.bind(null,473))},"v-53a0a5fa":function(){return n.e(44).then(n.bind(null,474))},"v-4621012e":function(){return n.e(46).then(n.bind(null,475))},"v-5fecab4c":function(){return n.e(45).then(n.bind(null,476))},"v-3612bc2e":function(){return n.e(47).then(n.bind(null,477))},"v-e23dcfe4":function(){return n.e(48).then(n.bind(null,478))},"v-07f489a8":function(){return n.e(49).then(n.bind(null,479))},"v-4dc71560":function(){return n.e(51).then(n.bind(null,480))},"v-2a7e6e88":function(){return n.e(50).then(n.bind(null,481))},"v-24ece539":function(){return n.e(53).then(n.bind(null,482))},"v-314138aa":function(){return n.e(52).then(n.bind(null,483))},"v-475bcf6b":function(){return n.e(54).then(n.bind(null,484))},"v-254cabb0":function(){return n.e(55).then(n.bind(null,485))},"v-365e0f1c":function(){return n.e(56).then(n.bind(null,486))},"v-0b10c5fe":function(){return n.e(57).then(n.bind(null,487))},"v-2cc5e709":function(){return n.e(58).then(n.bind(null,488))},"v-9f23503e":function(){return n.e(59).then(n.bind(null,489))},"v-e883b430":function(){return n.e(61).then(n.bind(null,490))},"v-22d79379":function(){return n.e(60).then(n.bind(null,491))},"v-21f3b69e":function(){return n.e(62).then(n.bind(null,492))},"v-ad636568":function(){return n.e(63).then(n.bind(null,493))},"v-d72197ac":function(){return n.e(65).then(n.bind(null,494))},"v-5171cdf8":function(){return n.e(64).then(n.bind(null,495))},"v-6957f54a":function(){return n.e(66).then(n.bind(null,496))},"v-231e64b8":function(){return n.e(67).then(n.bind(null,497))},"v-87aaba38":function(){return n.e(69).then(n.bind(null,498))},"v-58420d13":function(){return n.e(68).then(n.bind(null,499))},"v-7ebcd2e0":function(){return n.e(71).then(n.bind(null,500))},"v-5dcc80b0":function(){return n.e(70).then(n.bind(null,501))},"v-56f3a69d":function(){return n.e(72).then(n.bind(null,502))},"v-6dd192e7":function(){return n.e(73).then(n.bind(null,503))},"v-128e0dcf":function(){return n.e(74).then(n.bind(null,504))},"v-123af4a6":function(){return n.e(75).then(n.bind(null,505))},"v-3938ca42":function(){return n.e(76).then(n.bind(null,506))},"v-93d96b0a":function(){return n.e(77).then(n.bind(null,507))},"v-c47b14c8":function(){return n.e(78).then(n.bind(null,508))},"v-48e51b63":function(){return n.e(79).then(n.bind(null,509))},"v-628f98af":function(){return n.e(80).then(n.bind(null,510))},"v-1b8f6bee":function(){return n.e(81).then(n.bind(null,511))},"v-45c4720f":function(){return n.e(82).then(n.bind(null,512))},"v-7bd54dee":function(){return n.e(84).then(n.bind(null,513))},"v-e4106de2":function(){return n.e(83).then(n.bind(null,514))},"v-5231250e":function(){return n.e(85).then(n.bind(null,515))},"v-6c2c5722":function(){return n.e(86).then(n.bind(null,516))},"v-0b661dcb":function(){return n.e(87).then(n.bind(null,517))},"v-23694af3":function(){return n.e(88).then(n.bind(null,518))},"v-16b78eb9":function(){return n.e(89).then(n.bind(null,519))},"v-310eb5b9":function(){return n.e(90).then(n.bind(null,520))},"v-2c36d961":function(){return n.e(91).then(n.bind(null,521))},"v-39563743":function(){return n.e(93).then(n.bind(null,522))},"v-e1e5720a":function(){return n.e(94).then(n.bind(null,523))},"v-19af4dc6":function(){return n.e(92).then(n.bind(null,524))},"v-28707b06":function(){return n.e(95).then(n.bind(null,525))},"v-5f93f7fe":function(){return n.e(97).then(n.bind(null,526))},"v-762f0d70":function(){return n.e(96).then(n.bind(null,527))},"v-79abb1e4":function(){return n.e(98).then(n.bind(null,528))},"v-5da83102":function(){return n.e(99).then(n.bind(null,529))},"v-44ab1fb4":function(){return n.e(100).then(n.bind(null,530))},"v-34fdc569":function(){return n.e(101).then(n.bind(null,531))},"v-30048c0c":function(){return n.e(102).then(n.bind(null,532))},"v-4e6402b2":function(){return n.e(10).then(n.bind(null,533))},"v-11556580":function(){return n.e(104).then(n.bind(null,534))},"v-be112ee8":function(){return n.e(103).then(n.bind(null,535))},"v-4100a20c":function(){return n.e(105).then(n.bind(null,536))},"v-86d852e8":function(){return n.e(106).then(n.bind(null,537))},"v-5bae8fd8":function(){return n.e(107).then(n.bind(null,538))},"v-df237aa0":function(){return n.e(11).then(n.bind(null,539))},"v-6c1b55eb":function(){return n.e(109).then(n.bind(null,540))},"v-133fd176":function(){return n.e(110).then(n.bind(null,541))},"v-39370fa0":function(){return n.e(108).then(n.bind(null,542))},"v-4e9f312a":function(){return n.e(111).then(n.bind(null,543))},"v-946548b6":function(){return n.e(112).then(n.bind(null,544))}};function ja(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var Ta=/-(\w)/g,Ma=ja((function(t){return t.replace(Ta,(function(t,e){return e?e.toUpperCase():""}))})),$a=/\B([A-Z])/g,La=ja((function(t){return t.replace($a,"-$1").toLowerCase()})),Ua=ja((function(t){return t.charAt(0).toUpperCase()+t.slice(1)}));function Ra(t,e){if(e)return t(e)?t(e):e.includes("-")?t(Ua(Ma(e))):t(Ua(e))||t(La(e))}var Ia=Object.assign({},Da,Sa),Na=function(t){return Ia[t]},za=function(t){return Sa[t]},Va=function(t){return Da[t]},qa=function(t){return Lo.component(t)};function Ga(t){return Ra(za,t)}function Wa(t){return Ra(Va,t)}function Ha(t){return Ra(Na,t)}function Xa(t){return Ra(qa,t)}function Ya(){for(var t=arguments.length,e=new Array(t),n=0;n<t;n++)e[n]=arguments[n];return Promise.all(e.filter((function(t){return t})).map(function(){var t=a(o().mark((function t(e){var n;return o().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(Xa(e)||!Ha(e)){t.next=5;break}return t.next=3,Ha(e)();case 3:n=t.sent,Lo.component(e,n.default);case 5:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()))}function Ka(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}n(130);var Ja=n(93);function Qa(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=n){var r,o,i=[],a=!0,l=!1;try{for(n=n.call(t);!(a=(r=n.next()).done)&&(i.push(r.value),!e||i.length!==e);a=!0);}catch(t){l=!0,o=t}finally{try{a||null==n.return||n.return()}finally{if(l)throw o}}return i}}(t,e)||Object(Ja.a)(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}n(167),n(206),n(217);var Za=n(201),tl=n.n(Za),el=n(202),nl=n.n(el),rl={created:function(){if(this.siteMeta=this.$site.headTags.filter((function(t){return"meta"===Qa(t,1)[0]})).map((function(t){var e=Qa(t,2);e[0];return e[1]})),this.$ssrContext){var t=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(e=t)?e.map((function(t){var e="<meta";return Object.keys(t).forEach((function(n){e+=" ".concat(n,'="').concat(nl()(t[n]),'"')})),e+">"})).join("\n "):"",this.$ssrContext.canonicalLink=il(this.$canonicalUrl)}var e},mounted:function(){this.currentMetaTags=Object(ka.a)(document.querySelectorAll("meta")),this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta:function(){document.title=this.$title,document.documentElement.lang=this.$lang;var t=this.getMergedMetaTags();this.currentMetaTags=al(t,this.currentMetaTags)},getMergedMetaTags:function(){var t=this.$page.frontmatter.meta||[];return tl()([{name:"description",content:this.$description}],t,this.siteMeta,ll)},updateCanonicalLink:function(){ol(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",il(this.$canonicalUrl))}},watch:{$page:function(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy:function(){al(null,this.currentMetaTags),ol()}};function ol(){var t=document.querySelector("link[rel='canonical']");t&&t.remove()}function il(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return t?'<link href="'.concat(t,'" rel="canonical" />'):""}function al(t,e){if(e&&Object(ka.a)(e).filter((function(t){return t.parentNode===document.head})).forEach((function(t){return document.head.removeChild(t)})),t)return t.map((function(t){var e=document.createElement("meta");return Object.keys(t).forEach((function(n){e.setAttribute(n,t[n])})),document.head.appendChild(e),e}))}function ll(t){for(var e=0,n=["name","property","itemprop"];e<n.length;e++){var r=n[e];if(t.hasOwnProperty(r))return t[r]+r}return JSON.stringify(t)}n(128);var ul=n(94),cl=n.n(ul),sl={mounted:function(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:cl()((function(){this.setActiveHash()}),300),setActiveHash:function(){for(var t=this,e=[].slice.call(document.querySelectorAll(".sidebar-link")),n=[].slice.call(document.querySelectorAll(".header-anchor")).filter((function(t){return e.some((function(e){return e.hash===t.hash}))})),r=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),o=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),i=window.innerHeight+r,a=0;a<n.length;a++){var l=n[a],u=n[a+1],c=0===a&&0===r||r>=l.parentElement.offsetTop+10&&(!u||r<u.parentElement.offsetTop-10),s=decodeURIComponent(this.$route.hash);if(c&&s!==decodeURIComponent(l.hash)){var f=l;if(i===o)for(var E=a+1;E<n.length;E++)if(s===decodeURIComponent(n[E].hash))return;return this.$vuepress.$set("disableScrollBehavior",!0),void this.$router.replace(decodeURIComponent(f.hash),(function(){t.$nextTick((function(){t.$vuepress.$set("disableScrollBehavior",!1)}))}))}}}},beforeDestroy:function(){window.removeEventListener("scroll",this.onScroll)}},fl=n(203),El=n.n(fl),pl={mounted:function(){El.a.polyfill()}},hl=n(95),dl=n.n(hl),vl=[rl,sl,pl,{mounted:function(){var t=this;dl.a.configure({showSpinner:!1}),this.$router.beforeEach((function(t,e,n){t.path===e.path||Lo.component(t.name)||dl.a.start(),n()})),this.$router.afterEach((function(){dl.a.done(),t.isSidebarOpen=!1}))}}],Al={name:"GlobalLayout",computed:{layout:function(){var t=this.getLayout();return Ka("layout",t),Lo.component(t)}},methods:{getLayout:function(){if(this.$page.path){var t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},Bl=n(36),gl=Object(Bl.a)(Al,(function(){var t=this.$createElement;return(this._self._c||t)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){var r;switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),(r=t[e]).push.apply(r,Object(ka.a)(n));break;default:throw new Error("Unknown option name.")}}(gl,"mixins",vl);var ml=[{name:"v-71a99e66",path:"/CHANGELOG.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-71a99e66").then(n)}},{name:"v-a20b36e4",path:"/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-a20b36e4").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-ee79e108",path:"/runtime/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-ee79e108").then(n)}},{path:"/runtime/index.html",redirect:"/runtime/"},{name:"v-fda368f4",path:"/runtime/gmp/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-fda368f4").then(n)}},{path:"/runtime/gmp/index.html",redirect:"/runtime/gmp/"},{name:"v-61978e6d",path:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-61978e6d").then(n)}},{path:"/runtime/三色gc算法/",redirect:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/"},{path:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/index.html",redirect:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/"},{path:"/runtime/三色gc算法/",redirect:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/"},{name:"v-329e7f28",path:"/runtime/netpool/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-329e7f28").then(n)}},{path:"/runtime/netpool/index.html",redirect:"/runtime/netpool/"},{name:"v-1a70ad84",path:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-1a70ad84").then(n)}},{path:"/runtime/堆内存分配/",redirect:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/"},{path:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/index.html",redirect:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/"},{path:"/runtime/堆内存分配/",redirect:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/"},{name:"v-62caf5b5",path:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-62caf5b5").then(n)}},{path:"/runtime/定时器/",redirect:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/"},{path:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/index.html",redirect:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/"},{path:"/runtime/定时器/",redirect:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/"},{name:"v-1deba43b",path:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-1deba43b").then(n)}},{path:"/runtime/栈内存管理/",redirect:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/"},{path:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/index.html",redirect:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/"},{path:"/runtime/栈内存管理/",redirect:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/"},{name:"v-611574e1",path:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-611574e1").then(n)}},{path:"/runtime/系统监控/",redirect:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/"},{path:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/index.html",redirect:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/"},{path:"/runtime/系统监控/",redirect:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/"},{name:"v-2ef128a8",path:"/%E5%9F%BA%E7%A1%80/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-2ef128a8").then(n)}},{path:"/基础/",redirect:"/%E5%9F%BA%E7%A1%80/"},{path:"/%E5%9F%BA%E7%A1%80/index.html",redirect:"/%E5%9F%BA%E7%A1%80/"},{path:"/基础/",redirect:"/%E5%9F%BA%E7%A1%80/"},{name:"v-6ab2a0ec",path:"/%E5%9F%BA%E7%A1%80/helloWorld/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-6ab2a0ec").then(n)}},{path:"/基础/helloWorld/",redirect:"/%E5%9F%BA%E7%A1%80/helloWorld/"},{path:"/%E5%9F%BA%E7%A1%80/helloWorld/index.html",redirect:"/%E5%9F%BA%E7%A1%80/helloWorld/"},{path:"/基础/helloWorld/",redirect:"/%E5%9F%BA%E7%A1%80/helloWorld/"},{name:"v-5a0d1bac",path:"/%E5%9F%BA%E7%A1%80/interface/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5a0d1bac").then(n)}},{path:"/基础/interface/",redirect:"/%E5%9F%BA%E7%A1%80/interface/"},{path:"/%E5%9F%BA%E7%A1%80/interface/index.html",redirect:"/%E5%9F%BA%E7%A1%80/interface/"},{path:"/基础/interface/",redirect:"/%E5%9F%BA%E7%A1%80/interface/"},{name:"v-45cc1068",path:"/%E5%9F%BA%E7%A1%80/slice/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-45cc1068").then(n)}},{path:"/基础/slice/",redirect:"/%E5%9F%BA%E7%A1%80/slice/"},{path:"/%E5%9F%BA%E7%A1%80/slice/index.html",redirect:"/%E5%9F%BA%E7%A1%80/slice/"},{path:"/基础/slice/",redirect:"/%E5%9F%BA%E7%A1%80/slice/"},{name:"v-55499b6c",path:"/%E5%9F%BA%E7%A1%80/string/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-55499b6c").then(n)}},{path:"/基础/string/",redirect:"/%E5%9F%BA%E7%A1%80/string/"},{path:"/%E5%9F%BA%E7%A1%80/string/index.html",redirect:"/%E5%9F%BA%E7%A1%80/string/"},{path:"/基础/string/",redirect:"/%E5%9F%BA%E7%A1%80/string/"},{name:"v-2c2b04e8",path:"/%E5%9F%BA%E7%A1%80/map/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-2c2b04e8").then(n)}},{path:"/基础/map/",redirect:"/%E5%9F%BA%E7%A1%80/map/"},{path:"/%E5%9F%BA%E7%A1%80/map/index.html",redirect:"/%E5%9F%BA%E7%A1%80/map/"},{path:"/基础/map/",redirect:"/%E5%9F%BA%E7%A1%80/map/"},{name:"v-64b7cefe",path:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-64b7cefe").then(n)}},{path:"/基础/作用域/",redirect:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/"},{path:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/"},{path:"/基础/作用域/",redirect:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/"},{name:"v-3fd2593f",path:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-3fd2593f").then(n)}},{path:"/基础/其他内容/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/"},{path:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/"},{path:"/基础/其他内容/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/"},{name:"v-0047918d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/0.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-0047918d").then(n)}},{path:"/基础/函数方法/0.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/0.html"},{path:"/基础/函数方法/0.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/0.html"},{name:"v-44843426",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-44843426").then(n)}},{path:"/基础/函数方法/1.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.html"},{path:"/基础/函数方法/1.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.html"},{name:"v-89978b66",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/2.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-89978b66").then(n)}},{path:"/基础/函数方法/2.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/2.html"},{path:"/基础/函数方法/2.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/2.html"},{name:"v-ceaae2a6",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-ceaae2a6").then(n)}},{path:"/基础/函数方法/3.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html"},{path:"/基础/函数方法/3.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html"},{name:"v-7620e30d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/4.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-7620e30d").then(n)}},{path:"/基础/函数方法/4.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/4.html"},{path:"/基础/函数方法/4.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/4.html"},{name:"v-5397376d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/5.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5397376d").then(n)}},{path:"/基础/函数方法/5.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/5.html"},{path:"/基础/函数方法/5.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/5.html"},{name:"v-310d8bcd",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/6.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-310d8bcd").then(n)}},{path:"/基础/函数方法/6.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/6.html"},{path:"/基础/函数方法/6.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/6.html"},{name:"v-0e83e02d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-0e83e02d").then(n)}},{path:"/基础/函数方法/7.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html"},{path:"/基础/函数方法/7.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html"},{name:"v-14ebc3a2",path:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-14ebc3a2").then(n)}},{path:"/基础/变量声明/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/"},{path:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/"},{path:"/基础/变量声明/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/"},{name:"v-7467f5c8",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-7467f5c8").then(n)}},{path:"/基础/函数方法/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/"},{path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/"},{path:"/基础/函数方法/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/"},{name:"v-3a83efec",path:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-3a83efec").then(n)}},{path:"/基础/复合字面量/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/"},{path:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/"},{path:"/基础/复合字面量/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/"},{name:"v-782b6871",path:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-782b6871").then(n)}},{path:"/基础/常量声明/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/"},{path:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/"},{path:"/基础/常量声明/",redirect:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/"},{name:"v-1770fb24",path:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-1770fb24").then(n)}},{path:"/基础/求值顺序/",redirect:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/"},{path:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/"},{path:"/基础/求值顺序/",redirect:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/"},{name:"v-227dcdbc",path:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-227dcdbc").then(n)}},{path:"/基础/数字类型/",redirect:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/"},{path:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/"},{path:"/基础/数字类型/",redirect:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/"},{name:"v-57547db7",path:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-57547db7").then(n)}},{path:"/基础/泛型/",redirect:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/"},{path:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/"},{path:"/基础/泛型/",redirect:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/"},{name:"v-6c8c3522",path:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-6c8c3522").then(n)}},{path:"/基础/逻辑和判断语句/",redirect:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/"},{path:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/"},{path:"/基础/逻辑和判断语句/",redirect:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/"},{name:"v-2c445ed2",path:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-2c445ed2").then(n)}},{path:"/基础/结构体/",redirect:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/"},{path:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/"},{path:"/基础/结构体/",redirect:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/"},{name:"v-53a0a5fa",path:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-53a0a5fa").then(n)}},{path:"/基础/错误处理/",redirect:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/"},{path:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/"},{path:"/基础/错误处理/",redirect:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/"},{name:"v-4621012e",path:"/%E5%B7%A5%E7%A8%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-4621012e").then(n)}},{path:"/工程/",redirect:"/%E5%B7%A5%E7%A8%8B/"},{path:"/%E5%B7%A5%E7%A8%8B/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/"},{path:"/工程/",redirect:"/%E5%B7%A5%E7%A8%8B/"},{name:"v-5fecab4c",path:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5fecab4c").then(n)}},{path:"/基础/零值/",redirect:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/"},{path:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/index.html",redirect:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/"},{path:"/基础/零值/",redirect:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/"},{name:"v-3612bc2e",path:"/%E5%B7%A5%E7%A8%8B/cgo/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-3612bc2e").then(n)}},{path:"/工程/cgo/",redirect:"/%E5%B7%A5%E7%A8%8B/cgo/"},{path:"/%E5%B7%A5%E7%A8%8B/cgo/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/cgo/"},{path:"/工程/cgo/",redirect:"/%E5%B7%A5%E7%A8%8B/cgo/"},{name:"v-e23dcfe4",path:"/%E5%B7%A5%E7%A8%8B/copilot/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-e23dcfe4").then(n)}},{path:"/工程/copilot/",redirect:"/%E5%B7%A5%E7%A8%8B/copilot/"},{path:"/%E5%B7%A5%E7%A8%8B/copilot/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/copilot/"},{path:"/工程/copilot/",redirect:"/%E5%B7%A5%E7%A8%8B/copilot/"},{name:"v-07f489a8",path:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-07f489a8").then(n)}},{path:"/工程/goweb编程/",redirect:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/"},{path:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/"},{path:"/工程/goweb编程/",redirect:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/"},{name:"v-4dc71560",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-4dc71560").then(n)}},{path:"/工程/go标准库/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/"},{path:"/工程/go标准库/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/"},{name:"v-2a7e6e88",path:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-2a7e6e88").then(n)}},{path:"/工程/go命名惯例/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/"},{path:"/工程/go命名惯例/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/"},{name:"v-24ece539",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/fmt.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-24ece539").then(n)}},{path:"/工程/go标准库/fmt.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/fmt.html"},{path:"/工程/go标准库/fmt.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/fmt.html"},{name:"v-314138aa",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/encoding-hex.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-314138aa").then(n)}},{path:"/工程/go标准库/encoding-hex.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/encoding-hex.html"},{path:"/工程/go标准库/encoding-hex.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/encoding-hex.html"},{name:"v-475bcf6b",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-475bcf6b").then(n)}},{path:"/工程/go标准库/sync.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html"},{path:"/工程/go标准库/sync.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html"},{name:"v-254cabb0",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-254cabb0").then(n)}},{path:"/工程/go编程范式/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/"},{path:"/工程/go编程范式/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/"},{name:"v-365e0f1c",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-365e0f1c").then(n)}},{path:"/工程/go编程范式/k8s_visitor/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/"},{path:"/工程/go编程范式/k8s_visitor/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/"},{name:"v-0b10c5fe",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-0b10c5fe").then(n)}},{path:"/工程/go编程范式/pipeline/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/"},{path:"/工程/go编程范式/pipeline/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/"},{name:"v-2cc5e709",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-2cc5e709").then(n)}},{path:"/工程/go编程范式/代理/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/"},{path:"/工程/go编程范式/代理/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/"},{name:"v-9f23503e",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-9f23503e").then(n)}},{path:"/工程/go编程范式/信号量/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/"},{path:"/工程/go编程范式/信号量/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/"},{name:"v-e883b430",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-e883b430").then(n)}},{path:"/工程/go编程范式/功能选项/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/"},{path:"/工程/go编程范式/功能选项/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/"},{name:"v-22d79379",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-22d79379").then(n)}},{path:"/工程/go编程范式/创建者/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/"},{path:"/工程/go编程范式/创建者/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/"},{name:"v-21f3b69e",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-21f3b69e").then(n)}},{path:"/工程/go编程范式/单例/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/"},{path:"/工程/go编程范式/单例/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/"},{name:"v-ad636568",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-ad636568").then(n)}},{path:"/工程/go编程范式/原型/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/"},{path:"/工程/go编程范式/原型/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/"},{name:"v-d72197ac",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-d72197ac").then(n)}},{path:"/工程/go编程范式/定时函数/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/"},{path:"/工程/go编程范式/定时函数/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/"},{name:"v-5171cdf8",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5171cdf8").then(n)}},{path:"/工程/go编程范式/发布者订阅者/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/"},{path:"/工程/go编程范式/发布者订阅者/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/"},{name:"v-6957f54a",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-6957f54a").then(n)}},{path:"/工程/go编程范式/对象池/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/"},{path:"/工程/go编程范式/对象池/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/"},{name:"v-231e64b8",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-231e64b8").then(n)}},{path:"/工程/go编程范式/工厂方法/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/"},{path:"/工程/go编程范式/工厂方法/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/"},{name:"v-87aaba38",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-87aaba38").then(n)}},{path:"/工程/go编程范式/扇入/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/"},{path:"/工程/go编程范式/扇入/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/"},{name:"v-58420d13",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-58420d13").then(n)}},{path:"/工程/go编程范式/并行/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/"},{path:"/工程/go编程范式/并行/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/"},{name:"v-7ebcd2e0",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-7ebcd2e0").then(n)}},{path:"/工程/go编程范式/断路器/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/"},{path:"/工程/go编程范式/断路器/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/"},{name:"v-5dcc80b0",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5dcc80b0").then(n)}},{path:"/工程/go编程范式/扇出/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/"},{path:"/工程/go编程范式/扇出/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/"},{name:"v-56f3a69d",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-56f3a69d").then(n)}},{path:"/工程/go编程范式/有界并行/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/"},{path:"/工程/go编程范式/有界并行/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/"},{name:"v-6dd192e7",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-6dd192e7").then(n)}},{path:"/工程/go编程范式/生成器/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/"},{path:"/工程/go编程范式/生成器/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/"},{name:"v-128e0dcf",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-128e0dcf").then(n)}},{path:"/工程/go编程范式/策略/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/"},{path:"/工程/go编程范式/策略/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/"},{name:"v-123af4a6",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-123af4a6").then(n)}},{path:"/工程/go编程范式/装饰器/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/"},{path:"/工程/go编程范式/装饰器/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/"},{name:"v-3938ca42",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-3938ca42").then(n)}},{path:"/工程/go编程范式/观察者/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/"},{path:"/工程/go编程范式/观察者/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/"},{name:"v-93d96b0a",path:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-93d96b0a").then(n)}},{path:"/工程/go语言规范/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/"},{path:"/工程/go语言规范/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/"},{name:"v-c47b14c8",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-c47b14c8").then(n)}},{path:"/工程/go面试题/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/"},{path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/"},{path:"/工程/go面试题/",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/"},{name:"v-48e51b63",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/architect.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-48e51b63").then(n)}},{path:"/工程/go面试题/architect.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/architect.html"},{path:"/工程/go面试题/architect.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/architect.html"},{name:"v-628f98af",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/intermediate.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-628f98af").then(n)}},{path:"/工程/go面试题/intermediate.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/intermediate.html"},{path:"/工程/go面试题/intermediate.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/intermediate.html"},{name:"v-1b8f6bee",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/primary.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-1b8f6bee").then(n)}},{path:"/工程/go面试题/primary.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/primary.html"},{path:"/工程/go面试题/primary.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/primary.html"},{name:"v-45c4720f",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/senior.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-45c4720f").then(n)}},{path:"/工程/go面试题/senior.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/senior.html"},{path:"/工程/go面试题/senior.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/senior.html"},{name:"v-7bd54dee",path:"/%E5%B7%A5%E7%A8%8B/ioc/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-7bd54dee").then(n)}},{path:"/工程/ioc/",redirect:"/%E5%B7%A5%E7%A8%8B/ioc/"},{path:"/%E5%B7%A5%E7%A8%8B/ioc/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/ioc/"},{path:"/工程/ioc/",redirect:"/%E5%B7%A5%E7%A8%8B/ioc/"},{name:"v-e4106de2",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/%E4%B8%AD%E9%AB%98%E7%BA%A7go%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%80.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-e4106de2").then(n)}},{path:"/工程/go面试题/中高级go面试题一.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/%E4%B8%AD%E9%AB%98%E7%BA%A7go%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%80.html"},{path:"/工程/go面试题/中高级go面试题一.html",redirect:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/%E4%B8%AD%E9%AB%98%E7%BA%A7go%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%80.html"},{name:"v-5231250e",path:"/%E5%B7%A5%E7%A8%8B/log/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5231250e").then(n)}},{path:"/工程/log/",redirect:"/%E5%B7%A5%E7%A8%8B/log/"},{path:"/%E5%B7%A5%E7%A8%8B/log/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/log/"},{path:"/工程/log/",redirect:"/%E5%B7%A5%E7%A8%8B/log/"},{name:"v-6c2c5722",path:"/%E5%B7%A5%E7%A8%8B/wasm/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-6c2c5722").then(n)}},{path:"/工程/wasm/",redirect:"/%E5%B7%A5%E7%A8%8B/wasm/"},{path:"/%E5%B7%A5%E7%A8%8B/wasm/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/wasm/"},{path:"/工程/wasm/",redirect:"/%E5%B7%A5%E7%A8%8B/wasm/"},{name:"v-0b661dcb",path:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-0b661dcb").then(n)}},{path:"/工程/代码检查/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/"},{path:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/"},{path:"/工程/代码检查/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/"},{name:"v-23694af3",path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-23694af3").then(n)}},{path:"/工程/优秀第三方包/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/"},{path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/"},{path:"/工程/优秀第三方包/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/"},{name:"v-16b78eb9",path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-16b78eb9").then(n)}},{path:"/工程/优秀第三方包/gin/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/"},{path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/"},{path:"/工程/优秀第三方包/gin/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/"},{name:"v-310eb5b9",path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-310eb5b9").then(n)}},{path:"/工程/优秀第三方包/sonic/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/"},{path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/"},{path:"/工程/优秀第三方包/sonic/",redirect:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/"},{name:"v-2c36d961",path:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-2c36d961").then(n)}},{path:"/工程/动态调试/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/"},{path:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/"},{path:"/工程/动态调试/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/"},{name:"v-39563743",path:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-39563743").then(n)}},{path:"/工程/反射/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/"},{path:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/"},{path:"/工程/反射/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/"},{name:"v-e1e5720a",path:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-e1e5720a").then(n)}},{path:"/工程/命令/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/"},{path:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/"},{path:"/工程/命令/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/"},{name:"v-19af4dc6",path:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-19af4dc6").then(n)}},{path:"/工程/包及其构建工具/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/"},{path:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/"},{path:"/工程/包及其构建工具/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/"},{name:"v-28707b06",path:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-28707b06").then(n)}},{path:"/工程/坑/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/"},{path:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/"},{path:"/工程/坑/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/"},{name:"v-5f93f7fe",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5f93f7fe").then(n)}},{path:"/工程/测试/",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/"},{path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/"},{path:"/工程/测试/",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/"},{name:"v-762f0d70",path:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-762f0d70").then(n)}},{path:"/工程/字符编码/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/"},{path:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/"},{path:"/工程/字符编码/",redirect:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/"},{name:"v-79abb1e4",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-79abb1e4").then(n)}},{path:"/工程/测试/基准测试.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html"},{path:"/工程/测试/基准测试.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html"},{name:"v-5da83102",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5da83102").then(n)}},{path:"/工程/测试/基础测试.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95.html"},{path:"/工程/测试/基础测试.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95.html"},{name:"v-44ab1fb4",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E6%A8%A1%E7%B3%8A%E6%B5%8B%E8%AF%95.html",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-44ab1fb4").then(n)}},{path:"/工程/测试/模糊测试.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E6%A8%A1%E7%B3%8A%E6%B5%8B%E8%AF%95.html"},{path:"/工程/测试/模糊测试.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E6%A8%A1%E7%B3%8A%E6%B5%8B%E8%AF%95.html"},{name:"v-34fdc569",path:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-34fdc569").then(n)}},{path:"/工程/系统信号的处理/",redirect:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/"},{path:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/"},{path:"/工程/系统信号的处理/",redirect:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/"},{name:"v-30048c0c",path:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-30048c0c").then(n)}},{path:"/工程/读写模型/",redirect:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/"},{path:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/"},{path:"/工程/读写模型/",redirect:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/"},{name:"v-4e6402b2",path:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-4e6402b2").then(n)}},{path:"/工程/项目组织形式/",redirect:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/"},{path:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/index.html",redirect:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/"},{path:"/工程/项目组织形式/",redirect:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/"},{name:"v-11556580",path:"/%E5%B9%B6%E5%8F%91/atomic/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-11556580").then(n)}},{path:"/并发/atomic/",redirect:"/%E5%B9%B6%E5%8F%91/atomic/"},{path:"/%E5%B9%B6%E5%8F%91/atomic/index.html",redirect:"/%E5%B9%B6%E5%8F%91/atomic/"},{path:"/并发/atomic/",redirect:"/%E5%B9%B6%E5%8F%91/atomic/"},{name:"v-be112ee8",path:"/%E5%B9%B6%E5%8F%91/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-be112ee8").then(n)}},{path:"/并发/",redirect:"/%E5%B9%B6%E5%8F%91/"},{path:"/%E5%B9%B6%E5%8F%91/index.html",redirect:"/%E5%B9%B6%E5%8F%91/"},{path:"/并发/",redirect:"/%E5%B9%B6%E5%8F%91/"},{name:"v-4100a20c",path:"/%E5%B9%B6%E5%8F%91/channel/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-4100a20c").then(n)}},{path:"/并发/channel/",redirect:"/%E5%B9%B6%E5%8F%91/channel/"},{path:"/%E5%B9%B6%E5%8F%91/channel/index.html",redirect:"/%E5%B9%B6%E5%8F%91/channel/"},{path:"/并发/channel/",redirect:"/%E5%B9%B6%E5%8F%91/channel/"},{name:"v-86d852e8",path:"/%E5%B9%B6%E5%8F%91/context/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-86d852e8").then(n)}},{path:"/并发/context/",redirect:"/%E5%B9%B6%E5%8F%91/context/"},{path:"/%E5%B9%B6%E5%8F%91/context/index.html",redirect:"/%E5%B9%B6%E5%8F%91/context/"},{path:"/并发/context/",redirect:"/%E5%B9%B6%E5%8F%91/context/"},{name:"v-5bae8fd8",path:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-5bae8fd8").then(n)}},{path:"/并发/内存模型/",redirect:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/"},{path:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/index.html",redirect:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/"},{path:"/并发/内存模型/",redirect:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/"},{name:"v-df237aa0",path:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-df237aa0").then(n)}},{path:"/并发/同步原语/",redirect:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/"},{path:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/index.html",redirect:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/"},{path:"/并发/同步原语/",redirect:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/"},{name:"v-6c1b55eb",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-6c1b55eb").then(n)}},{path:"/编译器/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/"},{path:"/%E7%BC%96%E8%AF%91%E5%99%A8/index.html",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/"},{path:"/编译器/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/"},{name:"v-133fd176",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-133fd176").then(n)}},{path:"/编译器/gc/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/"},{path:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/index.html",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/"},{path:"/编译器/gc/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/"},{name:"v-39370fa0",path:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-39370fa0").then(n)}},{path:"/并发/并发模型/",redirect:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/"},{path:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/index.html",redirect:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/"},{path:"/并发/并发模型/",redirect:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/"},{name:"v-4e9f312a",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-4e9f312a").then(n)}},{path:"/编译器/gccgo/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/"},{path:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/index.html",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/"},{path:"/编译器/gccgo/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/"},{name:"v-946548b6",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/",component:gl,beforeEnter:function(t,e,n){Ya("Layout","v-946548b6").then(n)}},{path:"/编译器/llvm/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/"},{path:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/index.html",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/"},{path:"/编译器/llvm/",redirect:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/"},{path:"*",component:gl}],yl={title:"GOFamily - go 程序员宝典",description:"🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系",base:"/GOFamily/",headTags:[["link",{rel:"shortcut icon",type:"image/x-icon",href:"/GOFamily/favicon.ico"}]],pages:[{frontmatter:{},regularPath:"/CHANGELOG.html",relativePath:"CHANGELOG.md",key:"v-71a99e66",path:"/CHANGELOG.html",headers:[{level:2,title:"v0.3.0 (2022-03-02)",slug:"v0-3-0-2022-03-02"},{level:2,title:"Features",slug:"features"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/",relativePath:"README.md",key:"v-a20b36e4",path:"/",headers:[{level:2,title:"基础",slug:"基础"},{level:2,title:"并发",slug:"并发"},{level:2,title:"runtime",slug:"runtime"},{level:2,title:"编译器",slug:"编译器"},{level:2,title:"工程",slug:"工程"},{level:2,title:"参考资料",slug:"参考资料"},{level:2,title:"扫一扫添加我的公众号,回复 “加群”,可以加入微信群。",slug:"扫一扫添加我的公众号-回复-加群-可以加入微信群。"},{level:2,title:"star",slug:"star"},{level:2,title:"证书",slug:"证书"}],lastUpdated:"1/29/2024, 2:12:13 PM",lastUpdatedTimestamp:1706537533e3},{title:"runtime",frontmatter:{},regularPath:"/runtime/",relativePath:"runtime/README.md",key:"v-ee79e108",path:"/runtime/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/runtime/gmp/",relativePath:"runtime/gmp/README.md",key:"v-fda368f4",path:"/runtime/gmp/",headers:[{level:2,title:"参考文章",slug:"参考文章"}],lastUpdated:"11/26/2023, 3:56:49 PM",lastUpdatedTimestamp:1701014209e3},{title:"参考资料",frontmatter:{},regularPath:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/",relativePath:"runtime/三色gc算法/README.md",key:"v-61978e6d",path:"/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{frontmatter:{},regularPath:"/runtime/netpool/",relativePath:"runtime/netpool/README.md",key:"v-329e7f28",path:"/runtime/netpool/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/19/2023, 9:25:00 AM",lastUpdatedTimestamp:16844883e5},{frontmatter:{},regularPath:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/",relativePath:"runtime/堆内存分配/README.md",key:"v-1a70ad84",path:"/runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D/",lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{frontmatter:{},regularPath:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/",relativePath:"runtime/定时器/README.md",key:"v-62caf5b5",path:"/runtime/%E5%AE%9A%E6%97%B6%E5%99%A8/",lastUpdated:"1/5/2024, 2:48:04 PM",lastUpdatedTimestamp:1704466084e3},{frontmatter:{},regularPath:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/",relativePath:"runtime/栈内存管理/README.md",key:"v-1deba43b",path:"/runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/",lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{frontmatter:{},regularPath:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/",relativePath:"runtime/系统监控/README.md",key:"v-611574e1",path:"/runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7/",lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"基础",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/",relativePath:"基础/README.md",key:"v-2ef128a8",path:"/%E5%9F%BA%E7%A1%80/",lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/helloWorld/",relativePath:"基础/helloWorld/README.md",key:"v-6ab2a0ec",path:"/%E5%9F%BA%E7%A1%80/helloWorld/",headers:[{level:2,title:"诞生背景",slug:"诞生背景"},{level:2,title:"语言哲学",slug:"语言哲学"},{level:2,title:"语言特点",slug:"语言特点"},{level:2,title:"安装 Go",slug:"安装-go"},{level:2,title:"hello world",slug:"hello-world-2"}],lastUpdated:"1/26/2024, 10:08:28 AM",lastUpdatedTimestamp:1706263708e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/interface/",relativePath:"基础/interface/README.md",key:"v-5a0d1bac",path:"/%E5%9F%BA%E7%A1%80/interface/",headers:[{level:2,title:"方法集合决定接口的实现",slug:"方法集合决定接口的实现"},{level:2,title:"接口嵌入",slug:"接口嵌入"},{level:3,title:"在接口中嵌入接口类型",slug:"在接口中嵌入接口类型"},{level:3,title:"在结构体中嵌入接口类型",slug:"在结构体中嵌入接口类型"},{level:2,title:"匿名接口",slug:"匿名接口"},{level:2,title:"类型断言",slug:"类型断言"},{level:3,title:"常规的断言方式:",slug:"常规的断言方式"},{level:3,title:"存在于 switch 中的断言方式:",slug:"存在于-switch-中的断言方式"},{level:3,title:"断言类型也可以是接口",slug:"断言类型也可以是接口"},{level:2,title:"接口类型的底层",slug:"接口类型的底层"},{level:2,title:"如何判断接口类型的相等",slug:"如何判断接口类型的相等"},{level:2,title:"小接口的意义",slug:"小接口的意义"},{level:3,title:"如何设计小接口",slug:"如何设计小接口"},{level:2,title:"不可滥用空接口",slug:"不可滥用空接口"},{level:2,title:"接口作为程序水平组合的连接点,提供程序的可扩展性",slug:"接口作为程序水平组合的连接点-提供程序的可扩展性"},{level:2,title:"接口提供程序的可测试性",slug:"接口提供程序的可测试性"},{level:2,title:"接口的严格和函数的宽松对比",slug:"接口的严格和函数的宽松对比"},{level:2,title:"issues",slug:"issues"},{level:3,title:"interface 如何判断 nil",slug:"interface-如何判断-nil"},{level:3,title:"论述 “nil error != nil” 的原因",slug:"论述-nil-error-nil-的原因"},{level:3,title:"eface 和 iface 的区别",slug:"eface-和-iface-的区别"},{level:3,title:"如何查找 interface 中的方法",slug:"如何查找-interface-中的方法"},{level:3,title:"interface 设计的优缺点",slug:"interface-设计的优缺点"},{level:3,title:"空接口类型和一般类型是从属关系吗?",slug:"空接口类型和一般类型是从属关系吗"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/22/2024, 3:15:39 PM",lastUpdatedTimestamp:1705936539e3},{title:"切片",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/slice/",relativePath:"基础/slice/README.md",key:"v-45cc1068",path:"/%E5%9F%BA%E7%A1%80/slice/",headers:[{level:2,title:"基本操作",slug:"基本操作"},{level:2,title:"切片和数组的基本概念",slug:"切片和数组的基本概念"},{level:2,title:"切片,数组的底层数据结构",slug:"切片-数组的底层数据结构"},{level:2,title:"append 追加数据的操作",slug:"append-追加数据的操作"},{level:3,title:"对 append 的优化",slug:"对-append-的优化"},{level:2,title:"切片的 copy",slug:"切片的-copy"},{level:2,title:"切片未被合理 gc",slug:"切片未被合理-gc"},{level:2,title:"切片中的 range 注意事项",slug:"切片中的-range-注意事项"},{level:2,title:"切片转化为数组",slug:"切片转化为数组"},{level:2,title:"issues",slug:"issues"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"字符串",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/string/",relativePath:"基础/string/README.md",key:"v-55499b6c",path:"/%E5%9F%BA%E7%A1%80/string/",headers:[{level:2,title:"字符串的基础操作",slug:"字符串的基础操作"},{level:2,title:"字符串的基础知识",slug:"字符串的基础知识"},{level:2,title:"字符串的高效构造",slug:"字符串的高效构造"},{level:2,title:"字符串的底层",slug:"字符串的底层"},{level:3,title:"数据结构",slug:"数据结构"},{level:3,title:"类型转换",slug:"类型转换"},{level:2,title:"for-range 字符串",slug:"for-range-字符串"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"map",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/map/",relativePath:"基础/map/README.md",key:"v-2c2b04e8",path:"/%E5%9F%BA%E7%A1%80/map/",headers:[{level:2,title:"map 的基本操作",slug:"map-的基本操作"},{level:2,title:"map 基础知识",slug:"map-基础知识"},{level:2,title:"map 底层知识",slug:"map-底层知识"},{level:2,title:"issues",slug:"issues"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/",relativePath:"基础/作用域/README.md",key:"v-64b7cefe",path:"/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/",headers:[{level:2,title:"代码块的类型",slug:"代码块的类型"},{level:2,title:"if",slug:"if"},{level:2,title:"for",slug:"for"},{level:2,title:"switch && select",slug:"switch-select"}],lastUpdated:"1/22/2024, 9:15:19 AM",lastUpdatedTimestamp:1705914919e3},{title:"其他内容",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/",relativePath:"基础/其他内容/README.md",key:"v-3fd2593f",path:"/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/",headers:[{level:2,title:"指针",slug:"指针"},{level:2,title:"go 的引用类型和非引用类型",slug:"go-的引用类型和非引用类型"},{level:2,title:"全局变量和局部变量",slug:"全局变量和局部变量"},{level:2,title:"go init 函数的执行顺序",slug:"go-init-函数的执行顺序"},{level:2,title:"go 可比较类型",slug:"go-可比较类型"},{level:2,title:"go 可寻址类型",slug:"go-可寻址类型"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/0.html",relativePath:"基础/函数方法/0.md",key:"v-0047918d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/0.html",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.html",relativePath:"基础/函数方法/1.md",key:"v-44843426",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.html",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/2.html",relativePath:"基础/函数方法/2.md",key:"v-89978b66",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/2.html",lastUpdated:"4/5/2023, 3:48:20 PM",lastUpdatedTimestamp:16807097e5},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html",relativePath:"基础/函数方法/3.md",key:"v-ceaae2a6",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html",headers:[{level:2,title:"具体案例",slug:"具体案例"},{level:2,title:"多修饰器的 pipeline (串型调用)",slug:"多修饰器的-pipeline-串型调用"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/4.html",relativePath:"基础/函数方法/4.md",key:"v-7620e30d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/4.html",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/5.html",relativePath:"基础/函数方法/5.md",key:"v-5397376d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/5.html",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/6.html",relativePath:"基础/函数方法/6.md",key:"v-310d8bcd",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/6.html",lastUpdated:"4/10/2023, 4:16:27 PM",lastUpdatedTimestamp:1681143387e3},{title:"综合题",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html",relativePath:"基础/函数方法/7.md",key:"v-0e83e02d",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html",headers:[{level:2,title:"k8s visitor + 修饰器 + pipeline",slug:"k8s-visitor-修饰器-pipeline"},{level:2,title:"修饰器 + k8s visitor + pipeline",slug:"修饰器-k8s-visitor-pipeline"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"变量声明",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/",relativePath:"基础/变量声明/README.md",key:"v-14ebc3a2",path:"/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/",headers:[{level:2,title:"变量声明符号 var 和 :=",slug:"变量声明符号-var-和"},{level:2,title:"常见的变量声明方式",slug:"常见的变量声明方式"},{level:2,title:"go 语言可导出变量",slug:"go-语言可导出变量"},{level:2,title:"包级变量",slug:"包级变量"},{level:2,title:"函数级变量",slug:"函数级变量"},{level:2,title:"小心 shadow 的变量",slug:"小心-shadow-的变量"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"函数和方法",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/",relativePath:"基础/函数方法/README.md",key:"v-7467f5c8",path:"/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/",headers:[{level:2,title:"函数的初始化顺序",slug:"函数的初始化顺序"},{level:2,title:"init 函数",slug:"init-函数"},{level:2,title:"defer 函数",slug:"defer-函数"},{level:3,title:"defer 函数因为无法 return 造成的内存泄露 bug",slug:"defer-函数因为无法-return-造成的内存泄露-bug"},{level:3,title:"再次强调:有无返回值具体变量对于 defer 的影响",slug:"再次强调-有无返回值具体变量对于-defer-的影响"},{level:2,title:"变长参数",slug:"变长参数"},{level:3,title:"使用变长函数去模拟重载函数",slug:"使用变长函数去模拟重载函数"},{level:3,title:"使用变长函数去实现默认参数",slug:"使用变长函数去实现默认参数"},{level:2,title:"类型嵌入来完成继承",slug:"类型嵌入来完成继承"},{level:2,title:"define 类型的方法集合",slug:"define-类型的方法集合"},{level:2,title:"类型别名的方法集合",slug:"类型别名的方法集合"},{level:2,title:"函数式编程",slug:"函数式编程"},{level:3,title:"函数式编程的实际应用",slug:"函数式编程的实际应用"},{level:3,title:"这里还有关于函数式编程其它相关内容:",slug:"这里还有关于函数式编程其它相关内容"},{level:2,title:"issues",slug:"issues"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/16/2024, 9:10:50 AM",lastUpdatedTimestamp:170539625e4},{title:"复合字面量作为构造器",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/",relativePath:"基础/复合字面量/README.md",key:"v-3a83efec",path:"/%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 语言常量",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/",relativePath:"基础/常量声明/README.md",key:"v-782b6871",path:"/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/",headers:[{level:2,title:"局部常量",slug:"局部常量"},{level:2,title:"常量不可包含计算",slug:"常量不可包含计算"},{level:2,title:"枚举常量 iota",slug:"枚举常量-iota"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"求值顺序",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/",relativePath:"基础/求值顺序/README.md",key:"v-1770fb24",path:"/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/",headers:[{level:2,title:"包级变量声明语句中的表达式求值顺序",slug:"包级变量声明语句中的表达式求值顺序"},{level:2,title:"普通求值顺序",slug:"普通求值顺序"},{level:2,title:"赋值语句中的求值顺序",slug:"赋值语句中的求值顺序"},{level:2,title:"switch select 中的表达式的求值顺序",slug:"switch-select-中的表达式的求值顺序"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 数字类型",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/",relativePath:"基础/数字类型/README.md",key:"v-227dcdbc",path:"/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/",headers:[{level:2,title:"int",slug:"int"},{level:2,title:"float",slug:"float"},{level:3,title:"基础浮点数,math/big 包,decimal 三方包的对比",slug:"基础浮点数-math-big-包-decimal-三方包的对比"},{level:2,title:"complex 复数",slug:"complex-复数"},{level:2,title:"issues",slug:"issues"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"泛型",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/",relativePath:"基础/泛型/README.md",key:"v-57547db7",path:"/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/",headers:[{level:2,title:"约束",slug:"约束"},{level:3,title:"泛型是类型,约束是类型的约束",slug:"泛型是类型-约束是类型的约束"},{level:3,title:"约束的嵌套",slug:"约束的嵌套"},{level:2,title:"泛型",slug:"泛型-2"},{level:2,title:"使用方法",slug:"使用方法"},{level:2,title:"实现原理",slug:"实现原理"},{level:2,title:"跟其它语言的泛型进行对比",slug:"跟其它语言的泛型进行对比"},{level:3,title:"为什么 Java 编译器不在编译期就完成泛型的装箱操作呢?",slug:"为什么-java-编译器不在编译期就完成泛型的装箱操作呢"},{level:2,title:"用例子学泛型",slug:"用例子学泛型"},{level:3,title:"函数泛型 map-filter-reduce",slug:"函数泛型-map-filter-reduce"},{level:3,title:"例子二:方法上的泛型 sets",slug:"例子二-方法上的泛型-sets"},{level:3,title:"例子三:外部定义的约束 实现一个sort接口类型",slug:"例子三-外部定义的约束-实现一个sort接口类型"},{level:2,title:"issues",slug:"issues"},{level:3,title:"关于泛型中的零值",slug:"关于泛型中的零值"},{level:3,title:"无法识别使用了底层数据的其它类型",slug:"无法识别使用了底层数据的其它类型"},{level:3,title:"即便约束一致,类型也是不同的",slug:"即便约束一致-类型也是不同的"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/30/2024, 12:34:12 PM",lastUpdatedTimestamp:1706618052e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/",relativePath:"基础/逻辑和判断语句/README.md",key:"v-6c8c3522",path:"/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/",headers:[{level:2,title:"if",slug:"if"},{level:2,title:"for",slug:"for"},{level:3,title:"string",slug:"string"},{level:3,title:"map",slug:"map"},{level:3,title:"channel",slug:"channel"},{level:2,title:"switch && select",slug:"switch-select"},{level:2,title:"汇总一下 for 和 for range 中最容易迷惑的几段代码",slug:"汇总一下-for-和-for-range-中最容易迷惑的几段代码"}],lastUpdated:"1/22/2024, 9:20:13 AM",lastUpdatedTimestamp:1705915213e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/",relativePath:"基础/结构体/README.md",key:"v-2c445ed2",path:"/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/",headers:[{level:2,title:"简单介绍 struct",slug:"简单介绍-struct"},{level:2,title:"解耦结构体声明和调用",slug:"解耦结构体声明和调用"},{level:2,title:"匿名 struct",slug:"匿名-struct"},{level:2,title:"空结构体",slug:"空结构体"},{level:2,title:"直接嵌套还是作为字段",slug:"直接嵌套还是作为字段"}],lastUpdated:"1/13/2024, 2:04:03 PM",lastUpdatedTimestamp:1705154643e3},{frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/",relativePath:"基础/错误处理/README.md",key:"v-53a0a5fa",path:"/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/",headers:[{level:2,title:"错误处理的基本认识",slug:"错误处理的基本认识"},{level:2,title:"Error 的本质是什么?",slug:"error-的本质是什么"},{level:3,title:"自定义 error",slug:"自定义-error"},{level:3,title:"errors.Is()",slug:"errors-is"},{level:3,title:"errors.As()",slug:"errors-as"},{level:3,title:"errors.Join()",slug:"errors-join"},{level:2,title:"当错误处理遇到了 defer",slug:"当错误处理遇到了-defer"},{level:2,title:"错误处理实战的五种方式",slug:"错误处理实战的五种方式"},{level:3,title:"经典的错误处理方式",slug:"经典的错误处理方式"},{level:3,title:"屏蔽过程中的错误处理",slug:"屏蔽过程中的错误处理"},{level:3,title:"分层架构中的错误处理方法",slug:"分层架构中的错误处理方法"},{level:3,title:"pkg/errors",slug:"pkg-errors"},{level:3,title:"errgroup 的使用技巧",slug:"errgroup-的使用技巧"},{level:2,title:"错误处理相关技巧",slug:"错误处理相关技巧"},{level:3,title:"使用 errors.New() 时要写清楚包名",slug:"使用-errors-new-时要写清楚包名"},{level:3,title:"使用 error 处理一般错误,使用 panic 处理严重错误 (异常)",slug:"使用-error-处理一般错误-使用-panic-处理严重错误-异常"},{level:3,title:"基础库,应该避免使用 error types",slug:"基础库-应该避免使用-error-types"},{level:3,title:"优化不必要的代码让程序变得更简洁",slug:"优化不必要的代码让程序变得更简洁"},{level:3,title:"错误应该只处理一次",slug:"错误应该只处理一次"},{level:2,title:"业务 code 码的设置",slug:"业务-code-码的设置"},{level:3,title:"一律返回 http status 200,具体 code 码单独设置",slug:"一律返回-http-status-200-具体-code-码单独设置"},{level:3,title:"使用合适的 http status code + 简单的信息以及业务错误代码",slug:"使用合适的-http-status-code-简单的信息以及业务错误代码"},{level:3,title:"使用合适的 http status code + 非常详细的业务错误代码以及信息",slug:"使用合适的-http-status-code-非常详细的业务错误代码以及信息"},{level:3,title:"业务 code 码的具体设计",slug:"业务-code-码的具体设计"},{level:3,title:"如何设置 http status code",slug:"如何设置-http-status-code"},{level:2,title:"设计一个生产级的错误包",slug:"设计一个生产级的错误包"},{level:3,title:"生产级的错误包需要的功能",slug:"生产级的错误包需要的功能"},{level:3,title:"具体实现",slug:"具体实现"},{level:2,title:"issues",slug:"issues"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/5/2024, 2:50:37 PM",lastUpdatedTimestamp:1704466237e3},{title:"工程",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/",relativePath:"工程/README.md",key:"v-4621012e",path:"/%E5%B7%A5%E7%A8%8B/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 语言零值",frontmatter:{},regularPath:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/",relativePath:"基础/零值/README.md",key:"v-5fecab4c",path:"/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/",headers:[{level:2,title:"零值可用",slug:"零值可用"},{level:2,title:"零值不可用",slug:"零值不可用"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"cgo",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/cgo/",relativePath:"工程/cgo/README.md",key:"v-3612bc2e",path:"/%E5%B7%A5%E7%A8%8B/cgo/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"6/10/2022, 12:03:01 PM",lastUpdatedTimestamp:1654862581e3},{title:"Github Copilot",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/copilot/",relativePath:"工程/copilot/README.md",key:"v-e23dcfe4",path:"/%E5%B7%A5%E7%A8%8B/copilot/",lastUpdated:"6/29/2022, 3:31:28 AM",lastUpdatedTimestamp:1656473488e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/",relativePath:"工程/goweb编程/README.md",key:"v-07f489a8",path:"/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 标准库的简单介绍",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/",relativePath:"工程/go标准库/README.md",key:"v-4dc71560",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/",headers:[{level:2,title:"archive",slug:"archive"},{level:3,title:"archive/tar",slug:"archive-tar"},{level:3,title:"archive/zip",slug:"archive-zip"},{level:2,title:"bufio",slug:"bufio"},{level:2,title:"builtin",slug:"builtin"},{level:2,title:"bytes",slug:"bytes"},{level:2,title:"cmp",slug:"cmp"},{level:2,title:"compress",slug:"compress"},{level:3,title:"compress/bzip2",slug:"compress-bzip2"},{level:3,title:"compress/flate",slug:"compress-flate"},{level:3,title:"compress/gzip",slug:"compress-gzip"},{level:3,title:"compress/lzw",slug:"compress-lzw"},{level:3,title:"compress/zlib",slug:"compress-zlib"},{level:2,title:"container",slug:"container"},{level:3,title:"container/heap",slug:"container-heap"},{level:3,title:"container/list",slug:"container-list"},{level:3,title:"container/ring",slug:"container-ring"},{level:2,title:"context",slug:"context"},{level:2,title:"crypto",slug:"crypto"},{level:3,title:"crypto/aes",slug:"crypto-aes"},{level:3,title:"crypto/cipher",slug:"crypto-cipher"},{level:3,title:"crypto/des",slug:"crypto-des"},{level:3,title:"crypto/dsa",slug:"crypto-dsa"},{level:3,title:"crypto/ecdh",slug:"crypto-ecdh"},{level:3,title:"crypto/ecdsa",slug:"crypto-ecdsa"},{level:3,title:"crypto/ed25519",slug:"crypto-ed25519"},{level:3,title:"crypto/elliptic",slug:"crypto-elliptic"},{level:3,title:"crypto/hmac",slug:"crypto-hmac"},{level:3,title:"crypto/md5",slug:"crypto-md5"},{level:3,title:"crypto/rand",slug:"crypto-rand"},{level:3,title:"crypto/rc4",slug:"crypto-rc4"},{level:3,title:"crypto/rsa",slug:"crypto-rsa"},{level:3,title:"crypto/sha1",slug:"crypto-sha1"},{level:3,title:"crypto/sha256",slug:"crypto-sha256"},{level:3,title:"crypto/sha512",slug:"crypto-sha512"},{level:3,title:"crypto/subtle",slug:"crypto-subtle"},{level:3,title:"crypto/tls",slug:"crypto-tls"},{level:3,title:"crypto/x509",slug:"crypto-x509"},{level:2,title:"database",slug:"database"},{level:3,title:"database/sql",slug:"database-sql"},{level:3,title:"database/sql/driver",slug:"database-sql-driver"},{level:2,title:"debug",slug:"debug"},{level:3,title:"debug/buildinfo",slug:"debug-buildinfo"},{level:3,title:"debug/dwarf",slug:"debug-dwarf"},{level:3,title:"debug/elf",slug:"debug-elf"},{level:3,title:"debug/gosym",slug:"debug-gosym"},{level:3,title:"debug/macho",slug:"debug-macho"},{level:3,title:"debug/pe",slug:"debug-pe"},{level:3,title:"debug/plan9obj",slug:"debug-plan9obj"},{level:2,title:"embed",slug:"embed"},{level:2,title:"encoding",slug:"encoding"},{level:3,title:"encoding/ascii85",slug:"encoding-ascii85"},{level:3,title:"encoding/asn1",slug:"encoding-asn1"},{level:3,title:"encoding/base32",slug:"encoding-base32"},{level:3,title:"encoding/base64",slug:"encoding-base64"},{level:3,title:"encoding/binary",slug:"encoding-binary"},{level:3,title:"encoding/csv",slug:"encoding-csv"},{level:3,title:"encoding/gob",slug:"encoding-gob"},{level:3,title:"encoding/hex",slug:"encoding-hex"},{level:3,title:"encoding/json",slug:"encoding-json"},{level:3,title:"encoding/pem",slug:"encoding-pem"},{level:3,title:"encoding/xml",slug:"encoding-xml"},{level:2,title:"errors",slug:"errors"},{level:2,title:"expvar",slug:"expvar"},{level:2,title:"flag",slug:"flag"},{level:2,title:"fmt",slug:"fmt"},{level:2,title:"go",slug:"go"},{level:3,title:"go/ast",slug:"go-ast"},{level:3,title:"go/build",slug:"go-build"},{level:3,title:"go/constant",slug:"go-constant"},{level:3,title:"go/doc",slug:"go-doc"},{level:3,title:"go/format",slug:"go-format"},{level:3,title:"go/importer",slug:"go-importer"},{level:3,title:"go/parser",slug:"go-parser"},{level:3,title:"go/printer",slug:"go-printer"},{level:3,title:"go/scanner",slug:"go-scanner"},{level:3,title:"go/token",slug:"go-token"},{level:3,title:"go/types",slug:"go-types"},{level:2,title:"hash",slug:"hash"},{level:3,title:"hash/adler32",slug:"hash-adler32"},{level:3,title:"hash/crc32",slug:"hash-crc32"},{level:3,title:"hash/crc64",slug:"hash-crc64"},{level:3,title:"hash/fnv",slug:"hash-fnv"},{level:3,title:"hash/maphash",slug:"hash-maphash"},{level:2,title:"html",slug:"html"},{level:3,title:"html/template",slug:"html-template"},{level:2,title:"image",slug:"image"},{level:3,title:"image/color",slug:"image-color"},{level:3,title:"image/draw",slug:"image-draw"},{level:3,title:"image/gif",slug:"image-gif"},{level:3,title:"image/jpeg",slug:"image-jpeg"},{level:3,title:"png",slug:"png"},{level:2,title:"index",slug:"index"},{level:3,title:"index/suffixarray",slug:"index-suffixarray"},{level:2,title:"io",slug:"io"},{level:3,title:"io/fs",slug:"io-fs"},{level:3,title:"io/ioutil",slug:"io-ioutil"},{level:2,title:"log",slug:"log"},{level:3,title:"log/slog",slug:"log-slog"},{level:3,title:"log/syslog",slug:"log-syslog"},{level:2,title:"maps",slug:"maps"},{level:2,title:"math",slug:"math"},{level:3,title:"math/big",slug:"math-big"},{level:3,title:"math/bits",slug:"math-bits"},{level:3,title:"math/cmplx",slug:"math-cmplx"},{level:3,title:"math/rand",slug:"math-rand"},{level:2,title:"mime",slug:"mime"},{level:3,title:"mime/multipart",slug:"mime-multipart"},{level:3,title:"mime/quotedprintable",slug:"mime-quotedprintable"},{level:2,title:"net",slug:"net"},{level:3,title:"net/http",slug:"net-http"},{level:3,title:"net/mail",slug:"net-mail"},{level:3,title:"net/netip",slug:"net-netip"},{level:3,title:"net/rpc",slug:"net-rpc"},{level:3,title:"net/smtp",slug:"net-smtp"},{level:3,title:"net/textproto",slug:"net-textproto"},{level:3,title:"net/url",slug:"net-url"},{level:2,title:"os",slug:"os"},{level:3,title:"os/exec",slug:"os-exec"},{level:3,title:"os/signal",slug:"os-signal"},{level:3,title:"os/user",slug:"os-user"},{level:2,title:"path",slug:"path"},{level:3,title:"path/filepath",slug:"path-filepath"},{level:2,title:"plugin",slug:"plugin"},{level:2,title:"reflect",slug:"reflect"},{level:2,title:"regexp",slug:"regexp"},{level:3,title:"regexp/syntax",slug:"regexp-syntax"},{level:2,title:"runtime",slug:"runtime"},{level:3,title:"runtime/cgo",slug:"runtime-cgo"},{level:3,title:"runtime/coverage",slug:"runtime-coverage"},{level:3,title:"runtime/debug",slug:"runtime-debug"},{level:3,title:"runtime/metrics",slug:"runtime-metrics"},{level:3,title:"runtime/pprof",slug:"runtime-pprof"},{level:3,title:"runtime/race",slug:"runtime-race"},{level:3,title:"runtime/trace",slug:"runtime-trace"},{level:2,title:"slices",slug:"slices"},{level:2,title:"sort",slug:"sort"},{level:2,title:"strconv",slug:"strconv"},{level:2,title:"strings",slug:"strings"},{level:2,title:"sync",slug:"sync"},{level:3,title:"sync/atomic",slug:"sync-atomic"},{level:2,title:"syscall",slug:"syscall"},{level:3,title:"sync/js",slug:"sync-js"},{level:2,title:"testing",slug:"testing"},{level:3,title:"testing/fstest",slug:"testing-fstest"},{level:3,title:"testing/iotest",slug:"testing-iotest"},{level:3,title:"testing/quick",slug:"testing-quick"},{level:3,title:"testing/slogtest",slug:"testing-slogtest"},{level:2,title:"text",slug:"text"},{level:3,title:"text/scanner",slug:"text-scanner"},{level:3,title:"text/tabwriter",slug:"text-tabwriter"},{level:3,title:"text/template",slug:"text-template"},{level:2,title:"time",slug:"time"},{level:3,title:"time/tzdata",slug:"time-tzdata"},{level:2,title:"unicode",slug:"unicode"},{level:3,title:"unicode/utf16",slug:"unicode-utf16"},{level:3,title:"unicode/utf8",slug:"unicode-utf8"},{level:2,title:"unsafe",slug:"unsafe"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 命名惯例",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/",relativePath:"工程/go命名惯例/README.md",key:"v-2a7e6e88",path:"/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/",headers:[{level:2,title:"包",slug:"包"},{level:2,title:"变量,类型,函数,方法",slug:"变量-类型-函数-方法"},{level:2,title:"常量",slug:"常量"},{level:2,title:"接口",slug:"接口"},{level:2,title:"两种命名的对比",slug:"两种命名的对比"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"fmt",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/fmt.html",relativePath:"工程/go标准库/fmt.md",key:"v-24ece539",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/fmt.html",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"encoding/hex",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/encoding-hex.html",relativePath:"工程/go标准库/encoding-hex.md",key:"v-314138aa",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/encoding-hex.html",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"sync",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html",relativePath:"工程/go标准库/sync.md",key:"v-475bcf6b",path:"/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html",headers:[{level:2,title:"sync.Map",slug:"sync-map"},{level:3,title:"sync.Map 的底层数据",slug:"sync-map-的底层数据"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/",relativePath:"工程/go编程范式/README.md",key:"v-254cabb0",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/",headers:[{level:2,title:"创建模式",slug:"创建模式"},{level:2,title:"结构模式",slug:"结构模式"},{level:2,title:"行为模式",slug:"行为模式"},{level:2,title:"同步模式",slug:"同步模式"},{level:2,title:"并发模式",slug:"并发模式"},{level:2,title:"消息传递模式",slug:"消息传递模式"},{level:2,title:"稳定性模式",slug:"稳定性模式"},{level:2,title:"分析模式",slug:"分析模式"},{level:2,title:"函数式编程模式",slug:"函数式编程模式"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/26/2023, 3:56:49 PM",lastUpdatedTimestamp:1701014209e3},{title:"k8s visitor",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/",relativePath:"工程/go编程范式/k8s_visitor/README.md",key:"v-365e0f1c",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/k8s_visitor/",lastUpdated:"10/9/2023, 6:17:22 AM",lastUpdatedTimestamp:1696832242e3},{title:"pipeline",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/",relativePath:"工程/go编程范式/pipeline/README.md",key:"v-0b10c5fe",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/pipeline/",lastUpdated:"10/9/2023, 6:17:22 AM",lastUpdatedTimestamp:1696832242e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/",relativePath:"工程/go编程范式/代理/README.md",key:"v-2cc5e709",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BB%A3%E7%90%86/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/",relativePath:"工程/go编程范式/信号量/README.md",key:"v-9f23503e",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E4%BF%A1%E5%8F%B7%E9%87%8F/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/",relativePath:"工程/go编程范式/功能选项/README.md",key:"v-e883b430",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8A%9F%E8%83%BD%E9%80%89%E9%A1%B9/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{title:"创建者模式",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/",relativePath:"工程/go编程范式/创建者/README.md",key:"v-22d79379",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%88%9B%E5%BB%BA%E8%80%85/",lastUpdated:"8/9/2023, 11:27:50 AM",lastUpdatedTimestamp:169158047e4},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/",relativePath:"工程/go编程范式/单例/README.md",key:"v-21f3b69e",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8D%95%E4%BE%8B/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/",relativePath:"工程/go编程范式/原型/README.md",key:"v-ad636568",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8E%9F%E5%9E%8B/",lastUpdated:"8/9/2023, 11:27:50 AM",lastUpdatedTimestamp:169158047e4},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/",relativePath:"工程/go编程范式/定时函数/README.md",key:"v-d72197ac",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AE%9A%E6%97%B6%E5%87%BD%E6%95%B0/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/",relativePath:"工程/go编程范式/发布者订阅者/README.md",key:"v-5171cdf8",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%8F%91%E5%B8%83%E8%80%85%E8%AE%A2%E9%98%85%E8%80%85/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/",relativePath:"工程/go编程范式/对象池/README.md",key:"v-6957f54a",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%AF%B9%E8%B1%A1%E6%B1%A0/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/",relativePath:"工程/go编程范式/工厂方法/README.md",key:"v-231e64b8",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B7%A5%E5%8E%82%E6%96%B9%E6%B3%95/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/",relativePath:"工程/go编程范式/扇入/README.md",key:"v-87aaba38",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%85%A5/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/",relativePath:"工程/go编程范式/并行/README.md",key:"v-58420d13",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E5%B9%B6%E8%A1%8C/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/",relativePath:"工程/go编程范式/断路器/README.md",key:"v-7ebcd2e0",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%96%AD%E8%B7%AF%E5%99%A8/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/",relativePath:"工程/go编程范式/扇出/README.md",key:"v-5dcc80b0",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%89%87%E5%87%BA/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/",relativePath:"工程/go编程范式/有界并行/README.md",key:"v-56f3a69d",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E6%9C%89%E7%95%8C%E5%B9%B6%E8%A1%8C/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/",relativePath:"工程/go编程范式/生成器/README.md",key:"v-6dd192e7",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%94%9F%E6%88%90%E5%99%A8/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/",relativePath:"工程/go编程范式/策略/README.md",key:"v-128e0dcf",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E7%AD%96%E7%95%A5/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/",relativePath:"工程/go编程范式/装饰器/README.md",key:"v-123af4a6",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A3%85%E9%A5%B0%E5%99%A8/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/",relativePath:"工程/go编程范式/观察者/README.md",key:"v-3938ca42",path:"/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/%E8%A7%82%E5%AF%9F%E8%80%85/",lastUpdated:"8/7/2023, 3:58:56 PM",lastUpdatedTimestamp:1691423936e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/",relativePath:"工程/go语言规范/README.md",key:"v-93d96b0a",path:"/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"12/6/2023, 8:24:47 AM",lastUpdatedTimestamp:1701851087e3},{title:"go 面试题",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/",relativePath:"工程/go面试题/README.md",key:"v-c47b14c8",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/",headers:[{level:2,title:"按照公司排序",slug:"按照公司排序"},{level:2,title:"最终总结出的面试题",slug:"最终总结出的面试题"}],lastUpdated:"10/29/2023, 2:17:57 PM",lastUpdatedTimestamp:1698589077e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/architect.html",relativePath:"工程/go面试题/architect.md",key:"v-48e51b63",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/architect.html",lastUpdated:"10/29/2023, 2:17:57 PM",lastUpdatedTimestamp:1698589077e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/intermediate.html",relativePath:"工程/go面试题/intermediate.md",key:"v-628f98af",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/intermediate.html",lastUpdated:"10/29/2023, 2:17:57 PM",lastUpdatedTimestamp:1698589077e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/primary.html",relativePath:"工程/go面试题/primary.md",key:"v-1b8f6bee",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/primary.html",lastUpdated:"10/29/2023, 2:17:57 PM",lastUpdatedTimestamp:1698589077e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/senior.html",relativePath:"工程/go面试题/senior.md",key:"v-45c4720f",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/senior.html",lastUpdated:"10/29/2023, 2:17:57 PM",lastUpdatedTimestamp:1698589077e3},{title:"IOC",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/ioc/",relativePath:"工程/ioc/README.md",key:"v-7bd54dee",path:"/%E5%B7%A5%E7%A8%8B/ioc/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"6/29/2022, 3:31:28 AM",lastUpdatedTimestamp:1656473488e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/%E4%B8%AD%E9%AB%98%E7%BA%A7go%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%80.html",relativePath:"工程/go面试题/中高级go面试题一.md",key:"v-e4106de2",path:"/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/%E4%B8%AD%E9%AB%98%E7%BA%A7go%E9%9D%A2%E8%AF%95%E9%A2%98%E4%B8%80.html",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"log 包",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/log/",relativePath:"工程/log/README.md",key:"v-5231250e",path:"/%E5%B7%A5%E7%A8%8B/log/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/8/2022, 4:03:36 AM",lastUpdatedTimestamp:1667880216e3},{title:"wasm 在 go 中的实践",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/wasm/",relativePath:"工程/wasm/README.md",key:"v-6c2c5722",path:"/%E5%B7%A5%E7%A8%8B/wasm/",headers:[{level:2,title:"参考文章",slug:"参考文章"}],lastUpdated:"12/6/2023, 8:24:47 AM",lastUpdatedTimestamp:1701851087e3},{title:"代码检查工具",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/",relativePath:"工程/代码检查/README.md",key:"v-0b661dcb",path:"/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/",headers:[{level:2,title:"go vet / go tool vet",slug:"go-vet-go-tool-vet"},{level:2,title:"golangci-lint",slug:"golangci-lint"},{level:2,title:"govulncheck",slug:"govulncheck"},{level:2,title:"x/tools 工具系列",slug:"x-tools-工具系列"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"优秀第三方包",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/",relativePath:"工程/优秀第三方包/README.md",key:"v-23694af3",path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"gin",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/",relativePath:"工程/优秀第三方包/gin/README.md",key:"v-16b78eb9",path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"sonic",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/",relativePath:"工程/优秀第三方包/sonic/README.md",key:"v-310eb5b9",path:"/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/sonic/",lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"动态调试",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/",relativePath:"工程/动态调试/README.md",key:"v-2c36d961",path:"/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/",headers:[{level:2,title:"资料",slug:"资料"}],lastUpdated:"6/29/2022, 3:31:28 AM",lastUpdatedTimestamp:1656473488e3},{frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/",relativePath:"工程/反射/README.md",key:"v-39563743",path:"/%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84/",lastUpdated:"6/9/2023, 1:32:17 PM",lastUpdatedTimestamp:1686317537e3},{title:"命令",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/",relativePath:"工程/命令/README.md",key:"v-e1e5720a",path:"/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/",headers:[{level:2,title:"gofmt",slug:"gofmt"},{level:2,title:"goimports",slug:"goimports"},{level:2,title:"go build",slug:"go-build"},{level:2,title:"go install",slug:"go-install"},{level:2,title:"go get",slug:"go-get"},{level:2,title:"go clean",slug:"go-clean"},{level:2,title:"go doc godoc",slug:"go-doc-godoc"},{level:2,title:"go run",slug:"go-run"},{level:2,title:"go test",slug:"go-test"},{level:2,title:"go list",slug:"go-list"},{level:2,title:"go fix go tool fix",slug:"go-fix-go-tool-fix"},{level:2,title:"go vet / go tool vet",slug:"go-vet-go-tool-vet"},{level:2,title:"go tool pprof",slug:"go-tool-pprof"},{level:2,title:"go tool cgo",slug:"go-tool-cgo"},{level:2,title:"go env",slug:"go-env"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 包管理工具",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/",relativePath:"工程/包及其构建工具/README.md",key:"v-19af4dc6",path:"/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/",headers:[{level:2,title:"go 语言的包导入过程",slug:"go-语言的包导入过程"},{level:2,title:"go 程序的构建过程。",slug:"go-程序的构建过程。"},{level:2,title:"go module 构建工具",slug:"go-module-构建工具"},{level:3,title:"如何控制 go 引入的包的版本号。",slug:"如何控制-go-引入的包的版本号。"},{level:3,title:"如何优雅的升级和降级引入的包版本?",slug:"如何优雅的升级和降级引入的包版本"},{level:3,title:"引入的 go 包 git 更改名称了怎么办?",slug:"引入的-go-包-git-更改名称了怎么办"},{level:3,title:"go 包代理",slug:"go-包代理"},{level:3,title:"如何使用一个私有包",slug:"如何使用一个私有包"},{level:3,title:"本地开发使用的配置文件 go.work",slug:"本地开发使用的配置文件-go-work"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"12/8/2023, 6:39:03 AM",lastUpdatedTimestamp:1702017543e3},{title:"坑",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/",relativePath:"工程/坑/README.md",key:"v-28707b06",path:"/%E5%B7%A5%E7%A8%8B/%E5%9D%91/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 中的测试",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/",relativePath:"工程/测试/README.md",key:"v-5f93f7fe",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/",headers:[{level:2,title:"testing 包",slug:"testing-包"},{level:2,title:"testing/fstest 包",slug:"testing-fstest-包"},{level:2,title:"testing/iotest 包",slug:"testing-iotest-包"},{level:2,title:"testing/quick 包",slug:"testing-quick-包"},{level:2,title:"net/http/test",slug:"net-http-test"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"字符编码",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/",relativePath:"工程/字符编码/README.md",key:"v-762f0d70",path:"/%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81/",lastUpdated:"12/19/2022, 11:14:51 PM",lastUpdatedTimestamp:1671491691e3},{title:"基准测试",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html",relativePath:"工程/测试/基准测试.md",key:"v-79abb1e4",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html",headers:[{level:2,title:"hey",slug:"hey"},{level:2,title:"ethr",slug:"ethr"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"基础测试",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95.html",relativePath:"工程/测试/基础测试.md",key:"v-5da83102",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95.html",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"模糊测试",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E6%A8%A1%E7%B3%8A%E6%B5%8B%E8%AF%95.html",relativePath:"工程/测试/模糊测试.md",key:"v-44ab1fb4",path:"/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E6%A8%A1%E7%B3%8A%E6%B5%8B%E8%AF%95.html",headers:[{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"5/24/2022, 6:13:13 PM",lastUpdatedTimestamp:1653415993e3},{title:"系统信号的处理",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/",relativePath:"工程/系统信号的处理/README.md",key:"v-34fdc569",path:"/%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86/",lastUpdated:"11/29/2022, 1:05:58 PM",lastUpdatedTimestamp:1669727158e3},{title:"go 语言的读写模型",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/",relativePath:"工程/读写模型/README.md",key:"v-30048c0c",path:"/%E5%B7%A5%E7%A8%8B/%E8%AF%BB%E5%86%99%E6%A8%A1%E5%9E%8B/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{title:"go 项目组织形式",frontmatter:{},regularPath:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/",relativePath:"工程/项目组织形式/README.md",key:"v-4e6402b2",path:"/%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F/",lastUpdated:"11/16/2023, 6:44:02 AM",lastUpdatedTimestamp:1700117042e3},{frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/atomic/",relativePath:"并发/atomic/README.md",key:"v-11556580",path:"/%E5%B9%B6%E5%8F%91/atomic/",headers:[{level:2,title:"介绍一下 atomic 的内容",slug:"介绍一下-atomic-的内容"},{level:2,title:"基于原子库的第三方扩展",slug:"基于原子库的第三方扩展"},{level:2,title:"issues",slug:"issues"},{level:3,title:"对一个地址的赋值是原子操作吗?",slug:"对一个地址的赋值是原子操作吗"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/5/2024, 2:48:04 PM",lastUpdatedTimestamp:1704466084e3},{frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/",relativePath:"并发/README.md",key:"v-be112ee8",path:"/%E5%B9%B6%E5%8F%91/",lastUpdated:"1/5/2024, 2:48:04 PM",lastUpdatedTimestamp:1704466084e3},{title:"channel",frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/channel/",relativePath:"并发/channel/README.md",key:"v-4100a20c",path:"/%E5%B9%B6%E5%8F%91/channel/",headers:[{level:2,title:"基础用法",slug:"基础用法"},{level:3,title:"创建 channel",slug:"创建-channel"},{level:3,title:"channel 分为三种类型",slug:"channel-分为三种类型"},{level:3,title:"发送数据",slug:"发送数据"},{level:3,title:"接收数据",slug:"接收数据"},{level:3,title:"关闭 channel",slug:"关闭-channel"},{level:3,title:"判断从 channel 中取出的值是否有效",slug:"判断从-channel-中取出的值是否有效"},{level:3,title:"range channel",slug:"range-channel"},{level:3,title:"其它操作:len cap",slug:"其它操作-len-cap"},{level:3,title:"不同状态 channel 的总结",slug:"不同状态-channel-的总结"},{level:2,title:"select",slug:"select"},{level:3,title:"对于 select for 和 time.Sleep 的阻塞机制的理解",slug:"对于-select-for-和-time-sleep-的阻塞机制的理解"},{level:2,title:"定时器",slug:"定时器"},{level:3,title:"cron 规则定时任务框架 robfig/cron",slug:"cron-规则定时任务框架-robfig-cron"},{level:2,title:"使用反射执行未知数量的 channel",slug:"使用反射执行未知数量的-channel"},{level:2,title:"数据交流---生产者/消费者模式",slug:"数据交流-生产者-消费者模式"},{level:2,title:"传递信号/通知",slug:"传递信号-通知"},{level:3,title:"收发同时进行的信号",slug:"收发同时进行的信号"},{level:3,title:"使用计时器去解决长等待问题",slug:"使用计时器去解决长等待问题"},{level:3,title:"信号传递之 or-do 模式",slug:"信号传递之-or-do-模式"},{level:2,title:"锁",slug:"锁"},{level:2,title:"任务编排",slug:"任务编排"},{level:3,title:"fan-in",slug:"fan-in"},{level:3,title:"fan-out",slug:"fan-out"},{level:3,title:"map-reduce",slug:"map-reduce"},{level:3,title:"pipeline-流水线模式",slug:"pipeline-流水线模式"},{level:3,title:"stream-流模式",slug:"stream-流模式"},{level:3,title:"pipeline 流水线模式和 stream 流模式的对比",slug:"pipeline-流水线模式和-stream-流模式的对比"},{level:2,title:"channel 注意事项",slug:"channel-注意事项"},{level:3,title:"goroutine 泄露",slug:"goroutine-泄露"},{level:2,title:"channel 的实现原理",slug:"channel-的实现原理"},{level:3,title:"创建",slug:"创建"},{level:3,title:"send",slug:"send"},{level:3,title:"recive",slug:"recive"},{level:3,title:"close",slug:"close"},{level:2,title:"issues",slug:"issues"},{level:3,title:"channel 是并发银弹吗?",slug:"channel-是并发银弹吗"},{level:3,title:"有无 buffer 的 channel 区别",slug:"有无-buffer-的-channel-区别"},{level:3,title:"channel close 后,read write close 的区别",slug:"channel-close-后-read-write-close-的区别"},{level:3,title:"channle 底层是什么",slug:"channle-底层是什么"},{level:3,title:"channle 和运行时调度如何交互",slug:"channle-和运行时调度如何交互"},{level:3,title:"编程题,使用三个 goroutine 打印 abc 100 次",slug:"编程题-使用三个-goroutine-打印-abc-100-次"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/29/2024, 2:12:13 PM",lastUpdatedTimestamp:1706537533e3},{frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/context/",relativePath:"并发/context/README.md",key:"v-86d852e8",path:"/%E5%B9%B6%E5%8F%91/context/",headers:[{level:2,title:"使用 context",slug:"使用-context"},{level:2,title:"withValue",slug:"withvalue"},{level:3,title:"WithCancel",slug:"withcancel"},{level:3,title:"withTimeout withDeadline",slug:"withtimeout-withdeadline"},{level:2,title:"带有 cause 的函数",slug:"带有-cause-的函数"},{level:2,title:"在 WithTimeout 中 cancel() 函数的存在意义是什么?",slug:"在-withtimeout-中-cancel-函数的存在意义是什么"},{level:2,title:"issues",slug:"issues"},{level:3,title:"contex.Contex 如何实现并发安全的?",slug:"contex-contex-如何实现并发安全的"}],lastUpdated:"1/13/2024, 2:04:03 PM",lastUpdatedTimestamp:1705154643e3},{title:"内存模型",frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/",relativePath:"并发/内存模型/README.md",key:"v-5bae8fd8",path:"/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/",headers:[{level:2,title:"介绍一些 go 语言中的基本操作",slug:"介绍一些-go-语言中的基本操作"},{level:2,title:"内存模型存存在的意义",slug:"内存模型存存在的意义"},{level:3,title:"具体表现",slug:"具体表现"},{level:3,title:"三条定律",slug:"三条定律"},{level:2,title:"重排和可见性",slug:"重排和可见性"},{level:2,title:"同步操作的 happens-before",slug:"同步操作的-happens-before"},{level:3,title:"单个 goroutine",slug:"单个-goroutine"},{level:3,title:"init 函数",slug:"init-函数"},{level:3,title:"goroutine",slug:"goroutine"},{level:3,title:"channel",slug:"channel"},{level:3,title:"Mutex/RWMutex",slug:"mutex-rwmutex"},{level:3,title:"WaitGroup",slug:"waitgroup"},{level:3,title:"Once",slug:"once"},{level:3,title:"atomic",slug:"atomic"},{level:2,title:"issues",slug:"issues"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/23/2024, 7:58:45 AM",lastUpdatedTimestamp:1705996725e3},{frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/",relativePath:"并发/同步原语/README.md",key:"v-df237aa0",path:"/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/",headers:[{level:2,title:"sync.Mutex",slug:"sync-mutex"},{level:3,title:"临界区",slug:"临界区"},{level:3,title:"sync.Mutex 基础操作",slug:"sync-mutex-基础操作"},{level:3,title:"sync.Locker 接口",slug:"sync-locker-接口"},{level:3,title:"什么是 data race 的本质",slug:"什么是-data-race-的本质"},{level:3,title:"检测 data race 的工具",slug:"检测-data-race-的工具"},{level:3,title:"将互斥锁嵌入到结构体中",slug:"将互斥锁嵌入到结构体中"},{level:3,title:"sync.Mutex 互斥锁的实现原理",slug:"sync-mutex-互斥锁的实现原理"},{level:3,title:"sync.Mutex 易错的几种场景",slug:"sync-mutex-易错的几种场景"},{level:3,title:"sync.Mutex 扩展",slug:"sync-mutex-扩展"},{level:2,title:"sync.RWMutex",slug:"sync-rwmutex"},{level:2,title:"sync.WaitGroup",slug:"sync-waitgroup"},{level:3,title:"常见错误",slug:"常见错误"},{level:2,title:"SingleFlight",slug:"singleflight"},{level:2,title:"cyclicBarrier",slug:"cyclicbarrier"},{level:2,title:"errgroup",slug:"errgroup"},{level:2,title:"sync.Once",slug:"sync-once"},{level:2,title:"讨论线程安全的 map 在多线程中的使用",slug:"讨论线程安全的-map-在多线程中的使用"},{level:3,title:"直接加锁",slug:"直接加锁"},{level:3,title:"细颗粒度并发安全 Map",slug:"细颗粒度并发安全-map"},{level:3,title:"sync.Map",slug:"sync-map"},{level:2,title:"sync.Pool",slug:"sync-pool"},{level:3,title:"pool 内存浪费",slug:"pool-内存浪费"},{level:3,title:"worker pool",slug:"worker-pool"},{level:2,title:"semaphore",slug:"semaphore"},{level:3,title:"使用信号量时的注意事项",slug:"使用信号量时的注意事项"},{level:3,title:"使用 channel 去实现一个信号量",slug:"使用-channel-去实现一个信号量"},{level:2,title:"issues",slug:"issues"},{level:3,title:"问题一:有互斥锁就一定有临界区吗?",slug:"问题一-有互斥锁就一定有临界区吗"},{level:3,title:"问题二:如果 Mutex 已经被一个 goroutine 获取了锁,其它等待中的 goroutine 们只能一直等待。那么,等这个锁释放后,等待中的 goroutine 中哪一个会优先获取 Mutex 呢?",slug:"问题二-如果-mutex-已经被一个-goroutine-获取了锁-其它等待中的-goroutine-们只能一直等待。那么-等这个锁释放后-等待中的-goroutine-中哪一个会优先获取-mutex-呢"},{level:3,title:"问题三:Mutext 的底层中,使用 state 和 sema 来表示锁的状态,sema 是信号量,为什么在有信号量表示锁的状态之后还需要一个 state 表示锁是否上锁呢?",slug:"问题三-mutext-的底层中-使用-state-和-sema-来表示锁的状态-sema-是信号量-为什么在有信号量表示锁的状态之后还需要一个-state-表示锁是否上锁呢"},{level:3,title:"问题四:使用循环栅栏,信号量去完成经典并发题:水的制造工厂",slug:"问题四-使用循环栅栏-信号量去完成经典并发题-水的制造工厂"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"1/16/2024, 9:10:50 AM",lastUpdatedTimestamp:170539625e4},{frontmatter:{},regularPath:"/%E7%BC%96%E8%AF%91%E5%99%A8/",relativePath:"编译器/README.md",key:"v-6c1b55eb",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/",headers:[{level:2,title:"编译器概述",slug:"编译器概述"},{level:2,title:"编译器特性",slug:"编译器特性"},{level:2,title:"编译器实战",slug:"编译器实战"},{level:2,title:"编译器源码",slug:"编译器源码"},{level:2,title:"其他编译器",slug:"其他编译器"}],lastUpdated:"11/17/2023, 4:42:45 AM",lastUpdatedTimestamp:1700196165e3},{frontmatter:{},regularPath:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/",relativePath:"编译器/gc/README.md",key:"v-133fd176",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/gc/",headers:[{level:2,title:"前端组件",slug:"前端组件"},{level:2,title:"中端组件",slug:"中端组件"},{level:2,title:"后端组件",slug:"后端组件"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"12/6/2023, 8:24:47 AM",lastUpdatedTimestamp:1701851087e3},{frontmatter:{},regularPath:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/",relativePath:"并发/并发模型/README.md",key:"v-39370fa0",path:"/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/",headers:[{level:2,title:"并发和并行的关系",slug:"并发和并行的关系"},{level:2,title:"多线程并发模型",slug:"多线程并发模型"},{level:2,title:"csp",slug:"csp"},{level:2,title:"了解 goroutine",slug:"了解-goroutine"},{level:3,title:"创建 goroutine",slug:"创建-goroutine"},{level:3,title:"goroutine 退出",slug:"goroutine-退出"},{level:2,title:"参考资料",slug:"参考资料"}],lastUpdated:"11/27/2023, 8:26:59 AM",lastUpdatedTimestamp:1701073619e3},{title:"gccgo",frontmatter:{},regularPath:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/",relativePath:"编译器/gccgo/README.md",key:"v-4e9f312a",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/gccgo/",lastUpdated:"11/17/2023, 4:42:45 AM",lastUpdatedTimestamp:1700196165e3},{frontmatter:{},regularPath:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/",relativePath:"编译器/llvm/README.md",key:"v-946548b6",path:"/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/",headers:[{level:2,title:"gollvm",slug:"gollvm"},{level:2,title:"可以通过修改 Go Compiler 工具链,在编译过程中调用 LLVM Pass 执行优化。",slug:"可以通过修改-go-compiler-工具链-在编译过程中调用-llvm-pass-执行优化。"},{level:2,title:"llvm -golang",slug:"llvm-golang"}],lastUpdated:"11/17/2023, 4:42:45 AM",lastUpdatedTimestamp:1700196165e3}],themeConfig:{logo:"https://avatars.githubusercontent.com/u/42873232",lastUpdated:"最后更新",smoothScroll:!0,editLinks:!0,repo:"https://github.com/shgopher/GOFamily",docsBranch:"release",editLinkText:"在GitHub中编辑",nav:[{text:"首页",link:"/"},{text:"系列教程",ariaLabel:"Menu",items:[{text:"GOFamily 【go语言教程】",link:"https://shgopher.github.io/GOFamily/"},{text:"408 【基础408知识教程】",link:"https://shgopher.github.io/408/"},{text:"luban 【系统设计教程】",link:"https://shgopher.github.io/luban/"},{text:"dingdang 【工具教程】",link:"https://shgopher.github.io/dingdang/"},{text:"god 【给程序员写的书】",link:"https://shgopher.github.io/god/"}]},{text:"作者",link:"https://shgopher.github.io/"}],sidebar:"auto"}};n(365);Lo.component("Badge",(function(){return Promise.all([n.e(0),n.e(3)]).then(n.bind(null,545))})),Lo.component("CodeBlock",(function(){return Promise.all([n.e(0),n.e(4)]).then(n.bind(null,437))})),Lo.component("CodeGroup",(function(){return Promise.all([n.e(0),n.e(5)]).then(n.bind(null,438))}));n(366);n(367),n(368);var bl={name:"BackToTop",props:{threshold:{type:Number,default:300}},data:function(){return{scrollTop:null}},computed:{show:function(){return this.scrollTop>this.threshold}},mounted:function(){var t=this;this.scrollTop=this.getScrollTop(),window.addEventListener("scroll",cl()((function(){t.scrollTop=t.getScrollTop()}),100))},methods:{getScrollTop:function(){return window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0},scrollToTop:function(){window.scrollTo({top:0,behavior:"smooth"}),this.scrollTop=0}}},Cl=(n(370),Object(Bl.a)(bl,(function(){var t=this.$createElement,e=this._self._c||t;return e("transition",{attrs:{name:"fade"}},[this.show?e("svg",{staticClass:"go-to-top",attrs:{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 49.484 28.284"},on:{click:this.scrollToTop}},[e("g",{attrs:{transform:"translate(-229 -126.358)"}},[e("rect",{attrs:{fill:"currentColor",width:"35",height:"5",rx:"2",transform:"translate(229 151.107) rotate(-45)"}}),this._v(" "),e("rect",{attrs:{fill:"currentColor",width:"35",height:"5",rx:"2",transform:"translate(274.949 154.642) rotate(-135)"}})])]):this._e()])}),[],!1,null,"5fd4ef0c",null).exports),xl=(n(371),n(209),[{},function(t){t.Vue.mixin({computed:{$dataBlock:function(){return this.$options.__data__block__}}})},{},function(t){var e=t.Vue;t.router.options.scrollBehavior=function(t,n,r){if(r)return window.scrollTo({top:r.y,behavior:"smooth"});if(t.hash){if(e.$vuepress.$get("disableScrollBehavior"))return!1;var o=document.querySelector(t.hash);return!!o&&window.scrollTo({top:(i=o,a=document.documentElement,l=a.getBoundingClientRect(),u=i.getBoundingClientRect(),{x:u.left-l.left,y:u.top-l.top}).y,behavior:"smooth"})}return window.scrollTo({top:0,behavior:"smooth"});var i,a,l,u}},function(t){var e,n,r,o,i,a,l=t.router;"undefined"!=typeof window&&(e=window,n=document,r="script",o="ga",e.GoogleAnalyticsObject=o,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,i=n.createElement(r),a=n.getElementsByTagName(r)[0],i.async=1,i.src="https://www.google-analytics.com/analytics.js",a.parentNode.insertBefore(i,a),ga("create","G-GFKQEFHX3B","auto"),ga("set","anonymizeIp",!0),l.afterEach((function(t){ga("set","page",l.app.$withBase(t.fullPath)),ga("send","pageview")})))},function(t){t.Vue.component("BackToTop",Cl)},{},function(t){t.router;"undefined"!=typeof window&&function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)}()},function(t){var e=t.router;var n,r,o,i,a;!0,"undefined"!=typeof window&&(window,n=document,r="script",o="https://hm.baidu.com/hm.js?45951f610a1fa82985715b79291a8de9",i=n.createElement(r),a=n.getElementsByTagName(r)[0],i.src=o,a.parentNode.insertBefore(i,a),e.afterEach((function(t){"undefined"!=typeof _hmt&&_hmt&&_hmt.push(["_trackPageview",t.fullPath])})))}]),Fl=["BackToTop"];function wl(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function _l(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}function Pl(t,e,n){return e&&_l(t.prototype,e),n&&_l(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t}n(204);function Ol(t,e){return(Ol=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}n(197),n(198);function kl(t){return(kl=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function Dl(t,e){if(e&&("object"===r(e)||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}function Sl(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var n,r=kl(t);if(e){var o=kl(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return Dl(this,n)}}var jl=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&Ol(t,e)}(n,t);var e=Sl(n);function n(){return wl(this,n),e.apply(this,arguments)}return Pl(n)}(function(){function t(){wl(this,t),this.store=new Lo({data:{state:{}}})}return Pl(t,[{key:"$get",value:function(t){return this.store.state[t]}},{key:"$set",value:function(t,e){Lo.set(this.store.state,t,e)}},{key:"$emit",value:function(){var t;(t=this.store).$emit.apply(t,arguments)}},{key:"$on",value:function(){var t;(t=this.store).$on.apply(t,arguments)}}]),t}());Object.assign(jl.prototype,{getPageAsyncComponent:Ga,getLayoutAsyncComponent:Wa,getAsyncComponent:Ha,getVueComponent:Xa});var Tl={install:function(t){var e=new jl;t.$vuepress=e,t.prototype.$vuepress=e}};n(127);function Ml(t){t.beforeEach((function(e,n,r){if($l(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){var o=e.path.replace(/\/$/,"")+".html";$l(t,o)?r(o):r()}else r();else{var i=e.path+"/",a=e.path+".html";$l(t,a)?r(a):$l(t,i)?r(i):r()}}))}function $l(t,e){var n=e.toLowerCase();return t.options.routes.some((function(t){return t.path.toLowerCase()===n}))}var Ll={props:{pageKey:String,slotKey:{type:String,default:"default"}},render:function(t){var e=this.pageKey||this.$parent.$page.key;return Ka("pageKey",e),Lo.component(e)||Lo.component(e,Ga(e)),Lo.component(e)?t(e):t("")}},Ul={functional:!0,props:{slotKey:String,required:!0},render:function(t,e){var n=e.props,r=e.slots;return t("div",{class:["content__".concat(n.slotKey)]},r()[n.slotKey])}},Rl={computed:{openInNewWindowTitle:function(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},Il=(n(373),n(374),Object(Bl.a)(Rl,(function(){var t=this.$createElement,e=this._self._c||t;return e("span",[e("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[e("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),e("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),e("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports);function Nl(){return(Nl=a(o().mark((function t(e){var n,r,i,a;return o().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n="undefined"!=typeof window&&window.__VUEPRESS_ROUTER_BASE__?window.__VUEPRESS_ROUTER_BASE__:yl.routerBase||yl.base,Ml(r=new Pa({base:n,mode:"history",fallback:!1,routes:ml,scrollBehavior:function(t,e,n){return n||(t.hash?!Lo.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})}})),i={},t.prev=4,t.next=7,Promise.all(xl.filter((function(t){return"function"==typeof t})).map((function(t){return t({Vue:Lo,options:i,router:r,siteData:yl,isServer:e})})));case 7:t.next=12;break;case 9:t.prev=9,t.t0=t.catch(4),console.error(t.t0);case 12:return a=new Lo(Object.assign(i,{router:r,render:function(t){return t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Fl.map((function(e){return t(e)})))])}})),t.abrupt("return",{app:a,router:r});case 14:case"end":return t.stop()}}),t,null,[[4,9]])})))).apply(this,arguments)}Lo.config.productionTip=!1,Lo.use(Pa),Lo.use(Tl),Lo.mixin(function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:Lo;Oa(e),n.$vuepress.$set("siteData",e);var r=t(n.$vuepress.$get("siteData")),o=new r,i=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(o)),a={};return Object.keys(i).reduce((function(t,e){return e.startsWith("$")&&(t[e]=i[e].get),t}),a),{computed:a}}((function(t){return function(){function e(){wl(this,e)}return Pl(e,[{key:"setPage",value:function(t){this.__page=t}},{key:"$site",get:function(){return t}},{key:"$themeConfig",get:function(){return this.$site.themeConfig}},{key:"$frontmatter",get:function(){return this.$page.frontmatter}},{key:"$localeConfig",get:function(){var t,e,n=this.$site.locales,r=void 0===n?{}:n;for(var o in r)"/"===o?e=r[o]:0===this.$page.path.indexOf(o)&&(t=r[o]);return t||e||{}}},{key:"$siteTitle",get:function(){return this.$localeConfig.title||this.$site.title||""}},{key:"$canonicalUrl",get:function(){var t=this.$page.frontmatter.canonicalUrl;return"string"==typeof t&&t}},{key:"$title",get:function(){var t=this.$page,e=this.$page.frontmatter.metaTitle;if("string"==typeof e)return e;var n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}},{key:"$description",get:function(){var t=function(t){if(t){var e=t.filter((function(t){return"description"===t.name}))[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}},{key:"$lang",get:function(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}},{key:"$localePath",get:function(){return this.$localeConfig.path||"/"}},{key:"$themeLocaleConfig",get:function(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}},{key:"$page",get:function(){return this.__page?this.__page:function(t,e){for(var n=0;n<t.length;n++){var r=t[n];if(r.path.toLowerCase()===e.toLowerCase())return r}return{path:"",frontmatter:{}}}(this.$site.pages,this.$route.path)}}]),e}()}),yl)),Lo.component("Content",Ll),Lo.component("ContentSlotsDistributor",Ul),Lo.component("OutboundLink",Il),Lo.component("ClientOnly",{functional:!0,render:function(t,e){var n=e.parent,r=e.children;if(n._isMounted)return r;n.$once("hook:mounted",(function(){n.$forceUpdate()}))}}),Lo.component("Layout",Wa("Layout")),Lo.component("NotFound",Wa("NotFound")),Lo.prototype.$withBase=function(t){var e=this.$site.base;return"/"===t.charAt(0)?e+t.slice(1):t},window.__VUEPRESS__={version:"1.9.7",hash:"538fe53"},function(t){return Nl.apply(this,arguments)}(!1).then((function(t){var e=t.app;t.router.onReady((function(){e.$mount("#app")}))}))}]); \ No newline at end of file diff --git a/css/index.css b/css/index.css new file mode 100644 index 000000000..902c7ca00 --- /dev/null +++ b/css/index.css @@ -0,0 +1,3 @@ +.gt-container{ + width: 80%; +} \ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8fde7c1422266ca5f5dc0c2ff8cb0c789e385ea6 GIT binary patch literal 277379 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%0DA)qK%gYWw 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%0ABZEPw6lSpb0u^_p}nOiWIpR`X+K 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%0AB&`Yfxa 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 000000000..59b871014 --- /dev/null +++ b/index.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/6.5f593451.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" aria-current="page" class="home-link router-link-exact-active router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" aria-current="page" class="nav-link router-link-exact-active router-link-active"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" aria-current="page" class="nav-link router-link-exact-active router-link-active"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/#基础" class="sidebar-link">基础</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#并发" class="sidebar-link">并发</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#runtime" class="sidebar-link">runtime</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#编译器" class="sidebar-link">编译器</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#工程" class="sidebar-link">工程</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#扫一扫添加我的公众号-回复-加群-可以加入微信群。" class="sidebar-link">扫一扫添加我的公众号,回复 “加群”,可以加入微信群。</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#star" class="sidebar-link">star</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/#证书" class="sidebar-link">证书</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p align="left"> +hey~,我是科科,目前就职于国内一家互联网公司,你们可以加我<a href="#wechat.png">微信</a>,交个朋友吧~ +</p> <br> <p align="center"><a href="#wechat.png" target="_blank"><img src="https://img.shields.io/static/v1?label=%E7%A7%91%E7%A7%91%E4%BA%BA%E7%A5%9E&message=%E5%85%AC%E4%BC%97%E5%8F%B7&color="></a> <a href="https://space.bilibili.com/478621088" target="_blank"><img src="https://img.shields.io/static/v1?label=bilibili&message=b%E7%AB%99&color=blue"></a> <a href="https://www.zhihu.com/people/shgopher" target="_blank"><img src="https://img.shields.io/static/v1?label=zhihu&message=%E7%9F%A5%E4%B9%8E&color=blue"></a> <a href="https://blog.csdn.net/zyfljxzby" target="_blank"><img src="https://img.shields.io/static/v1?label=csdn&message=CSDN&color=red"></a> <a href="https://www.toutiao.com/c/user/token/MS4wLjABAAAAIGeO1-kCUelF-G8GW3AvJlrEL7tiO24WHJmnX4nV1bs" target="_blank"><img src="https://img.shields.io/static/v1?label=toutiao&message=%E5%A4%B4%E6%9D%A1&color=red"></a></p> <p>添加微信公众号:<a href="#wechat.png">科科人神</a>,回复:</p> <ul><li><p><code>面试题</code>,获取经典 go 面试大全 (巨全,强推,不仅有 go 面试题还有大厂的算法和系统设计原题以及面试技巧等等内容)</p></li> <li><p><code>好友</code>,可以添加作者的微信好友</p></li></ul> <h2 id="基础">基础</h2> <ul><li><a href="/GOFamily/基础/helloWorld/">hello world</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E">变量声明</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E">常量声明</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC">零值</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F">复合字面量</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B">数字类型</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93">结构体</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/slice">slice</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/string">string</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/map">map</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F">求值顺序</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F">作用域</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95">函数方法</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/interface">接口</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5">逻辑和判断语句</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B">泛型</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86">错误处理</a></li> <li><a href="./%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9">其他内容</a></li></ul> <h2 id="并发">并发</h2> <ul><li><a href="./%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B">内存模型</a></li> <li><a href="./%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B">并发模型</a></li> <li><a href="./%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD">同步原语</a></li> <li><a href="./%E5%B9%B6%E5%8F%91/channel">channel</a></li> <li><a href="./%E5%B9%B6%E5%8F%91/context">context</a></li> <li><a href="./%E5%B9%B6%E5%8F%91/atomic">atomic</a></li></ul> <h2 id="runtime">runtime</h2> <ul><li><a href="./runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95">三色 gc 算法</a></li> <li><a href="./runtime/gmp">G:M:P</a></li> <li><a href="./runtime/%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D">堆内存分配</a></li> <li><a href="./runtime/%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86">栈内存管理</a></li> <li><a href="./runtime/%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7">系统监控</a></li> <li><a href="./runtime/netpool">netpool</a></li> <li><a href="./runtime/%E5%AE%9A%E6%97%B6%E5%99%A8">定时器</a></li></ul> <h2 id="编译器">编译器</h2> <ul><li><a href="./%E7%BC%96%E8%AF%91%E5%99%A8/gc">gc</a></li> <li><a href="./%E7%BC%96%E8%AF%91%E5%99%A8/llvm">llvm</a></li> <li><a href="./%E7%BC%96%E8%AF%91%E5%99%A8/gccgo">gccgo</a></li></ul> <h2 id="工程">工程</h2> <ul><li><a href="/GOFamily/工程/go编程范式/">go 编程范式/设计模式</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7">包管理工具</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/log">log 包</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95">测试</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95">动态调试</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/cgo">cgo</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5">代码检查</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E5%8F%8D%E5%B0%84">反射</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B">go web 编程</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/wasm">wasm</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/ioc">ioc</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4">命令</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81">字符编码</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E7%B3%BB%E7%BB%9F%E4%BF%A1%E5%8F%B7%E7%9A%84%E5%A4%84%E7%90%86">系统信号的处理</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E7%9A%84%E7%A7%98%E5%AF%86%E5%AD%A6">go 语言的密码学</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85">优秀第三方包</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93">go 标准库</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F">go 项目组织形式</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B">go 命名惯例</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83">go 语言规范</a></li> <li><a href="./%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98">go 面试题</a></li></ul> <h2 id="参考资料">参考资料</h2> <ul><li><a href="https://go.dev" target="_blank" rel="noopener noreferrer">go.dev<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/golang/go" target="_blank" rel="noopener noreferrer">go src<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://www.gopl.io/" target="_blank" rel="noopener noreferrer">the go programming language<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://book.douban.com/subject/35720729/" target="_blank" rel="noopener noreferrer">GO 语言精进之路<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://shgopher.github.io/pdf/mastering-go-cn.pdf" target="_blank" rel="noopener noreferrer">Mastering Go<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://draveness.me/golang/" target="_blank" rel="noopener noreferrer">Go 语言设计与实现<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://book.douban.com/subject/36104087/" target="_blank" rel="noopener noreferrer">深度探索 GO 语言<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://juejin.cn/post/7241452578125824061" target="_blank" rel="noopener noreferrer">我为什么放弃 GO 语言?<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/teivah/100-go-mistakes" target="_blank" rel="noopener noreferrer">100-go-mistakes<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://time.geekbang.org/opencourse/intro/100069501" target="_blank" rel="noopener noreferrer">Go 语言编程模式实战<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://time.geekbang.org/column/intro/100061801" target="_blank" rel="noopener noreferrer">Go 并发编程实战课<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://time.geekbang.org/column/intro/100079601" target="_blank" rel="noopener noreferrer">Go 语言项目开发实战<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://time.geekbang.org/column/intro/100013101" target="_blank" rel="noopener noreferrer">Go 语言核心 36 讲<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://time.geekbang.org/column/intro/100090601" target="_blank" rel="noopener noreferrer">手把手带你写一个 Web 框架<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://coding.imooc.com/class/chapter/180.html#Anchor" target="_blank" rel="noopener noreferrer">Google 资深工程师深度讲解 Go 语言<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/LeoYang90/Golang-Internal-Notes" target="_blank" rel="noopener noreferrer">Golang-Internal-Notes<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://space.bilibili.com/373073810" target="_blank" rel="noopener noreferrer">刘丹冰 Aceld bilibili<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul> <h2 id="扫一扫添加我的公众号-回复-加群-可以加入微信群。">扫一扫添加我的公众号,回复 “加群”,可以加入微信群。</h2> <p id="wechat.png" align="center"><br> <br> <img src="/GOFamily/assets/img/wechat.4a3030a4.png" alt="公众号搜:科科人神"></p> <h2 id="star">star</h2> <p><a href="https://starchart.cc/shgopher/GOFamily" target="_blank" rel="noopener noreferrer"><img src="https://starchart.cc/shgopher/GOFamily.svg" alt="Stargazers over time"><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h2 id="证书">证书</h2> <p><a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="知识共享许可协议" src="https://i.creativecommons.org/l/by/3.0/88x31.png" style="border-width:0;"></a><br>本作品采用<a rel="license" href="http://creativecommons.org/licenses/by/3.0/">知识共享署名 3.0 未本地化版本许可协议</a>进行许可。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/29/2024, 2:12:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/6.5f593451.js" defer></script> + </body> +</html> diff --git a/runtime/gmp/index.html b/runtime/gmp/index.html new file mode 100644 index 000000000..d2bf62d1f --- /dev/null +++ b/runtime/gmp/index.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/15.ccbbdb7a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/runtime/gmp/#参考文章" class="sidebar-link">参考文章</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="g-m-p">G:M:P</h1> <h2 id="参考文章">参考文章</h2> <ul><li>https://mp.weixin.qq.com/s/iAy9ReQhnmCYUFvwYroGPA</li> <li>https://www.bilibili.com/video/BV19r4y1w7Nx/</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/gmp/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/26/2023, 3:56:49 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/15.ccbbdb7a.js" defer></script> + </body> +</html> diff --git a/runtime/index.html b/runtime/index.html new file mode 100644 index 000000000..8873e9cc7 --- /dev/null +++ b/runtime/index.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>runtime | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/14.fa863532.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>runtime</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="runtime">runtime</h1> <ul><li><a href="./%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95">三色 gc 算法</a></li> <li><a href="./%E5%A0%86%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D">堆内存分配</a></li> <li><a href="./%E6%A0%88%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86">栈内存管理</a></li> <li><a href="./%E7%B3%BB%E7%BB%9F%E7%9B%91%E6%8E%A7">系统监控</a></li> <li><a href="./gmp">G:M:P</a></li> <li><a href="./%E5%AE%9A%E6%97%B6%E5%99%A8">定时器</a></li> <li><a href="./netpool">netpool</a></li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/14.fa863532.js" defer></script> + </body> +</html> diff --git a/runtime/netpool/index.html b/runtime/netpool/index.html new file mode 100644 index 000000000..ba7312e3b --- /dev/null +++ b/runtime/netpool/index.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/16.d5f6c328.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/runtime/netpool/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-语言网络模型">go 语言网络模型</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/jGrPM0UgqjZ10cXafoC0wQ</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/netpool/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/19/2023, 9:25:00 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/16.d5f6c328.js" defer></script> + </body> +</html> diff --git "a/runtime/\344\270\211\350\211\262gc\347\256\227\346\263\225/index.html" "b/runtime/\344\270\211\350\211\262gc\347\256\227\346\263\225/index.html" new file mode 100644 index 000000000..2d6b0cafb --- /dev/null +++ "b/runtime/\344\270\211\350\211\262gc\347\256\227\346\263\225/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>参考资料 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/17.1312d121.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>参考资料</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/runtime/%E4%B8%89%E8%89%B2gc%E7%AE%97%E6%B3%95/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="参考资料">参考资料</h2> <ul><li>https://draveness.me/golang/</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/三色gc算法/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/17.1312d121.js" defer></script> + </body> +</html> diff --git "a/runtime/\345\240\206\345\206\205\345\255\230\345\210\206\351\205\215/index.html" "b/runtime/\345\240\206\345\206\205\345\255\230\345\210\206\351\205\215/index.html" new file mode 100644 index 000000000..e60460b34 --- /dev/null +++ "b/runtime/\345\240\206\345\206\205\345\255\230\345\210\206\351\205\215/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/18.4b8a1599.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/堆内存分配/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/18.4b8a1599.js" defer></script> + </body> +</html> diff --git "a/runtime/\345\256\232\346\227\266\345\231\250/index.html" "b/runtime/\345\256\232\346\227\266\345\231\250/index.html" new file mode 100644 index 000000000..45c962923 --- /dev/null +++ "b/runtime/\345\256\232\346\227\266\345\231\250/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/19.5ed73af4.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/定时器/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/5/2024, 2:48:04 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/19.5ed73af4.js" defer></script> + </body> +</html> diff --git "a/runtime/\346\240\210\345\206\205\345\255\230\347\256\241\347\220\206/index.html" "b/runtime/\346\240\210\345\206\205\345\255\230\347\256\241\347\220\206/index.html" new file mode 100644 index 000000000..f09a5259a --- /dev/null +++ "b/runtime/\346\240\210\345\206\205\345\255\230\347\256\241\347\220\206/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/20.fea9a837.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/栈内存管理/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/20.fea9a837.js" defer></script> + </body> +</html> diff --git "a/runtime/\347\263\273\347\273\237\347\233\221\346\216\247/index.html" "b/runtime/\347\263\273\347\273\237\347\233\221\346\216\247/index.html" new file mode 100644 index 000000000..6eecf5ecb --- /dev/null +++ "b/runtime/\347\263\273\347\273\237\347\233\221\346\216\247/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/21.321b1448.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/runtime/系统监控/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/21.321b1448.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/helloWorld/index.html" "b/\345\237\272\347\241\200/helloWorld/index.html" new file mode 100644 index 000000000..c5999322a --- /dev/null +++ "b/\345\237\272\347\241\200/helloWorld/index.html" @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/23.6633ca8a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/helloWorld/#诞生背景" class="sidebar-link">诞生背景</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/helloWorld/#语言哲学" class="sidebar-link">语言哲学</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/helloWorld/#语言特点" class="sidebar-link">语言特点</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/helloWorld/#安装-go" class="sidebar-link">安装 Go</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/helloWorld/#hello-world-2" class="sidebar-link">hello world</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="hello-world">hello world</h1> <h2 id="诞生背景">诞生背景</h2> <p>Go 语言是 Google 的 Robert Griesemer,Rob Pike 和 Ken Thompson 于 2007 年开始设计开发的一门编程语言。Go 语言吸收了 C 语言的表达能力,并添加了像动态语言中的并发性等特性,目的是让编程更简单高效。</p> <h2 id="语言哲学">语言哲学</h2> <p>Go 语言编程哲学如下:</p> <ul><li>面向接口编程</li> <li>组合替换继承</li> <li>简单优于复杂</li> <li>内置并发支持</li></ul> <h2 id="语言特点">语言特点</h2> <p>Go 语言的主要特点有:</p> <ul><li>语法简单,容易学习使用</li> <li>编译非常迅速,执行速度较快</li> <li>静态类型语言 - 变量和函数需要声明类型</li> <li>垃圾回收 - 自动的内存管理,不需要手动释放内存</li> <li>并发支持 - 原生支持 goroutine 和 channel</li> <li>简洁规范 - 语法简单一致,容易阅读理解</li> <li>代码风格统一 - 提供了标准的代码风格</li></ul> <h2 id="安装-go">安装 Go</h2> <p>要安装 Go 语言,可以去官网 https://go.dev 下载最新的安装包。</p> <p>安装非常简单,一般直接使用默认设置即可完成安装。</p> <p>安装完成后,可以使用 <code>go version</code> 命令检查安装是否成功。</p> <h2 id="hello-world-2">hello world</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Hello World"</span><span class="token punctuation">)</span> + ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span>ch +<span class="token punctuation">}</span> +</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/helloWorld/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/26/2024, 10:08:28 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/23.6633ca8a.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/index.html" "b/\345\237\272\347\241\200/index.html" new file mode 100644 index 000000000..be8c7c7b4 --- /dev/null +++ "b/\345\237\272\347\241\200/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>基础 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/22.e3bbafa7.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>基础</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="基础">基础</h1> <ul><li><a href="./%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E">变量声明</a></li> <li><a href="./%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E">常量声明</a></li> <li><a href="./%E9%9B%B6%E5%80%BC">零值</a></li> <li><a href="./%E5%A4%8D%E5%90%88%E5%AD%97%E9%9D%A2%E9%87%8F">复合字面量</a></li> <li><a href="./%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B">数字类型</a></li> <li><a href="./slice">slice</a></li> <li><a href="./string">string</a></li> <li><a href="./map">map</a></li> <li><a href="./%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95">函数方法</a></li> <li><a href="./interface">interface</a></li> <li><a href="./%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5">逻辑和判断语句</a></li> <li><a href="./%E5%85%B3%E9%94%AE%E5%AD%97">关键字</a></li> <li><a href="./%E6%B3%9B%E5%9E%8B">泛型</a></li> <li><a href="./%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9">其他内容</a></li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/22.e3bbafa7.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/interface/index.html" "b/\345\237\272\347\241\200/interface/index.html" new file mode 100644 index 000000000..ef25903cc --- /dev/null +++ "b/\345\237\272\347\241\200/interface/index.html" @@ -0,0 +1,714 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/24.edf743ad.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#方法集合决定接口的实现" class="sidebar-link">方法集合决定接口的实现</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#接口嵌入" class="sidebar-link">接口嵌入</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#在接口中嵌入接口类型" class="sidebar-link">在接口中嵌入接口类型</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#在结构体中嵌入接口类型" class="sidebar-link">在结构体中嵌入接口类型</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#匿名接口" class="sidebar-link">匿名接口</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#类型断言" class="sidebar-link">类型断言</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#常规的断言方式" class="sidebar-link">常规的断言方式:</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#存在于-switch-中的断言方式" class="sidebar-link">存在于 switch 中的断言方式:</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#断言类型也可以是接口" class="sidebar-link">断言类型也可以是接口</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#接口类型的底层" class="sidebar-link">接口类型的底层</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#如何判断接口类型的相等" class="sidebar-link">如何判断接口类型的相等</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#小接口的意义" class="sidebar-link">小接口的意义</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#如何设计小接口" class="sidebar-link">如何设计小接口</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#不可滥用空接口" class="sidebar-link">不可滥用空接口</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#接口作为程序水平组合的连接点-提供程序的可扩展性" class="sidebar-link">接口作为程序水平组合的连接点,提供程序的可扩展性</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#接口提供程序的可测试性" class="sidebar-link">接口提供程序的可测试性</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#接口的严格和函数的宽松对比" class="sidebar-link">接口的严格和函数的宽松对比</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#interface-如何判断-nil" class="sidebar-link">interface 如何判断 nil</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#论述-nil-error-nil-的原因" class="sidebar-link">论述 “nil error != nil” 的原因</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#eface-和-iface-的区别" class="sidebar-link">eface 和 iface 的区别</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#如何查找-interface-中的方法" class="sidebar-link">如何查找 interface 中的方法</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#interface-设计的优缺点" class="sidebar-link">interface 设计的优缺点</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#空接口类型和一般类型是从属关系吗" class="sidebar-link">空接口类型和一般类型是从属关系吗?</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/interface/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="接口">接口</h1> <blockquote><p>有关泛型相关的约束内容均放置在<a href="../%E6%B3%9B%E5%9E%8B">泛型</a>这一章节,这里不再赘述</p></blockquote> <p>重点内容前情提要</p> <ul><li>方法集合决定接口的实现</li> <li>接口的嵌入</li> <li>类型断言</li> <li>接口类型的底层</li> <li>如何判断接口类型的相等</li> <li>论述 “nil error != nil” 的原因</li> <li>小接口的意义</li> <li>不可滥用空接口</li> <li>接口作为程序水平组合的连接点,提供程序的可扩展性</li> <li>接口提供程序的可测试性</li> <li>接口的严格对比函数的宽松</li></ul> <p>接口,go 语言提供的,用于抽象以及数据解耦的组件,<strong>在操作接口时,go 语言要求的严格程度远大于函数和方法。</strong></p> <p>在 go1.18+ 中接口的概念从包含抽象的方法变成了类型,但是我们在外部可以操作的接口仍然只能是经典接口,不过经典接口是可以当做约束在内部使用的,不过官方不推荐经典接口当做一般约束那种使用方式。</p> <p>go 语言为了区分,将传统接口称之为接口,将扩展的接口称之为约束,实际上传统接口是约束概念的子集。扩展的约束并不能在函数或者方法以及类型之外使用。</p> <p>这一章我们只介绍经典接口的基本概念和使用方法。</p> <p>接口具有静态语言和动态语言的共同特点。</p> <p>静态类型特点:</p> <ul><li>接口可以作为类型:<code>var e error</code></li> <li>支持在编译期进行类型检查:在编译器期间会对右边的变量进行类型的检查,检查是否实现了接口定义的方法类型中的所有方法</li></ul> <p>动态类型的特点:</p> <ul><li>在运行时可以对接口进行动态赋值</li> <li>接口类型可以在运行时被赋予不同的动态类型变量,从而进行 “多态”</li></ul> <h2 id="方法集合决定接口的实现">方法集合决定接口的实现</h2> <p>通常,我们使用下面这种形式去完成接口的实现</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Writer <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Write</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> BufferWrite <span class="token keyword">struct</span> <span class="token punctuation">{</span> + value bytes<span class="token punctuation">.</span>Buffer +<span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>b <span class="token operator">*</span>BufferWrite<span class="token punctuation">)</span> <span class="token function">Write</span><span class="token punctuation">(</span>p <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>我们知道,go 语言规定,不可跨包去实现类型的方法,所以我们只讨论自定义的类型与接口之间的关系,首先抛出结论:松耦合关系。</p> <p>go 语言使用一种叫做鸭子理论的方式去实现接口:只要实现了接口的方法 (go 泛型,go1.18+, 理论从方法改为了类型) 就算是实现了这个接口,这属于隐式接口实现。即:接口和它的实现者之间为正交关系。</p> <p>通常来说,例如 es6,Java 等都是要显式的说明实现了哪个接口的,但是 go 不需要,它只需要实现方法即可,而且,它还可以实现多个接口,毕竟多实现几个方法就可以算是实现了这个接口。由此还可以推断出,go 可以多实现方法,而不会影响对接口的实现。</p> <p>这里要说明一下,go 语言对于定义在指针类型上的变量有语法糖:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Writer <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>s Student<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span> <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> t Student + <span class="token keyword">var</span> tp <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student<span class="token punctuation">)</span> + <span class="token keyword">var</span> w Writer + <span class="token comment">// ❌</span> + w <span class="token operator">=</span> t + <span class="token comment">// ✅</span> + w <span class="token operator">=</span> tp + +<span class="token punctuation">}</span> +</code></pre></div><p>我们可以看到,get 和 set 分别是一个值类型和一个指针类型上实现的,这里我们的结论是:当实现接口时,<strong>类型的指针变量</strong>在实现方法上可以包括<em><strong>定义在类型指针上的方法以及定义在值类型上的方法***,但是</strong>值类型变量</em><em>只包含定义在</em><em>值类型</em>*上的方法</p> <p>这里是提示信息:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>cannot use t <span class="token punctuation">(</span>variable of <span class="token builtin class-name">type</span> Student<span class="token punctuation">)</span> as Writer value <span class="token keyword">in</span> assignment: Student does not implement Writer <span class="token punctuation">(</span>method <span class="token builtin class-name">set</span> has pointer receiver<span class="token punctuation">)</span> +</code></pre></div><p>通常来说,这不应该成为程序员的烦恼,所以想用谁就好好的定义在谁上面的方法即可,完全不会出错。</p> <h2 id="接口嵌入">接口嵌入</h2> <h3 id="在接口中嵌入接口类型">在接口中嵌入接口类型</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Writer <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Write</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> + <span class="token function">error</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Error1 <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">error</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> WriterError <span class="token keyword">interface</span> <span class="token punctuation">{</span> + Writer + Error1 +<span class="token punctuation">}</span> +</code></pre></div><p>这样的组合就可以组合成一个新的接口,并且嵌入的接口还可以有方法上的交集,go 是不介意的 (go1.14+)。</p> <h3 id="在结构体中嵌入接口类型">在结构体中嵌入接口类型</h3> <p>在结构体中嵌入一个接口,就相当于实现了这个接口 (当然结构体的指针类型也实现了这个接口),拥有了它的方法,但是注意,拥有的是这种抽象方法,那么我们为什么要将一个接口类型嵌入到一个结构体中呢?</p> <p>因为 go 语言规定,嵌入接口,结构体相当于实现了这些接口,这里注意,这里必须是直接嵌入,如果是接口类型作为变量类型的方式是不能拥有接口的方法的。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// ✅</span> +<span class="token keyword">type</span> A1 <span class="token keyword">struct</span><span class="token punctuation">{</span> + A +<span class="token punctuation">}</span> +<span class="token comment">// ❌</span> +<span class="token keyword">type</span> A2 <span class="token keyword">struct</span><span class="token punctuation">{</span> + A A +<span class="token punctuation">}</span> +<span class="token comment">// ❌</span> +<span class="token keyword">type</span> A3 <span class="token keyword">struct</span><span class="token punctuation">{</span> + a A +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>当结构体本身也实现了方法时,优先调用结构体的方法。</strong></em></p> <p>这个场景是这样的,在某个函数中,它的参数是一个接口类型,并且这个函数调用的只是这个接口类型的某个,或几个方法,并不是全部,那么我们作为结构体,想实现这个接口,又不想多实现额外的方法,那么这种方法就很好用了。</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>A<span class="token punctuation">)</span> + <span class="token function">D</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> A <span class="token keyword">struct</span> <span class="token punctuation">{</span> + BI +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> BI <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>A<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span> + <span class="token comment">// 如果想调用被嵌入的接口的方法可以这么用,</span> + <span class="token comment">// 我们知道调用直接嵌入的对象时候,变量名称默等于后面的类型名称,</span> + <span class="token comment">// 看下面演示</span> + <span class="token comment">// var a A</span> + <span class="token comment">// a.BI.get()</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">D</span><span class="token punctuation">(</span>b BI<span class="token punctuation">)</span> <span class="token punctuation">{</span> + b<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +</code></pre></div><p>注意上文提到了,接口中内嵌接口的时候,内嵌的接口方法可以重复,但是结构体中内嵌的接口,不允许出现方法重复的问题:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌ : ambiguous selector a.get</span> +<span class="token keyword">type</span> A <span class="token keyword">struct</span><span class="token punctuation">{</span> + BI + BI1 +<span class="token punctuation">}</span> +<span class="token keyword">type</span> BI <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> BI1 <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">err</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>不过,要想解决这个问题,我们只需要让结构体实现这种重复的方法即可,这样,优先级就提升到了结构体,接口的方法就不会被调用了。比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a A + <span class="token function">D</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token function">D1</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> A <span class="token keyword">struct</span> <span class="token punctuation">{</span> + BI + BI1 +<span class="token punctuation">}</span> +<span class="token keyword">type</span> BI <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> BI1 <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">err</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>A<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">D</span><span class="token punctuation">(</span>b BI<span class="token punctuation">)</span> <span class="token punctuation">{</span> + b<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">D1</span><span class="token punctuation">(</span>b BI1<span class="token punctuation">)</span> <span class="token punctuation">{</span> + b<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>下面让我们看一下,这种用法在单元测试场景中的应用</p> <p>让我们描述一个场景:</p> <p>有一个函数,它接受一个接口类型作为参数,我们要对它进行单元测试,而且我们要伪造一些数据。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数体</span> +<span class="token keyword">func</span> <span class="token function">MaleCount</span><span class="token punctuation">(</span>s stmt<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + result<span class="token punctuation">,</span>err <span class="token operator">:=</span> s<span class="token punctuation">.</span><span class="token function">Exec</span><span class="token punctuation">(</span><span class="token string">"SELECT count(*) FROM exployee_tab WHERE gender=?"</span><span class="token punctuation">,</span><span class="token string">"1"</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">,</span>err + <span class="token punctuation">}</span> + <span class="token keyword">return</span> result<span class="token punctuation">.</span><span class="token function">Int</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token boolean">nil</span> +<span class="token punctuation">}</span> +<span class="token comment">// 抽象接口</span> +<span class="token keyword">type</span> stmt <span class="token keyword">interface</span> <span class="token punctuation">{</span> + Close <span class="token builtin">error</span> + <span class="token function">NumInput</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">int</span> + <span class="token function">Exec</span><span class="token punctuation">(</span>stmt <span class="token builtin">string</span><span class="token punctuation">,</span>args <span class="token operator">...</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span>Result<span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span> + <span class="token function">Query</span><span class="token punctuation">(</span>args <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span>Rows<span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// 接口相关的一些数据</span> +<span class="token keyword">type</span> Result <span class="token keyword">struct</span><span class="token punctuation">{</span> + Count <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>r Result<span class="token punctuation">)</span> <span class="token function">Int</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token keyword">return</span> r<span class="token punctuation">.</span>Count<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Rows <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>我们可以看到,要想对这个 MaleCount 函数进行处理,那么一个实现了 stmt 接口的动态类型必不可少,但是我们并不需要所有的方法,仅仅需要 Exec 方法。</p> <p>所以我们第一步就是设置一个 fake 类型,并且将接口内嵌来完成 “继承”。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> fakeStmtForMaleCount <span class="token keyword">struct</span><span class="token punctuation">{</span> + stmt +<span class="token punctuation">}</span> +<span class="token comment">// 这里实际上只是简写,</span> +<span class="token comment">//真正的测试要对smt和arg进行测试的</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>f fakeStmtForMaleCount<span class="token punctuation">)</span><span class="token function">Exec</span><span class="token punctuation">(</span>stmt <span class="token builtin">string</span><span class="token punctuation">,</span>args <span class="token operator">...</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span>Result<span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> Result<span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当我们内嵌完成继承之后,我们相当于拥有了这些抽象方法,然后我们在这个接口体上自行实现 Exec,这样就可以将结构体的 Exec 优先级提前。</p> <p>那么让我们开始使用虚假数据 <code>Result{1}</code> 开始测试 MaleCount 函数</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">TestEmployeeMaleCount</span><span class="token punctuation">(</span>t <span class="token operator">*</span>testing<span class="token punctuation">.</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fs <span class="token operator">:=</span> fakeStmtForMaleCount<span class="token punctuation">{</span><span class="token punctuation">}</span> + v<span class="token punctuation">,</span>err <span class="token operator">:=</span> <span class="token function">MaleCount</span><span class="token punctuation">(</span>fs<span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + t<span class="token punctuation">.</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token string">"error is :"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">if</span> v <span class="token operator">!=</span> <span class="token number">1</span> <span class="token punctuation">{</span> + t<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"we want %d, actual is %d"</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="匿名接口">匿名接口</h2> <p>与普通命名接口不同,匿名接口没有类型名,只通过方法集来定义接口</p> <p>匿名接口的作用主要有:</p> <ul><li>临时使用,不需要命名</li> <li>作为参数或返回值,减少接口命名</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">doSomething</span><span class="token punctuation">(</span>v <span class="token keyword">interface</span><span class="token punctuation">{</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// ...</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">returnInterface</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">interface</span><span class="token punctuation">{</span> <span class="token function">Foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token punctuation">{</span> + <span class="token comment">// ...</span> + <span class="token keyword">return</span> x +<span class="token punctuation">}</span> +</code></pre></div><h2 id="类型断言">类型断言</h2> <p>当使用空接口作为类型参数的时候,空接口已经充盈了一个动态类型,如果我们要将这个空接口类型转化为原来的类型就需要断言。</p> <h3 id="常规的断言方式">常规的断言方式:</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a any + a <span class="token operator">=</span> <span class="token number">12</span> + <span class="token comment">// 第二个参数 ok 变量可以省略</span> + <span class="token comment">// v := a.(int)</span> + <span class="token comment">// fmt.Println(v)</span> + <span class="token keyword">if</span> v<span class="token punctuation">,</span> ok <span class="token operator">:=</span> a<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ok <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="存在于-switch-中的断言方式">存在于 switch 中的断言方式:</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> f any + f <span class="token operator">=</span> <span class="token string">"12"</span> + <span class="token comment">// (type)里面的type为固定用法,不能更改。</span> + <span class="token keyword">switch</span> v <span class="token operator">:=</span> f<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token builtin">string</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"NO"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="断言类型也可以是接口">断言类型也可以是接口</h3> <p>断言中的类型不止是实际类型比如 int 比如一个具体的 struct,还能是接口类型,比如一个接口类型:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">type</span> MyAget <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">IsMyAget</span><span class="token punctuation">(</span>e <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token builtin">bool</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token boolean">_</span> <span class="token punctuation">,</span>ok<span class="token operator">:=</span>e<span class="token punctuation">.</span><span class="token punctuation">(</span>MyAget<span class="token punctuation">)</span><span class="token punctuation">;</span>ok<span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">true</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">false</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这个函数的意义是这样的,接受一个 error 接口类型的对象,然后断言看它是否是 MyAget 接口类型。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Age <span class="token keyword">struct</span> <span class="token punctuation">{</span> + value <span class="token builtin">string</span> + e <span class="token builtin">error</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>Age<span class="token punctuation">)</span> <span class="token function">Age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">10</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>a <span class="token operator">*</span>Age<span class="token punctuation">)</span><span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> a<span class="token punctuation">.</span>value +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">IsMyAget</span><span class="token punctuation">(</span><span class="token operator">&</span>Age<span class="token punctuation">{</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token boolean">nil</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="接口类型的底层">接口类型的底层</h2> <p>这是接口的底层数据:</p> <p>一般接口:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// interface</span> +<span class="token keyword">type</span> iface <span class="token keyword">struct</span> <span class="token punctuation">{</span> + tab <span class="token operator">*</span>itab + data unsafe<span class="token punctuation">.</span>Pointer +<span class="token punctuation">}</span> +</code></pre></div><p>空接口:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// empty interface</span> +<span class="token keyword">type</span> eface <span class="token keyword">struct</span> <span class="token punctuation">{</span> + _type <span class="token operator">*</span>_type + data unsafe<span class="token punctuation">.</span>Pointer +<span class="token punctuation">}</span> +</code></pre></div><p>data 表示的意思一样,值是动态类型的地址。我们比较 value 时,比较的是地址指向的数据是否相同而不是地址本身。</p> <p>空接口并没有定义接口的方法,因此 <code>_type</code> 定义的均为动态类型的元数据</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> _type <span class="token keyword">struct</span> <span class="token punctuation">{</span> + size <span class="token builtin">uintptr</span> + ptrdata <span class="token builtin">uintptr</span> + hash <span class="token builtin">uint32</span> + tflag tflag + align <span class="token builtin">uint8</span> + fieldalign <span class="token builtin">uint8</span> + kind <span class="token builtin">uint8</span> + alg <span class="token operator">*</span>typeAlg + gcdata <span class="token operator">*</span><span class="token builtin">byte</span> + str nameOff + ptrToThis typeOff + +<span class="token punctuation">}</span> +</code></pre></div><p>一般接口因为本身定义了方法,因此它需要定义自己的方法,以及动态类型的数据,因此它除了 <code>_type</code> 外,还定义了 <code>interfacetype</code> 用来存储自己定义的方法元数据。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> itab <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token comment">// 非空接口本身的信息</span> + inter <span class="token operator">*</span>interfacetype + <span class="token comment">// 动态类型数据</span> + _type <span class="token operator">*</span>_type + <span class="token comment">// _type.hash的copy,用于 switch 判断类型</span> + hash <span class="token builtin">uint32</span> + <span class="token boolean">_</span> <span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token builtin">byte</span> + <span class="token comment">// 动态类型已实现接口方法的调用地址数组</span> + fun <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token builtin">uintptr</span> +<span class="token punctuation">}</span> +</code></pre></div><p>注意这里的 fun 数组,这里定义的 <code>[1]uintptr</code> 在实际使用时,可能不是 [1],这里的数据时可变的,如果是 2,就表示实现了两个方法。</p> <p>原文的注释是这样的 <code>// variable sized. fun[0]==0 means _type does not implement inter.</code></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> interfacetype <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token comment">// 接口本身的类型信息</span> + typ _type + <span class="token comment">// 接口所在的包路径</span> + pkgpath name + <span class="token comment">// 接口方法集合</span> + mhdr <span class="token punctuation">[</span><span class="token punctuation">]</span>imethod +<span class="token punctuation">}</span> + +</code></pre></div><h2 id="如何判断接口类型的相等">如何判断接口类型的相等</h2> <p><em><strong>当接口类型未被赋予动态类型时</strong></em>,它的两个字段,即:动态类型字段和动态类型 value 字段均为 nil,那么这个未初始化的接口变量就恒等于 <code>nil</code></p> <p>当接口类型被赋予了动态类型,那么如果判断这时候的接口类型,必须为类型相同以及值相同,接下来我们看一个案例:</p> <p><em><strong>两个非空非 nil 接口变量比较:</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">printNonEmptyInterface1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> T <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>t T<span class="token punctuation">)</span> <span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token string">"bad error"</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">printNonEmptyInterface1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> err1 <span class="token builtin">error</span> <span class="token comment">// 非空接口类型</span> + <span class="token keyword">var</span> err1ptr <span class="token builtin">error</span> <span class="token comment">// 非空接口类型</span> + <span class="token keyword">var</span> err2 <span class="token builtin">error</span> <span class="token comment">// 非空接口类型</span> + <span class="token keyword">var</span> err2ptr <span class="token builtin">error</span> <span class="token comment">// 非空接口类型</span> + + err1 <span class="token operator">=</span> T<span class="token punctuation">{</span><span class="token string">"eden"</span><span class="token punctuation">}</span> + err1ptr <span class="token operator">=</span> <span class="token operator">&</span>T<span class="token punctuation">{</span><span class="token string">"eden"</span><span class="token punctuation">}</span> + + err2 <span class="token operator">=</span> T<span class="token punctuation">{</span><span class="token string">"eden"</span><span class="token punctuation">}</span> + err2ptr <span class="token operator">=</span> <span class="token operator">&</span>T<span class="token punctuation">{</span><span class="token string">"eden"</span><span class="token punctuation">}</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"err1:"</span><span class="token punctuation">,</span> err1<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"err2:"</span><span class="token punctuation">,</span> err2<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"err1 = err2:"</span><span class="token punctuation">,</span> err1 <span class="token operator">==</span> err2<span class="token punctuation">)</span> <span class="token comment">// true</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"err1ptr:"</span><span class="token punctuation">,</span> err1ptr<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"err2ptr:"</span><span class="token punctuation">,</span> err2ptr<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"err1ptr = err2ptr:"</span><span class="token punctuation">,</span> err1ptr <span class="token operator">==</span> err2ptr<span class="token punctuation">)</span> <span class="token comment">// false</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code>err1<span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token number">0x104c959a8</span><span class="token punctuation">,</span><span class="token number">0x1400004c748</span><span class="token punctuation">)</span> +err2<span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token number">0x104c959a8</span><span class="token punctuation">,</span><span class="token number">0x1400004c728</span><span class="token punctuation">)</span> +err1 <span class="token operator">=</span> err2<span class="token punctuation">:</span> <span class="token boolean">true</span> +err1ptr<span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token number">0x104c95988</span><span class="token punctuation">,</span><span class="token number">0x1400004c738</span><span class="token punctuation">)</span> +err2ptr<span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token number">0x104c95988</span><span class="token punctuation">,</span><span class="token number">0x1400004c758</span><span class="token punctuation">)</span> +err1ptr <span class="token operator">=</span> err2ptr<span class="token punctuation">:</span> <span class="token boolean">false</span> +</code></pre></div><blockquote><p>println,预定义函数,在编译期间,会由编译器根据要输出的参数的类型,将 println 替换为特定的函数,这些预定义函数定义在 <a href="https://github.com/golang/go/blob/96d16803c2aae5407e99c2a1db79bb51d9e1c8da/src/runtime/print.go#L255" target="_blank" rel="noopener noreferrer">runtime/print.go<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 中,针对 eface 和 iface 的打印函数是: +<code>go func printeface(e eface){ print(e._type, e.data) }</code> <code>go func printiface(i iface){ print(i.tab, i.data) }</code></p></blockquote> <p>如代码所示,我们要判断的是,非空接口,并且已经实现了动态类型的两组接口类型,答案已经写在代码里了,即:<code>err1 == err2</code> <code>err1ptr != err2ptr</code></p> <p>现在就让我们从源码出发来探究一下原因。</p> <p>首先,我们知道<strong>类型相同以及值相同才是真的相等</strong>,err1 和 err2 的动态类型均为 <code>T</code>,值也均为 <code>T{"eden"}</code>,所以他们相等;err1ptr,和 err2ptr 的类型均为 <code>*T</code>,值均为 <code>&T{"eden"}</code>,但是系统却判断他们不相等,从源码来看,二者的 <code>tab *itab</code>,因为动态类型的元数据相同,这个字段一致,所以类型一致,从第二个字段 data 来说,<em><strong>data 存储了 <code>&T{"edent"}</code> 的地址,这个地址指向的内容仍为地址</strong></em>,从内容上来说地址指向的地址值并不相同,所以这就可以解释为什么结果是 false 了。</p> <p><em><strong>接下来我们看一下两个空非 nil 接口类型的比较:</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a any + <span class="token keyword">var</span> b any + a <span class="token operator">=</span> <span class="token operator">&</span>S<span class="token punctuation">{</span> + <span class="token string">"1"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + b <span class="token operator">=</span> <span class="token operator">&</span>S<span class="token punctuation">{</span> + <span class="token string">"1"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token comment">//(0x102f8aaa0,0x1400004c758)</span> + <span class="token comment">//(0x102f8aaa0,0x1400004c748)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + <span class="token comment">// false</span> + <span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> S <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>根据源码所知,a 和 b 的 <code>_type</code> 是完全相同的,然而地址指向的地址不相同,所以结果是 false,下面让我们稍微改动一下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a any + <span class="token keyword">var</span> b any + a <span class="token operator">=</span> <span class="token operator">&</span>S<span class="token punctuation">{</span> + + <span class="token punctuation">}</span> + b <span class="token operator">=</span> <span class="token operator">&</span>S<span class="token punctuation">{</span> + + <span class="token punctuation">}</span> +<span class="token comment">// (0x104422aa0,0x1400004c767)</span> +<span class="token comment">// (0x104422aa0,0x1400004c767)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + <span class="token comment">// true</span> + <span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> S <span class="token keyword">struct</span> <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>这个时候你惊奇的发现,结果竟然是 true,这是为什么呢?不是说,地址指向的地址应该是不同的吗?nonono,并不是所有的情况都是那样,如果结果是空接口,那么空接口的所有变量指向的都是同一个地址,所以从结果上来说,data 其实地址是相同的,指向的是同一个数据,所以答案是 true。</p> <blockquote><p>在 Go 中,空数据结构 (比如 struct {}) 不占用任何内存空间,因此在创建空数据结构时,它们实际上是指向同一个地址的。这是因为在 Go 中,每个变量都需要分配内存空间,以便可以存储它们的值。但是,由于空结构体没有任何字段,因此它们不需要分配任何内存空间。因此,在创建空结构体时,它们实际上是指向同一个已经分配的零大小内存块的指针。</p></blockquote> <p><em><strong>一个非空接口类型和一个空接口类型一定不相等吗?</strong></em></p> <p>如果你根据源码来看,第一个字段本身就不一样,肯定不相等了,但是 go 在比较相等时,比较的是 <code>_type</code> 字段,并不是全部的 tab 数据,所以当两者字段中的 <code>_type</code> 相同就表示类型相同:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a any <span class="token operator">=</span> S<span class="token punctuation">{</span><span class="token number">6</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> b B <span class="token operator">=</span> S<span class="token punctuation">{</span><span class="token number">6</span><span class="token punctuation">}</span> + <span class="token comment">//(0x1040dfae0,0x1400004c760) </span> + <span class="token comment">//(0x1040e5a68,0x1400004c758)</span> + <span class="token comment">//true</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> S <span class="token keyword">struct</span><span class="token punctuation">{</span> + <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> B <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>S<span class="token punctuation">)</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>所以从结果来看,_type 字段相同均为 S,data 也是一致的,所以答案是 true</p> <p><em><strong>nil 接口类型:</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> e <span class="token builtin">error</span> + <span class="token keyword">var</span> a any + <span class="token comment">//(0x0,0x0)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token comment">//(0x0,0x0)</span> + <span class="token function">println</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>e <span class="token operator">==</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> e<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当一个接口是未给定动态类型的接口类型,它就是 nil 接口,那么它的类型和 data 值均为空,所以只要是 nil 接口,他们均相等,并且等于 nil。</p> <p>最后说明一下,<em><strong>当接口类型获取动态类型的时候,绝大多数情况下,会将动态类型的值复制,并且放置在一个新的内存空间里,所以原始数据跟接口类型的数据再无瓜葛,指针类型除外</strong></em>,不过为了节省空间,有一种情况,go 编译器就会放弃这个动作,并不会每次都重新分配。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> x any <span class="token operator">=</span> <span class="token number">34</span> + <span class="token keyword">var</span> y any <span class="token operator">=</span> x + <span class="token keyword">var</span> z any <span class="token operator">=</span> x +<span class="token comment">// (0x1023343e0,0x10232c1b0)</span> +<span class="token comment">// (0x1023343e0,0x10232c1b0)</span> +<span class="token comment">// (0x1023343e0,0x10232c1b0)</span> + <span class="token function">println</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>z<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>可以看到,go 判断,x y z 三个空接口类型的动态类型,类型均相同都是 int,并且 data 指向同一块内存地址。</p> <p>非空接口也是一样:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a1 a <span class="token operator">=</span> b<span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> a2 a <span class="token operator">=</span> a1 +<span class="token comment">// (0x102791a48,0x1400004c758)</span> +<span class="token comment">// (0x102791a48,0x1400004c758)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a1<span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a2<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> a <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> b <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>我们如果想获取关于接口的内部实现细节,可以看一下这个<a href="https://github.com/bigwhite/GoProgrammingFromBeginnerToMaster/blob/main/chapter5/sources/dumpinterface.go" target="_blank" rel="noopener noreferrer">项目<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>,可以输出内部的信息</p> <h2 id="小接口的意义">小接口的意义</h2> <p><em><strong>接口越小,抽象程度越高,使用范围也就越大</strong></em></p> <p>一群飞禽走兽,我们可以给他们的行为抽象为 “飞行”,一群能游泳的动物我们可以给他们的行为抽象为 “游泳”。那么飞行和游泳涵盖的内容就会非常的多,使用范围就会很大,比如我们现在有一个函数,要求对所有能飞行的动物做出打印动作,那么众多飞行的动物就都可以使用这个函数。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + e1 <span class="token operator">:=</span> e<span class="token punctuation">{</span><span class="token string">"大鹅"</span><span class="token punctuation">}</span> + y1 <span class="token operator">:=</span> y<span class="token punctuation">{</span><span class="token string">"老鹰"</span><span class="token punctuation">}</span> + <span class="token comment">// {大鹅} 他们的具体行为模式是: 大鹅慢慢的飞</span> + <span class="token function">PrintFlyer</span><span class="token punctuation">(</span>e1<span class="token punctuation">)</span> + <span class="token comment">// {老鹰} 他们的具体行为模式是: 老鹰迅速飞行</span> + <span class="token function">PrintFlyer</span><span class="token punctuation">(</span>y1<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Flyer <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Fly</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>flyMod <span class="token builtin">string</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">PrintFlyer</span><span class="token punctuation">(</span>f Flyer<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>f<span class="token punctuation">,</span> <span class="token string">"他们的具体行为模式是:"</span><span class="token punctuation">,</span> f<span class="token punctuation">.</span><span class="token function">Fly</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 大鹅</span> +<span class="token keyword">type</span> e <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token function">Fly</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token string">"大鹅慢慢的飞"</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 老鹰</span> +<span class="token keyword">type</span> y <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>y<span class="token punctuation">)</span> <span class="token function">Fly</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token string">"老鹰迅速飞行"</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>易于实现和测试</strong></em></p> <p>当接口的方法较少时,动态类型实现的方法就少了,必然容易实现以及容易测试。</p> <p><em><strong>高內聚,易于复合组合</strong></em></p> <p>我们抽象程度很高的接口,接口做的事情就很单一,比如飞行类的接口方法就是飞行,游泳动物的接口方法就只有游泳,当有会游泳也会飞行的动物时,我们只需要成立一个新的接口,将飞机类和游泳类的接口嵌入到新接口中就形成了一个全新的会飞行也会游泳的接口了。</p> <p>如果一个接口涵盖了各种方法,那么当组合接口的时候,势必某些方法是被弃用的,所以综上所述,设置单一的,高内聚的方法是好的设计方案。</p> <h3 id="如何设计小接口">如何设计小接口</h3> <ol><li><p>先初步抽象出接口,这个时候可以有耦合,也可以不够高抽象,但是你得先定义出一个初步的接口出来,与此同时我们也得清楚,越是业务代码,抽象出一个高内聚的接口越难。</p></li> <li><p>将大接口拆分为小接口,使用一段时间以后,我们会发现某些操作是可以单出被提取出来的,比如 io 包的 writer 和 reader,那么我们就可以把这个动作单独抽象出来。抽象的最高程度就是只有一个方法,这就非常的內聚了,可以说,这种程度的抽象在日常业务中还是相对比较难的,需要在长时间的使用中,慢慢摸索。</p></li></ol> <p>综上所述:现搞出一个能用的大接口再说,以后慢慢解耦,形成抽象程度更高的小接口。</p> <h2 id="不可滥用空接口">不可滥用空接口</h2> <p>空接口和非空接口最大的差异性其实不止是底层数据的不同,我们知道他们一个是 eface 一个是 iface,最重要的差距是,非空接口在编译期是会对接口变量要赋值的动态类型做编译检查的,也就是说会对实参进行检查,来确定他真的实现了这个接口定义的方法,这就是一次安全的保护屏障</p> <p>与此同时,空接口并没有提供任何的保护屏障,他没有给编译器提供要检查的参数,因此我们说不要滥用空接口,因为它让你的代码缺少编译期间的安全检查屏障。</p> <p>因为空接口的不安全性,我们可以得出一下结论</p> <ul><li>尽量不使用空接口</li> <li>仅仅在未知类型的时候使用空接口</li> <li>如果存在已知类型,并且类型较多的情况下,可以使用泛型编程</li> <li>尽可能的抽象出带有方法的接口,并使用非空接口去作为函数参数</li></ul> <h2 id="接口作为程序水平组合的连接点-提供程序的可扩展性">接口作为程序水平组合的连接点,提供程序的可扩展性</h2> <p>在 go 语言中,一切皆组合,不过组合分为两种:</p> <ol><li>垂直组合,也就是类似接口的嵌入,结构体的嵌入,这种类型的组合被称之为垂直组合</li> <li>水平组合,接口是水平组合的关键,当函数使用接口作为参数之后,实际参数可以无限制的水平扩展,只要我们传入的变量实现了这个接口</li></ol> <p>垂直组合的三种方法:</p> <ul><li>往接口中嵌入接口实现新接口</li> <li>往结构体中嵌入接口,实现接口体实现接口这个操作</li> <li>往接口体中嵌入结构体,实现新的结构体这个操作</li></ul> <p>水平组合的几种形式:</p> <p><em><strong>基本形式:</strong></em></p> <p>函数或者方法的参数是接口类型,接口类型作为连接点,将多个包的数据连接在一起。这种方法满足了 “依赖抽象”,“里氏替换原则”,“接口隔离” 等代码设计原则。</p> <blockquote><p>依赖抽象原则 (Dependency Inversion Principle,DIP):高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。(<strong>接口本身就是一种抽象,高层模块和底层模块都依赖接口这个抽象组件组合在一起</strong>) +里氏替换原则 (Liskov Substitution Principle,LSP):子类对象应该能够替换掉程序中的任何父类对象。也就是说,在任何需要父类对象的地方,都可以使用子类对象来替换,而不会影响程序的正确性。(<strong>接口动态类型将替换接口变量</strong>) +接口隔离原则 (Interface Segregation Principle,ISP):客户端不应该依赖于它不需要的接口。也就是说,一个类对另外一个类的依赖应该建立在最小的接口上。(<strong>go 推崇最小接口模式</strong>)</p></blockquote> <p>这些原则都是为了提高代码的可维护性、可扩展性和可重用性。它们可以帮助我们设计出更加灵活、健壮和易于维护的代码。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Read</span><span class="token punctuation">(</span>r io<span class="token punctuation">.</span>Reader<span class="token punctuation">,</span><span class="token builtin">cap</span> <span class="token builtin">int64</span><span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">Copy</span><span class="token punctuation">(</span>r io<span class="token punctuation">.</span>Writer<span class="token punctuation">,</span>src io<span class="token punctuation">.</span>Reader<span class="token punctuation">)</span> +</code></pre></div><p><em><strong>包裹函数:</strong></em></p> <p>函数或者方法,接受一个接口类型的参数,返回值也是这个接口类型。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">LimitReader</span><span class="token punctuation">(</span>r Reader<span class="token punctuation">,</span>n <span class="token builtin">int</span><span class="token punctuation">)</span>Reader<span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token operator">&</span>A<span class="token punctuation">}</span> + +<span class="token keyword">type</span> A <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span><span class="token operator">*</span>A<span class="token punctuation">)</span><span class="token function">Reade</span><span class="token punctuation">(</span>p <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span><span class="token punctuation">(</span>n <span class="token builtin">int</span><span class="token punctuation">,</span>err <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">//</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们可以定义类似的内容,来实现链式调用。例如</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token function">CapReader</span><span class="token punctuation">(</span><span class="token function">LimitReader</span><span class="token punctuation">(</span><span class="token function">AReader</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +</code></pre></div><p><em><strong>适配器函数类型:</strong></em></p> <p>将一个普通函数,转化为一个满足接口类型的动态类型:</p> <div class="language-go extra-class"><pre class="language-go"><code>http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":80"</span><span class="token punctuation">,</span>http<span class="token punctuation">.</span><span class="token function">HandlerFunc</span><span class="token punctuation">(</span>greeting<span class="token punctuation">)</span><span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">greeting</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span>r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span><span class="token punctuation">{</span> +<span class="token comment">//</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Handler <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">ServeHTTP</span><span class="token punctuation">(</span>ResponseWriter<span class="token punctuation">,</span><span class="token operator">*</span>Request<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> HandlerFunc <span class="token keyword">func</span><span class="token punctuation">(</span>ResponseWriter<span class="token punctuation">,</span><span class="token operator">*</span>Request<span class="token punctuation">)</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>f HandlerFunc<span class="token punctuation">)</span> <span class="token function">ServeHTTP</span><span class="token punctuation">(</span>w ResponseWriter<span class="token punctuation">,</span>r <span class="token operator">*</span>Request<span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">f</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span>r<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>这就是适配器函数类型。http.HandlerFunc 就是这个适配器函数。</p> <p><em><strong>中间件:</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":80"</span><span class="token punctuation">,</span><span class="token function">aHandler</span><span class="token punctuation">(</span><span class="token function">bHandler</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span><span class="token function">HandlerFunc</span><span class="token punctuation">(</span>greeting<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>具体的实现过程可以参考<a href="/GOFamily/基础/函数方法/3.html">这里</a></p> <p>通常来说,web 编程中的中间件就是这么用的,使用 pipline 的方法,使用修饰器模式 (包裹函数) 然后链式调用,使用 http.HandlerFunc 进行适配器 (也就是类型的转换) 进而实现中间件的功能。</p> <h2 id="接口提供程序的可测试性">接口提供程序的可测试性</h2> <p>主要思想就是从引入一个结构体变成引入一个接口,这样就可以完美的解耦上下的数据。</p> <p>下面有一个场景,使用接口来降低耦合达到可以测试函数的目的。</p> <p>首先我们先看一下原版:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"example.com/s/cache"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">AddA</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> year <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + + cache<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> year<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们发现,整个数据耦合在一起了,如果想替换掉 cache 包,那就是不可能的,下面我们使用接口将 AddA 改造一下。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Ader <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">Add</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> year <span class="token builtin">int</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">AddA</span><span class="token punctuation">(</span>a Ader<span class="token punctuation">,</span>name <span class="token builtin">string</span><span class="token punctuation">,</span>year <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + a<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> year<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>下面我们实现一下这个接口</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> ExampleAd <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>d <span class="token operator">*</span>ExampleAd<span class="token punctuation">)</span><span class="token function">Add</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> year <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + d<span class="token punctuation">.</span>name <span class="token operator">=</span> name + d<span class="token punctuation">.</span>year <span class="token operator">=</span> year + cache<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>d<span class="token punctuation">.</span>name<span class="token punctuation">,</span> d<span class="token punctuation">.</span>year<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>最后的运行</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>ExampleAd<span class="token punctuation">)</span> + +<span class="token function">AddA</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span><span class="token string">"liming"</span><span class="token punctuation">,</span><span class="token number">13</span><span class="token punctuation">)</span> + +</code></pre></div><h2 id="接口的严格和函数的宽松对比">接口的严格和函数的宽松对比</h2> <p>接口的实现是严格的:在实现接口的时候函数需要显示转换 (适配器模式)</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":8080"</span><span class="token punctuation">,</span> http<span class="token punctuation">.</span><span class="token function">HandlerFunc</span><span class="token punctuation">(</span>hi<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Fprintf</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token string">"hi"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>这是正确的用法,不能因为 hi 跟 http.HandlerFunc 底层一样,就认为它俩相等,因为 http.HandlerFunc 实现了接口,并不代表 hi 实现了接口。</p> <p>实际上是不等于的关系,需要显式的转换一下。</p> <p>接下来让我们看一下刚才代码原理:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> b <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">add</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> a <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>a1 a<span class="token punctuation">)</span><span class="token function">add</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span>y <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">a1</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span>y<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> t <span class="token punctuation">(</span>x<span class="token punctuation">,</span>y <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> x<span class="token operator">+</span>y +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> bb b <span class="token operator">=</span> <span class="token function">a</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span> + bb<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>函数的使用是宽松的。当直接使用函数,以及 return 函数的的时候,(其它引用类型也一样:slice,map,func,interface,chan) 是不需要显式转换的,只有非引用类型比如 int,bool string struct ... 需要。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 不需要显示的转换</span> +<span class="token comment">// 或者也可以说:系统自动把这个匿名函数推导为了b类型。</span> + +<span class="token comment">// 函数类型 return </span> +<span class="token keyword">type</span> b <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> + +<span class="token keyword">func</span> <span class="token function">get2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> b <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 函数类型 直接使用</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">string</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token string">"hello"</span> + <span class="token punctuation">}</span> + <span class="token function">get</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> N <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">string</span> + +<span class="token keyword">func</span> <span class="token function">get</span><span class="token punctuation">(</span>n N<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token comment">// 当然你如果显式的转换一下也是没有问题的</span> +<span class="token comment">// 或者说,你人为的帮它推导出了类型是b类型</span> +<span class="token keyword">func</span> <span class="token function">get3</span><span class="token punctuation">(</span><span class="token punctuation">)</span> b <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">b</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>不过除了函数等引用类型之外的非引用类型还是必须显示的转换的</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 整数类型</span> +<span class="token keyword">type</span> a <span class="token builtin">int</span> + +<span class="token keyword">func</span> <span class="token function">get1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a1 a + a1 <span class="token operator">=</span> <span class="token number">12</span> + <span class="token keyword">return</span> <span class="token function">int</span><span class="token punctuation">(</span>a1<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// struct 也需要显示的转换</span> +<span class="token keyword">type</span> b <span class="token keyword">struct</span> <span class="token punctuation">{</span> + i <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> b1 b + +<span class="token keyword">func</span> <span class="token function">get7</span><span class="token punctuation">(</span><span class="token punctuation">)</span>b1<span class="token punctuation">{</span> + <span class="token keyword">return</span> b1<span class="token punctuation">{</span>i<span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 或者是</span> + +<span class="token keyword">func</span> <span class="token function">get8</span><span class="token punctuation">(</span><span class="token punctuation">)</span> b1 <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">b1</span><span class="token punctuation">(</span>b<span class="token punctuation">{</span>i<span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><h2 id="issues">issues</h2> <h3 id="interface-如何判断-nil"><em><strong>interface 如何判断 nil</strong></em></h3> <p>只有类型是 nil + value 是 nil 的接口类型才是 nil,否则它不等于 nil</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">var</span> a1 a + <span class="token comment">// true</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a1 <span class="token operator">==</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> + <span class="token keyword">var</span> b1 <span class="token operator">*</span>b + a1 <span class="token operator">=</span> b1 + <span class="token comment">// false</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a1 <span class="token operator">==</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> a <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> b <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token operator">*</span>b<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><h3 id="论述-nil-error-nil-的原因"><em><strong>论述 “nil error != nil” 的原因</strong></em></h3> <p>nil error 通常可以用这种方法来输出:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token builtin">error</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token operator">*</span>b<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span> + <span class="token comment">//(0x102205988,0x0)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token comment">//false,原因主要是动态类型赋予了这个指针类型具体的类型了,只是没有类型的值而已</span> + <span class="token function">println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> b <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token builtin">error</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>可以发现,nil error 的类型并不是 0x0,而 nil 接口变量是 0X0,0x0,所以这两者并不相同。</p> <h3 id="eface-和-iface-的区别"><em><strong>eface 和 iface 的区别</strong></em></h3> <p>eface 和 iface 的第二个字段相同均存储的是动态类型的地址,然而 eface 的第一个字段保存的是动态类型的元数据,即:_type 字段,而 iface 的第一个字段不仅仅保存了动态类型的元数据 _type,还保存了自己的方法集合的相关数据,以及动态类型实现的方法地址等数据。</p> <h3 id="如何查找-interface-中的方法"><em><strong>如何查找 interface 中的方法</strong></em></h3> <p>除了查找文档,以及查看源码,还可以通过反射来查找 interface 中的方法。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> MyInterface <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">Method2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">//这里就是将nil转化为*MyInterface类型,elem()是一个非常重要的方法, Elem返回接口 v 包含的值或指针 v 指向的值</span> +t <span class="token operator">:=</span> reflect<span class="token punctuation">.</span><span class="token function">TypeOf</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token operator">*</span>MyInterface<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Elem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> t<span class="token punctuation">.</span><span class="token function">NumMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + m <span class="token operator">:=</span> t<span class="token punctuation">.</span><span class="token function">Method</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m<span class="token punctuation">.</span>Name<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>使用反射,判断某个类型是否实现了某个接口:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"io"</span> + <span class="token string">"os"</span> + <span class="token string">"reflect"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// As interface types are only used for static typing, a</span> + <span class="token comment">// common idiom to find the reflection Type for an interface</span> + <span class="token comment">// type Foo is to use a *Foo value.</span> + writerType <span class="token operator">:=</span> reflect<span class="token punctuation">.</span><span class="token function">TypeOf</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token operator">*</span>io<span class="token punctuation">.</span>Writer<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Elem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + fileType <span class="token operator">:=</span> reflect<span class="token punctuation">.</span><span class="token function">TypeOf</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token operator">*</span>os<span class="token punctuation">.</span>File<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>fileType<span class="token punctuation">.</span><span class="token function">Implements</span><span class="token punctuation">(</span>writerType<span class="token punctuation">)</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +</code></pre></div><h3 id="interface-设计的优缺点"><em><strong>interface 设计的优缺点</strong></em></h3> <p>优点:</p> <ul><li>可扩展性:程序拥有横向扩展的能力</li> <li>松耦合:接口可以实现代码的松耦合,因为接口只是定义了一组方法,而不是实现,因此它们可以被许多不同的类型实现,这使得代码更加灵活。</li> <li>可测试性:使用接口编写的代码更容易进行单元测试,因为可以提供模拟对象来模拟接口所定义的方法。这有助于在代码库中提供更高的测试覆盖率。</li> <li>可读性:使用接口编写的代码更容易阅读和理解,因为可以通过接口名称和方法签名来查看类型所提供的功能。</li></ul> <p>缺点:</p> <ul><li>过度设计:如果使用不当,接口可能会导致过度设计,这可能会令代码库变得复杂、难以理解和维护。因此,在设计接口时应该遵循简单性原则,<strong>仅定义必要的方法</strong>。</li> <li>性能损失:使用接口可能会导致一些性能损失,因为在运行时需要进行类型断言和方法查找。虽然这种影响通常很小,但在高性能场景下可能会有所不同。</li> <li>难以理解:对于新手来说,理解接口的概念和使用可能会比较困难,这可能会导致一些代码可读性差的问题。</li></ul> <h3 id="空接口类型和一般类型是从属关系吗"><em><strong>空接口类型和一般类型是从属关系吗?</strong></em></h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>value any<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">var</span> a <span class="token builtin">bool</span> +<span class="token comment">// ❌</span> +<span class="token function">age</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +</code></pre></div><p>上面的代码就表示,<em><strong>空接口类型和一般的类型是平级关系</strong></em>,不能说 any 被所有类型实现了,就说 any 是所有类型的父类,这是错误的。所以当我们的 age 中 value 是 any 类型,那么我们传入的数据的类型也得是 any 类型,不然不就是类型错误了吗</p> <p>那么我们学的,所有类型都实现了空接口这句话如何使用呢,很简单,让任何类型转化为 any 类型即可,任何类型转化为 any 类型之后,就会变成 any 类型,并不是之前它的类型。</p> <p>所以这里的代码应该这么写:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>value any<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">var</span> b <span class="token builtin">bool</span> <span class="token operator">=</span> <span class="token boolean">true</span> +<span class="token keyword">var</span> a any <span class="token operator">=</span> b <span class="token comment">// 所以这里的 true 从 布尔类型 直接变成了any类型 </span> +<span class="token comment">// ✅</span> +<span class="token function">age</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +</code></pre></div><p>即便你直接传入字面量也可以:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">age</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// 这里的 字面量 1 其实就是 any 类型 并不是所谓的int或者uint</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>value any<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="参考资料">参考资料</h2> <ul><li>https://book.douban.com/subject/35720728/ 246 页 - 286 页</li> <li>https://mp.weixin.qq.com/s/6_ygmyd64LP7rlkrOh-kRQ</li> <li>https://github.com/golang/go/blob/master/src/runtime/runtime2.go</li> <li>https://github.com/golang/go/blob/master/src/runtime/type.go</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/interface/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/22/2024, 3:15:39 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/24.edf743ad.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/map/index.html" "b/\345\237\272\347\241\200/map/index.html" new file mode 100644 index 000000000..356b2193e --- /dev/null +++ "b/\345\237\272\347\241\200/map/index.html" @@ -0,0 +1,149 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>map | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/7.5280db48.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>map</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/map/#map-的基本操作" class="sidebar-link">map 的基本操作</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/map/#map-基础知识" class="sidebar-link">map 基础知识</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/map/#map-底层知识" class="sidebar-link">map 底层知识</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/map/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/map/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="map">map</h1> <p>导读:</p> <ul><li>map 的基本操作</li> <li>map 基础知识</li> <li>map 底层知识</li> <li>iussues</li></ul> <h2 id="map-的基本操作">map 的基本操作</h2> <p>因为 go 使用拉链法去构造 go 语言的 map,所以只要内存不被消耗光,map 中的元素是无限的。跟 slice 不同,map 不分 lenth 和 cap,在 make 中<strong>只有</strong>一个位置,这个位置表示的含义就是 cap</p> <p>map 的基础操作</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 声明一个新的map</span> + <span class="token keyword">var</span> m <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">int</span> + <span class="token comment">// 给引用类型map分配底层数据结构</span> + m <span class="token operator">=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// or m = make(map[string]int,100)</span> + <span class="token comment">// 插入数据</span> + m<span class="token punctuation">[</span><span class="token string">"hello"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> + <span class="token keyword">if</span> v<span class="token punctuation">,</span> ok <span class="token operator">:=</span> m<span class="token punctuation">[</span><span class="token string">"hello"</span><span class="token punctuation">]</span><span class="token punctuation">;</span> ok <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 在初始化的时候无法初始化两个一样的key,这个检查是编译器就开始的</span> + m <span class="token operator">=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token string">"a"</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string">"a"</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">}</span> <span class="token comment">// error</span> + <span class="token comment">// 在初始化的时候无法初始化两个一样的key,但是如果是一个变量的话是可以的,</span> + <span class="token comment">// 因为编译器时无法获取变量的值的,所以这种方式通过。</span> + m <span class="token operator">=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span>a<span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span>a<span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">}</span> <span class="token comment">// 这样是正确的。</span> + <span class="token comment">// 遍历数据</span> + <span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> m <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>k<span class="token punctuation">,</span> <span class="token string">":"</span><span class="token punctuation">,</span> v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 删除数据,不存在这个数据不会panic</span> + <span class="token function">delete</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> <span class="token string">"hello"</span><span class="token punctuation">)</span> + <span class="token comment">// 删除 map 所有条目</span> + <span class="token function">clear</span><span class="token punctuation">(</span>m<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +</code></pre></div><h2 id="map-基础知识">map 基础知识</h2> <p>映射的第一步就是把键值转化为哈希值 (通常是一个很大的整数),然后根据哈希值的映射,把 key-value 本体,以及对应的哈希值存储在哈希筒中,go 使用链表法充当哈希筒,当寻找值的时候,通过哈希计算,以及取模映射,先查找到哈希筒,然后使用哈希值的方式去寻找有没有符合的哈希值,如果找到了,那么再使用 key 原来的值二次比较,这一步主要是为了规避哈希碰撞,即:俩 key 算出来的哈希值是一样的这种行为。</p> <p>因为存 <code>==</code> 这种行为,所以 go 语言 map 的键值是有局限的,<strong>不可以是函数类型、字典类型和切片类型</strong>,如果是接口类型,传入的实际类型也不能是函数,字典和切片,例如</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token boolean">_</span> <span class="token operator">=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token comment">// panic</span> + <span class="token string">"1"</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + +<span class="token punctuation">}</span> + +</code></pre></div><p>**虽然,map 的 key 可以设置为接口,但是最好不要这么干,因为会在运行时引入风险,比如上述代码就是风险。同样的,如果 key 是数组类型,亦或者是 struct,参数值都不能是函数,切片和 map。**无论被埋藏的有多深,都不能出现切片,map,函数这几种类型,比如说 <code>[10][2][]string</code>,运行时都会看出来。</p> <p>那么用什么类型的作为 key 值是比较推荐的呢?</p> <p>这里有两个关键词:求哈希的速度,判断相等的速度,基本原理是越简单的类型速度越快,比如 bool,int8,就比 int64 快,因为 int8 单个值只占了一个字节,int64 是 8 个字节,所以越复杂的越慢,比如一个 struct,因为求一个 struct 的哈希值,需要对里面的字段都进行哈希计算,然后合并起来,大大影响了速度,所以优先选用数值类型和指针类型 (因为指针类型也就是一个 16 进制的正整数而已),如果选 string,最好短一些的比较好</p> <p>在内存不爆炸的情况下,map 的 key 是无限量的,随意添加。</p> <p>map 有一个最佳实践是使用形如 <code>value,ok := map[key]</code> 的 “comma OK” 的方法去获取 map 的值,OK 的意义就是为了获得 key 是否存在这个 map 里,因为就算不存在,map 也不会报错或者 Panic,返回的是这个值的零值,比如 int 就返回 0,那如果某一个 key 刚好结果是 0 就说不清了对吧,所以引入了这个 “comma ok” 机制,另外还存在一个不存在也不会 Panic 的操作,就是使用 <code>delete(map,key)</code> 的方法去删除 key 值</p> <p>map 的遍历跟 slice 一样,使用 m := range map 的方法,但是输出的顺序是不固定的,如果想输出稳定的值,可以将 range 改成普通的 for 循环,然后 key 值使用一个切片存储,这样的话,读取 key 值的时候顺序就是固定的了。</p> <h2 id="map-底层知识">map 底层知识</h2> <p>当 map 使用字面量的方式进行初始化的时候,数量小于25时,它会首先启用 make 关键字创建一个 map,然后使用 <code>m["k"] = v</code> 的方式进行初始化,当超过 25 的时候,其实也差不多,它会使用两个切片分别存储 key 和 value,然后使用 <code>m[k] = v</code> 的方式进行初始化,实际上 go 的复合类型使用字面量进行初始化基本上都是这种方式,基本上的流程就是使用关键字创建底层数据,然后使用最简单的方式进行 k-v 赋值,所以你也可以把字面量的赋值当作一种语法糖。</p> <p>map 的语法在运行时会转化为另一套对应关系,这个转化是在编译器搞定的。</p> <div class="language-go extra-class"><pre class="language-go"><code>m <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> m <span class="token operator">:=</span> runtime<span class="token punctuation">.</span><span class="token function">makemap</span><span class="token punctuation">(</span>maptype<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> m<span class="token punctuation">)</span><span class="token comment">// maptype 下文有解释</span> + +v <span class="token operator">:=</span> m<span class="token punctuation">[</span><span class="token string">"hello"</span><span class="token punctuation">]</span> <span class="token operator">-</span><span class="token operator">></span> v <span class="token operator">:=</span> runtime<span class="token punctuation">.</span><span class="token function">mapaccess1</span><span class="token punctuation">(</span>maptype<span class="token punctuation">,</span>m <span class="token punctuation">,</span> <span class="token string">"hello"</span><span class="token punctuation">)</span> <span class="token comment">// 这里实际上引入的是 "hello"的 指针</span> + +v<span class="token punctuation">,</span>ok <span class="token operator">:=</span> m<span class="token punctuation">[</span><span class="token string">"hello"</span><span class="token punctuation">]</span> <span class="token operator">-</span><span class="token operator">></span> v<span class="token punctuation">,</span>ok <span class="token operator">:=</span> runtime<span class="token punctuation">.</span><span class="token function">mapacess2</span><span class="token punctuation">(</span>maptype<span class="token punctuation">,</span>m <span class="token punctuation">,</span> <span class="token string">"hello"</span><span class="token punctuation">)</span> + +m<span class="token punctuation">[</span><span class="token string">"hello"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">12</span> <span class="token operator">-</span><span class="token operator">></span> v <span class="token operator">:=</span> runtime<span class="token punctuation">.</span><span class="token function">mapassign</span><span class="token punctuation">(</span>maptype<span class="token punctuation">,</span>m <span class="token punctuation">,</span> <span class="token string">"hello"</span><span class="token punctuation">)</span> + +<span class="token function">delete</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span><span class="token string">"hello"</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> runtiem<span class="token punctuation">.</span><span class="token function">mapdelete</span><span class="token punctuation">(</span>maptype<span class="token punctuation">,</span>m <span class="token punctuation">,</span> <span class="token string">"hello"</span><span class="token punctuation">)</span> + +</code></pre></div><p>hmap 是一个 struct,这个结构体拥有众多字段,它用来描述这个 map 底层应用具有的所有字段。可以理解为它是描述 map 的头部文件,存储了所有的字段,但是并不存储真实的 body。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> hmap <span class="token keyword">struct</span> <span class="token punctuation">{</span> + count <span class="token builtin">int</span> + flags <span class="token builtin">uint8</span> + B <span class="token builtin">uint8</span> + noverflow <span class="token builtin">uint16</span> + hash0 <span class="token builtin">uint32</span> + buckets unsafe<span class="token punctuation">.</span>Pointer <span class="token comment">// 重点</span> + oldbuckets unsafe<span class="token punctuation">.</span>Pointer + nevacuate <span class="token builtin">uintptr</span> + extra <span class="token operator">*</span>mapextra +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> mapextra <span class="token keyword">struct</span> <span class="token punctuation">{</span> + overflow <span class="token operator">*</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">*</span>bmap + oldoverflow <span class="token operator">*</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">*</span>bmap + nextOverflow <span class="token operator">*</span>bmap +<span class="token punctuation">}</span> + +<span class="token comment">// 这是一个桶本身的数据结构,但是在运行时阶段会重塑这个结构体,添加更多的字段</span> +<span class="token keyword">type</span> bmap <span class="token keyword">struct</span> <span class="token punctuation">{</span> + tophash <span class="token punctuation">[</span>bucketCnt<span class="token punctuation">]</span><span class="token builtin">uint8</span> +<span class="token punctuation">}</span> +<span class="token comment">// 这是添加字段以后的样子</span> +<span class="token comment">// 所以三个数组就完成了数据的存储,也可以避免padding的发生</span> +<span class="token keyword">type</span> bmap <span class="token keyword">struct</span> <span class="token punctuation">{</span> + topbits <span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">]</span><span class="token builtin">uint8</span> + keys <span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">]</span>keytype + values <span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">]</span>valuetype + pad <span class="token builtin">uintptr</span> + overflow <span class="token builtin">uintptr</span> +<span class="token punctuation">}</span> +</code></pre></div><ul><li>count:当前 map 的 value 个数,len 返回的就是这个值</li> <li>flags:map 的状态标志 iterator oldterator hashwriting samesizegrow</li> <li>B:<code>2 ^ B = 桶数量</code></li> <li>noverflow:指的是 overflow 的桶的数量</li> <li>hash0:哈希函数的种子值,用作哈希函数的参数,引入随机性</li> <li>buckets:指向桶数组的指针</li> <li>oldbuckets:在 map 扩容阶段指向前一个桶的指针</li> <li>nevacuate:map 扩容阶段充当扩容进度计数器,所有下标号小于 nevacuate 的桶都是已经完成了数据排空和迁移的操作的</li> <li>extra:【此字段是可选字段】如果有 overflow 的桶出现,该字段保证 overflow 的桶不会被 gc,具体操作就是该字段存储所有指向 overflow 的桶的指针</li></ul> <p>当声明一个 map 的时候,运行时就会为这个 map 具体的变量生成一个实例,上门那个是 map 的描述符号,这里说的这个数据结构是定义这个 map 中所有元信息的。</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">type</span> maptype <span class="token keyword">struct</span> <span class="token punctuation">{</span> + typ _type + key <span class="token operator">*</span>_type + elem <span class="token operator">*</span>_type + bucket <span class="token operator">*</span>_type <span class="token comment">// 表示hash bucket 内部的类型</span> + <span class="token comment">// function for hashing keys (ptr to key, seed) -> hash</span> + hasher <span class="token keyword">func</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span>Pointer<span class="token punctuation">,</span> <span class="token builtin">uintptr</span><span class="token punctuation">)</span> <span class="token builtin">uintptr</span> + keysize <span class="token builtin">uint8</span> <span class="token comment">// size of key slot</span> + elemsize <span class="token builtin">uint8</span> <span class="token comment">// size of elem slot</span> + bucketsize <span class="token builtin">uint16</span> <span class="token comment">// size of bucket</span> + flags <span class="token builtin">uint32</span> +<span class="token punctuation">}</span> +</code></pre></div><p>go 的 map 只有一套 method,只要使用这个 maptype 的具体不同实现就可以满足操作。比如 map[int]int 和 map[int]string,他们都使用 maptype 来定义自己的元信息,但是操作这这个元信息的函数是一个,只要取不同的 typ key 这种指针类型取操作就可以了。</p> <p>存储数据的 body 本体是由一个 <code>类似二维数组</code> + <code>链表</code> 组成的,具体的图像如下:</p> <p><img src="/GOFamily/assets/img/hash.b54950a0.svg" alt=""></p> <p>tophash 区域就是为了寻找 key 和 value 使用空间换时间的原理做的索引,当我们把 hashcode 的高位值逐一比较的时候就可以确定 key 和 value 的位置。</p> <p>key 和 value 都是连续的内存区域,key 和 value 在一个桶中只能存在 8 个,多余的在不满足扩容的情况下就会存储在溢出桶中,寻找 key 和 value 使用 tophash 的位置即可,go 使用分开存储 tophash,key,value 的方式,所以 go 就避免了数据 padding,满足了内存对齐,避免了内存的浪费。需要注意的是,当 key 和 value 大于 128 个字节的时候,存储的就是他们的指针</p> <p>map 的扩容有一个具体的衡量指标,负载因子,当 hmap 中的 <code>count > 负载因子 * 2^B</code> (map 的负载因子为 6.5),或者溢出桶过多的时候,就会扩容。当因为溢出桶太多的时候,创建的新 map 的桶和现有的桶一样,当因为不满足负载因子导致的扩容时,会创建两倍于现有 bucket 的新 bucket,但是旧的桶 data 并不会立刻被迁移到新的 bucket 中,在 map 进行插入和删除的过程中旧的内容会被逐步迁移到新的桶中。原来旧的内容就会被 gc 掉。</p> <p>普通 map 的扩容并不是原子性的,所以 map 的扩容过程会去检查是否已经处于扩容中。</p> <p>当持续向 map 中写入数据,并且删除,然后继续写入删除,这个时候如果没有造成装载因子的超出,就会造成溢出桶过多的情况,这个时候就会造成内存的泄漏,所以会创建一个一样大的 map,存储没有被删除的数据,并且将那些被标记为 delete 的数据进行垃圾回收,没错,你进行 delete 的时候并没有真的 delete,只有 gc 以后才是真的 delete。</p> <p>将旧的数据放在 runtime.hmap 中的 oldbuckets 字段上,然后将新的数据结构放在 buckets 上,溢出桶的设置也是一样的,因为 extra 指向的数据结构也是三个字段,老的,新的,正在使用的。</p> <p>运行时会将一个旧桶的数据分流到两个新的桶子里,但是如果是内存泄漏的等量扩容时,就只会把一个旧桶的数据导入到一个新的桶子里,请注意这里的迁移指的是拷贝,在计数器计算数据已经被分流完全以后,旧的桶和旧的溢出桶的数据就会被 gc 掉</p> <p>因为存在旧桶和新桶,所以在查找数据的时候,会先从旧桶查找数据,如果没有再去新的桶中查找,当我们写入和删除数据的时候,除了写入的新数据到新的桶中,也会把旧的桶中的一部分数据拷贝到新的桶中,当然了不会拷贝全部,这是为了效率考虑的,</p> <h2 id="issues">issues</h2> <p><code>问题一:</code> <strong>map 元素可以取地址吗?</strong></p> <p><a href="/GOFamily/基础/其他内容/#go可寻址类型">不能</a>,map 元素 (例如 ma [“12”]) 属于结果值,所以无法获取地址</p> <p><code>问题二:</code> <strong>map 可以并发读写吗?可以 recover 吗?</strong></p> <p>map 是线程不安全类型,读写得加互斥锁;被 recover 的 Panic 有几项是不能的:</p> <ul><li>数据竞争 (比如:<strong>对 map 进行并发读写</strong>)</li></ul> <blockquote><p>可以通过 go 的编译标记 race 对代码进行检测是否存在数据竞争</p></blockquote> <ul><li>内存不足出现的 Panic</li> <li>死锁出现的 Panic</li></ul> <p><code>问题三:</code> <strong>sync.Map 适合的场景,和 map 加锁的区别</strong></p> <p>sync.Map 在读多写少性能比较好,否则并发性能很差</p> <blockquote><p>有关 sync.Map 的<a href="/GOFamily/工程/go标准库/sync.html#syncmap">详细内容</a></p></blockquote> <p>map 不支持并发的读或者是写 (go1.6 以后就不支持并发的读和写了,之前的版本支持并发的读,但是不支持并发的写),所以 map+锁性能在读多写少和读少写多,读和写一样多的情况下是一样的。</p> <p>最优解是使用多把锁即:分段锁的方式,并发读写,大幅提高性能</p> <p><code>问题四:</code> <strong>在值为 nil 的字典上执行读操作会成功吗,那写操作呢?</strong></p> <p>答案是在值为 nil 的字典写会 Panic,读是没问题的。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">// 结果是int的一个初始值 0 </span> + a<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">// panic</span> +<span class="token punctuation">}</span> + +</code></pre></div><p><code>问题五:</code> <strong>为什么不用向下寻址式?</strong></p> <p>我们知道解决哈希碰撞的问题有向下寻址法,链表法,这是因为哈希函数只能把数据尽可能分布的均匀,如果哈希函数的输出的范围大于输入的范围,这是不现实的,这就要求映射无穷多,这显然不可能,所以必然会有两个不同的 key 算出来的哈希值是相同的,那么如果很多 key 算出的哈希值都是一样的,这就出现了查找效率从 O(1) 下降到了 O(n) 这就是所谓的哈希冲突。</p> <blockquote><p>这里提到的哈希值一样,有可能是后几位一样,也就是部分一样,比如后 9 位相同</p></blockquote> <p>向下寻址法的意思是:依次向下一位去探究是否是要找的哈希对,当然插入的时候也是这,向没有数据的地方插入,所以这种方法必须要使用数组这种结构,而且遍历的时候还得使用循环数组的这种思想 <code>index := hash("author") % array.len</code>,开放寻址法有一个数据指标叫做装载因子,就是说元素的个数/数组长度,一旦装载因子大于 70 %乃至 90 % 基本上就倒退为了 O(n) 的时间复杂度,并且底层是数组的情况下,必须使用连续的内存地址,并且数组长度是有限的,并且大概率会发生内存 padding 的情况,因为 kv 要存储在一起,这就又造成了更大的浪费。</p> <p>总结一下:不使用向下寻址使用拉链法的原因在于,1 可以利用碎片式的内存,2 不用内存 padding 造成浪费 3 原则上链表长度无限,可以无限增加。</p> <p><code>问题六:</code> <strong>map 如何操作真缩容?</strong></p> <p>可以使用 cap 重新生成一个 map,然后使用遍历的方式将老的 map 数据导入到新的小的 map 中,如果你知道数据不会再次增大的情况下是可以这么做的。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://github.com/golang/go/</li> <li>https://blog.csdn.net/EDDYCJY/article/details/120465701</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/map/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/7.5280db48.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/slice/index.html" "b/\345\237\272\347\241\200/slice/index.html" new file mode 100644 index 000000000..6dce766df --- /dev/null +++ "b/\345\237\272\347\241\200/slice/index.html" @@ -0,0 +1,298 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>切片 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/25.831fd7ee.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>切片</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#基本操作" class="sidebar-link">基本操作</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#切片和数组的基本概念" class="sidebar-link">切片和数组的基本概念</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#切片-数组的底层数据结构" class="sidebar-link">切片,数组的底层数据结构</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#append-追加数据的操作" class="sidebar-link">append 追加数据的操作</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#对-append-的优化" class="sidebar-link">对 append 的优化</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#切片的-copy" class="sidebar-link">切片的 copy</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#切片未被合理-gc" class="sidebar-link">切片未被合理 gc</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#切片中的-range-注意事项" class="sidebar-link">切片中的 range 注意事项</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#切片转化为数组" class="sidebar-link">切片转化为数组</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/slice/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="切片">切片</h1> <p>导读:</p> <ul><li>切片的基本操作</li> <li>切片和数组的基本概念</li> <li>切片数组的底层数据结构</li> <li>issues</li></ul> <h2 id="基本操作">基本操作</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 初始化一个切片,设置长度为5,容量为10</span> +a <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token comment">// 获取一个新的切片,遵循左闭右开的原则,取值时并且只看长度不能看容量</span> +<span class="token comment">// b切片,长度为1,容量为8(下文有讲,向右原则)</span> +b<span class="token operator">:=</span> a<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">]</span> +<span class="token comment">// 判断切片长度为0</span> +<span class="token function">len</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span> +<span class="token comment">// append 数据</span> +a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> +<span class="token comment">// 将切片内容清空(element设置为初始值,比如int就是0,string就是"")</span> +<span class="token function">clear</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token comment">//</span> +<span class="token comment">// 将一个切片转为一个数组,注意,新数组不能超过切片的长度,且是数据的深度拷贝</span> +<span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +</code></pre></div><h2 id="切片和数组的基本概念">切片和数组的基本概念</h2> <p>数组是拥有一段连续内存的数据结构,切片是存储了这个数据结构地址,长度以及容量的 struct,这里俗称这种数据结构 (类似切片) 叫引用类型</p> <p>生成数组有两种方式 <code>[3]int</code> 和 <code>[...]int</code> 但是后者其实只是一种语法题,go 会自动推断出容量,因为推断是在编译期搞定的,所以并不会影响数组运行时的效率。</p> <p>不同长度的相同数据类型数组不是一个类型,比如 <code>[1]string{}</code> 和 <code>[2]string{}</code> 就是两个类型</p> <div class="language-go extra-class"><pre class="language-go"><code>t<span class="token punctuation">.</span>Extra <span class="token operator">=</span> <span class="token operator">&</span>Array<span class="token punctuation">{</span>Elem<span class="token punctuation">:</span> elem<span class="token punctuation">,</span> Bound<span class="token punctuation">:</span> bound<span class="token punctuation">}</span> +</code></pre></div><p>这段代码可以解释一下,它来自 go 的源代码,可以看出,生成数组的是一个 struct,那么显而易见了,里面的各项参数都必须一致的情况下 struct 才是一致的,所以,必须类型和容量都满足才行</p> <p>但是切片没有这个烦恼,只要数据类型一致就是一种类型,因为它在编译期间的结构体中只有类型,并没有数量,数量需要在运行时才能确定</p> <p>“切片的切片” 的容量是和 “切片的” 容量是不一致的 (比如这里的 a 和 b),我们来看一个例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">}</span> + b <span class="token operator">:=</span> a<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">5</span><span class="token punctuation">]</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">len</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">cap</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>output:<code>6, 6, 3, 4</code></p> <p>我猜你肯定以为 b 的容量也是 6,但是不是,go 规定,<em><strong>切片只能向右看</strong></em>,不能向左看,我们来说一下上面这个例子,a 就不用说了,a 的底层数据结构数组就是 6 个长度,所以 a 自然长度和容量都是 6,但是 b,它是切片的切片,遵从左闭右开的规则,它的长度是从 index 的 2 到 4,也就是说是 <code>[3 4 5]</code>,自然它的长度就是 3,这毫无疑问,又因为切片遵从 “只能向右看容量” 的规则,它的容量从 index 2 开始往后算,也就是 <code>6 - 2 = 4</code> 所以它的长度是 3 容量是 4</p> <h2 id="切片-数组的底层数据结构">切片,数组的底层数据结构</h2> <p>严格意义来说,go 的切片不存在扩容,如果切片想要的数据量大于底层数组的容量时,那么系统会做两件事,开辟新的数组,给这个数组生成新的切片,之前的数组和切片并没有任何的改变,而且如果没有被引用了,还会被 gc 掉</p> <p>数组在数量小于等于 4 的时候,直接分配在栈内存里,如果大于四且没有逃逸到堆上时,变量就会在静态存储区初始化然后拷贝到栈上</p> <blockquote><p>静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。</p></blockquote> <blockquote><p>栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。任何临时变量都是处于栈区的,包括在 main () 函数中定义的变量</p></blockquote> <blockquote><p>堆区:亦称动态内存分配。程序在运行的时候用 malloc 或 new 申请任意大小的内存,程序员自己负责在适当的时候用 free 或 delete 释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。</p></blockquote> <p><strong>切片的底层数据结构。</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> SliceHeader <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Data <span class="token builtin">uintptr</span> + Len <span class="token builtin">int</span> + Cap <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><p>实际上,切片就是一个 struct (struct 是 go 的基本组成单位,实际上很多东西都可以使用结构体来表达,比如接口底层也是结构体)</p> <p>当我们使用字面量的方式去生成一个 slice 的时候,会在编译期间搞定,但是如果使用 make 去生成一个切片时,就会在运行时生成一个切片,在运行时生成切片,不仅仅会进行边界检查,而且还会看是否逃逸到堆上。</p> <p>**slice 的扩容规律,**如果期望容量大于当前容量的两倍就会使用期望容量,如果当前切片的长度小于 <a href="https://github.com/golang/go/blob/fd0ffedae2dd9e202efc2dd7f7937baa08600d26/src/runtime/slice.go#L178" target="_blank" rel="noopener noreferrer">256<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 就会将容量 x2, +如果当前切片的长度大于 256 就会逐步 (按照这个公式 <code>cap += (cap + 768) / 4</code>) 从 2 倍的倍增速率调整到 1.25 的倍率,增加到新容量大于期望容量。不过这还不是全部</p> <p>slice 扩容具体操作。扩容的时候并不是严格按照这个规律来的,这只是一个大致的规律,实际运行的时候会进行 <code>padding</code> (填充),也就是内存的对齐,将容量字节数尽量靠近 2 的次方,比如说期望的新容量是 5,这时期望分配的内存大小为 40 字节 (具体看一个位置多少个字节,这里是按照 8 举例子),运行时会向上取整内存的大小到 48 字节 (取整到 go 的<a href="https://github.com/golang/go/blob/b634f5d97a6e65f19057c00ed2095a1a872c7fa8/src/runtime/sizeclasses.go#L84" target="_blank" rel="noopener noreferrer">推荐值<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>),所以新切片的容量是 <code>48 / 8 = 6</code></p> <p>我们知道当切片扩容的时候,重新分配底层数组是会牵涉到内存的复制的,因此尽量减少内存复制就是我们要追求的事情了,当我们往后面追加数据的时候,如果可以提前预估要使用的容量,那么就不牵涉到多次的内存复制了</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">const</span> sliceSize <span class="token operator">=</span> <span class="token number">1000</span> + m <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> sliceSize<span class="token punctuation">)</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> sliceSize<span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + m <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> i<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +</code></pre></div><p><strong>slice 的浅拷贝</strong> <code>s := make([]int, 3,12)</code>,<code>s1 := s[1:2]</code>,那么 s1 和 s 是浅层拷贝,他们拥有一个共同的底层数组,更改任意一个另一个的值也会发生改变。</p> <p>**slice 的深拷贝。**copy 内置函数会将源内存 data 直接一次性拷贝,所以慎用,很消耗资源。</p> <p><strong>slice 的边界检查消除以及优化。<strong>go 在编译数组或者切片的时候都会在编译期间进行边界越界的检查,不过也只是普通的检查,比如直接使用整数或者常量访问数组,对于</strong>用变量去获取切片数组的情况</strong>根本就检查不了,这个时候 go 的运行时就会起作用,发出 Panic,那么边界检查有什么缺点呢?就是会降低运行时的效率,当然这里指的是运行时的检查,因为编译器的检查首先本身能力有限,其次只会降低编译速度而已,所以 go 从 1.17 开始,就开始支持了边界检查的消除,为了就是在证明不会越界的情况下,提高代码的运行效率,下面我们看一下取消运行时边界检查的例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 这种不能确定,所以还是会检查</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> a <span class="token punctuation">{</span> + a<span class="token punctuation">[</span>i<span class="token punctuation">]</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 这样,就可以消除边界检查,因为运行时确定不可能出现问题</span> +<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">--</span> <span class="token punctuation">{</span> + <span class="token boolean">_</span> <span class="token operator">=</span> a<span class="token punctuation">[</span>i<span class="token punctuation">]</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 或者这样也可以</span> + +<span class="token keyword">func</span> <span class="token function">A</span><span class="token punctuation">(</span>i <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> b <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">if</span> <span class="token function">len</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">256</span> <span class="token punctuation">{</span> + i <span class="token operator">=</span> i<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">256</span><span class="token punctuation">]</span> <span class="token comment">// 这里就是给运行时一个暗示,表示i的最大index不会超过 256</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> b <span class="token punctuation">{</span> <span class="token comment">// v的最大值也不会超过 256(byte最大值 255)</span> + <span class="token boolean">_</span> <span class="token operator">=</span> i<span class="token punctuation">[</span>v<span class="token punctuation">]</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +</code></pre></div><h2 id="append-追加数据的操作">append 追加数据的操作</h2> <p>前文我们知道 slice 会发生扩容情况,那么这种扩容一般是在 append 操作的时候发生的,通常来说操作是这样的:</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// 注意,append操作是追加的意思,所以这里不是 100,而是0001</span> +<span class="token comment">// 0001</span> +</code></pre></div><p>当 slice 底层数组不够 append 的时候,就会发生扩容:</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span> +a<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> +a<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token operator">=</span> <span class="token number">2</span> +a<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">3</span> +<span class="token comment">// 这里还是相同的数组,因为容量没有超过</span> +a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span> + +<span class="token comment">// 这里的a 指向的就不同于之前的那个数组了。</span> +<span class="token comment">//底层就变成了一个新的数组 1 2 3 4 5 0 0 0 ;fmt.Println(cap(a)) : 8</span> +a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span> +</code></pre></div><p>同样底层数组的不同区域的切片 append 的时候经常会发生意想不到的结果:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span> + a1 <span class="token operator">:=</span> a<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>a1<span class="token punctuation">)</span> + a1 <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a1<span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>a1<span class="token punctuation">)</span> + a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>a1<span class="token punctuation">)</span> + a1 <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a1<span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>a1<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +<span class="token comment">//[0 0 0] [0]</span> +<span class="token comment">// [0 0 2] [0 2]</span> +<span class="token comment">// [0 0 2 4] [0 2]</span> +<span class="token comment">// [0 0 2 5] [0 2 5]</span> +</code></pre></div><p>从上面的案例可以说明,首先,a1 a 指向同一个底层数组,其次,a1 和 a 在 append 的时候,都是在各自切片的后面添加数据,他们会互相影响,在写代码的时候容易出现 bug</p> <h3 id="对-append-的优化">对 append 的优化</h3> <p>对一个未知大小的切片进行 append 操作的最佳选择是初始化一个 nil 切片:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span> +s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span><span class="token string">"a"</span><span class="token punctuation">)</span> +</code></pre></div><p>s 在初始化的时候没有分配内存,在 append 的时候分配了一个底层数组,下面这种方式就会浪费一次内存分配</p> <div class="language-go extra-class"><pre class="language-go"><code>s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span> +s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span><span class="token string">"a"</span><span class="token punctuation">)</span> +</code></pre></div><p>这种方式,在 s 初始化的时候会给予它一个底层长度为 0 的数组,即便长度为 0,go 并未分配实际的内存空间,但是仍然浪费了执行片段,append 的时候还要再次分配底层数组。</p> <p>不过使用 make 的方式比较适合<strong>已知容量</strong>的场景。</p> <p>除此之外还有两种初始化的方式:</p> <ul><li><code>[]int(nil)</code></li> <li><code>[]string("a")</code></li></ul> <p>我们知道 <code>[]int{}</code> 和 <code>var s []int</code> 是两种皆然不同的初始化方式,虽然都是 0 长度,但是前者不是 nil,后者是 nil,不过 append 的时候不会介意是否是 nil,这也提醒了我们判断是否是空切片的方式,使用 len == 0 才是正确的方法,“是否等于 nil” 是错误用法。</p> <p><code>[]string(nil)</code> 的用法非常少见,通常来说,使用场景就下面这么一个:</p> <div class="language-go extra-class"><pre class="language-go"><code>src <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">,</span><span class="token string">"there"</span><span class="token punctuation">,</span><span class="token string">"!"</span><span class="token punctuation">)</span> +s <span class="token operator">:=</span> <span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">string</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">,</span> src<span class="token operator">...</span><span class="token punctuation">)</span> +</code></pre></div><p>我们这里使用一个值为 nil 的切片主要是为了符合类型的需求。</p> <h2 id="切片的-copy">切片的 copy</h2> <p>copy 是 go 语言的内置函数,全局使用,<code>copy(a,b []Type)</code>,copy 是深度拷贝,它将后者的数据完全拷贝给前者。</p> <p>要注意的是,将要被复制的元素能复制的量取决于前者的 length</p> <p>比如下面这种情况,被复制的元素就是 0,但是并不会 panic</p> <div class="language-go extra-class"><pre class="language-go"><code>src <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +<span class="token keyword">var</span> d <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> +<span class="token comment">// []</span> +<span class="token function">copy</span><span class="token punctuation">(</span>d<span class="token punctuation">,</span>src<span class="token punctuation">)</span> +</code></pre></div><p>一般来说,我们会使用相同的 length:</p> <div class="language-go extra-class"><pre class="language-go"><code>src <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +d <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token function">len</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token function">copy</span><span class="token punctuation">(</span>d<span class="token punctuation">,</span>src<span class="token punctuation">)</span> +</code></pre></div><p>或者直接使用 append 也能做到 copy</p> <div class="language-go extra-class"><pre class="language-go"><code>src <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +d <span class="token operator">:=</span> <span class="token function">append</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">,</span>src<span class="token operator">...</span><span class="token punctuation">)</span> +</code></pre></div><h2 id="切片未被合理-gc">切片未被合理 gc</h2> <p>当切片完成自己的使命时,我们希望它可以正常的被 gc 掉,通常来说,我们可以手动使用 <code>runtime.GC()</code> 来强制系统进行垃圾回收,下面我们看一种 bug,这种 bug 出现以后,我们手动的垃圾回收将会无效</p> <div class="language-go extra-class"><pre class="language-go"><code>s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token comment">// 此处原本的想法是只取两个数据</span> +<span class="token comment">// 但是造成了10个数据都不能垃圾回收,8个浪费</span> +b <span class="token operator">:=</span> s<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">:</span><span class="token punctuation">]</span> +runtime<span class="token punctuation">.</span><span class="token function">GC</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +runtime<span class="token punctuation">.</span><span class="token function">KeepLive</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> +</code></pre></div><p>本来我们期望 s 底层数组可以被垃圾回收,但是 b 也指向这个相同的底层数组,那么这个垃圾回收就无法执行。</p> <p>正确的方法是</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token function">copy</span><span class="token punctuation">(</span>res<span class="token punctuation">,</span>s<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token keyword">return</span> res +</code></pre></div><p>当然了,我们深究 gc 的本质就会发现,三色 gc 算法是看某个对象是否还被变量持有,是否可以通过变量的方式追踪到,来作为回收标准的,要么我们像前者一样,不再让变量持有值,要么将值变成 nil 即可:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A <span class="token keyword">struct</span> <span class="token punctuation">{</span> + v <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span> +<span class="token punctuation">}</span> +s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span>A<span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token comment">// 此处原本的想法是只取两个数据</span> +<span class="token comment">// 但是造成了10个数据都不能垃圾回收,8个浪费</span> +<span class="token keyword">for</span> i<span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token number">8</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token comment">// 这里是手动的将前八个数据丢弃掉</span> + s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>v <span class="token operator">=</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +b <span class="token operator">:=</span> s<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">:</span><span class="token punctuation">]</span> +runtime<span class="token punctuation">.</span><span class="token function">GC</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +runtime<span class="token punctuation">.</span><span class="token function">KeepLive</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> +</code></pre></div><p>这种多切片指向底层数组而造成的无法正常垃圾回收的行为很常见。在工作中还是应该检查好自己的代码,避免这种行为的发生。</p> <h2 id="切片中的-range-注意事项">切片中的 range 注意事项</h2> <p>range 时,我们直接修改返回的值是不会生效的,因为返回的值并不是原始的数据,而是数据的复制。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + result <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>Student<span class="token punctuation">{</span> + <span class="token punctuation">{</span><span class="token number">12</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span><span class="token number">13</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> student <span class="token operator">:=</span> <span class="token keyword">range</span> result <span class="token punctuation">{</span> + student<span class="token punctuation">.</span>year<span class="token operator">++</span> + <span class="token punctuation">}</span> + <span class="token comment">// 12 13</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>也就是说,这里的 <code>student :=</code> student 的改变不会影响 result 中的任何数据,除非这里的 <code>[]Student</code> 是 <code>[]*Student</code></p> <p>下面我们演示一下,正确的在 range 时的操作方式:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + result <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>Student<span class="token punctuation">{</span> + <span class="token punctuation">{</span><span class="token number">12</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span><span class="token number">13</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> result <span class="token punctuation">{</span> + result<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>year<span class="token operator">++</span> + <span class="token punctuation">}</span> + <span class="token comment">// 13 14</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>正确的方式就是直接使用 result 本身进行操作,就可以真正的去改变 result 了。</p> <p>并且,在 range 的时候,range 后面的数据其实也是复制品,也就是说,这里的 <code>:= range result</code> result 也是复制品,原有的 result 如何变化都不会影响 range 结果。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 这里的 result</span> +<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> result <span class="token punctuation">{</span> + <span class="token comment">// 跟这里面的result不是一个值,</span> + <span class="token comment">//只有里面的result才是跟外面的result是一个值</span> + result<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>year<span class="token operator">++</span> + <span class="token punctuation">}</span> +</code></pre></div><p>下面我们再看一个案例:</p> <div class="language-go extra-class"><pre class="language-go"><code>s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">)</span> +<span class="token keyword">for</span> <span class="token keyword">range</span> s <span class="token punctuation">{</span> + s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// [0 0 0 10 10 10]</span> +</code></pre></div><p>你猜结果是多少呢?是会一直 range 吗?因为数据在一直添加啊,nonono,只会 range 3 次而已,因为 range 后面的 s 是固定不变的,它本身只是原有 s 的复制品而已。</p> <p>综上:</p> <ul><li>range 后面的数据是原有数据的复制品</li> <li>range 前面的 k v 更是后面复制品输出数据的复制品</li> <li>range 里面的数据才是跟外面的数据保持一致</li></ul> <p>第三点很关键,range 后面的数据跟 range 里面的数据并不是一个:</p> <div class="language-go extra-class"><pre class="language-go"><code>s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">)</span> +<span class="token comment">// 这里的s</span> +<span class="token keyword">for</span> <span class="token keyword">range</span> s <span class="token punctuation">{</span> + <span class="token comment">// 这里的s 跟外面保持一致</span> + s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><strong>不能</strong>把 range 当做 function 来类比:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">range</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token keyword">range</span><span class="token punctuation">(</span>s any<span class="token punctuation">)</span><span class="token punctuation">(</span>k<span class="token punctuation">,</span>v any<span class="token punctuation">)</span><span class="token punctuation">{</span> + s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">++</span> +<span class="token punctuation">}</span> +</code></pre></div><p>如果是函数,函数体的变量 s 和函数内部的 s 就是同一个,显然,range 中,range 后面的 s 和 range 里面的 s 并不是同一个。</p> <h2 id="切片转化为数组">切片转化为数组</h2> <p>在 go 1.20 版本中,新添加了切片转为数组或者数组指针的操作,具体实现如下:</p> <div class="language-go extra-class"><pre class="language-go"><code>s<span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span> +a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +a1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +a2 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +a3 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +</code></pre></div><p><code>a[0] == s[0]</code>,也就是说,转化出来的就是底层的那个数组的复制,<strong>注意并不是底层数组本身</strong>,不过这里相同切片转化的数组指针是指向这个切片的底层数组的,所以 a2 和 a3,s 是公用一个数组的,如果更改了 a2[0],那么 a3,s 也是会发生改变的,a1 a 已经是数据的复制了,他们有了分别的生活了。</p> <p>下面我们看一个具体的代码演示:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + a1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + a2 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + a3 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> a<span class="token punctuation">,</span> a1<span class="token punctuation">,</span> a2<span class="token punctuation">,</span> a3<span class="token punctuation">)</span> + a<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> a<span class="token punctuation">,</span> a1<span class="token punctuation">,</span> a2<span class="token punctuation">,</span> a3<span class="token punctuation">)</span> + a2<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">12</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> a<span class="token punctuation">,</span> a1<span class="token punctuation">,</span> a2<span class="token punctuation">,</span> a3<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">//[0 0] [0] [0 0] &[0] &[0 0]</span> +<span class="token comment">//[0 0] [1] [0 0] &[0] &[0 0]</span> +<span class="token comment">//[12 0] [1] [0 0] &[12] &[12 0]</span> + +<span class="token comment">// 可以证明确实是指向同样的底层数据</span> +fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>a2<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token operator">&</span>a3<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token operator">&</span>s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token comment">// 0x1400012a020 0x1400012a020 0x1400012a020</span> +</code></pre></div><p>当一个切片转化为一个数组的时候,数组的长度不能大于切片的长度,而不是容量</p> <p>那么下面这种代码就会出现 bug</p> <div class="language-go extra-class"><pre class="language-go"><code>s<span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span> +a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +a1 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token comment">// panic: cannot convert slice with length 2 to array or pointer to array with length 3</span> +</code></pre></div><p>下面我们看一下转化后的特殊值</p> <div class="language-go extra-class"><pre class="language-go"><code>s<span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">)</span> +a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token comment">// []</span> +a1 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token comment">// &[]</span> + +<span class="token comment">//将非空切片转为长度为 0 的数组,得到的指针不是 nil,比如 b2</span> +<span class="token keyword">var</span> j <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> +b <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span> <span class="token comment">// panic</span> +b1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token comment">// [] </span> +b2 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token comment">// <nil></span> +b3 <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span><span class="token comment">// panic</span> + +<span class="token comment">//将 nil 切片转为长度为 0 的数组,得到的指针为 nil</span> +c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span> +u <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token comment">//&[] </span> +u1 <span class="token operator">:=</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token function">int</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> <span class="token comment">// []</span> +</code></pre></div><h2 id="issues">issues</h2> <p><code>问题一:</code> <em><strong>如果有多个切片指向了同一个底层数组,那么你认为应该注意些什么</strong></em></p> <p>一定要避免 a 切片的更改造成的底层数据的改变,对 b 切片的结果造成影响,因为它们指向同一个数据底层</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +b <span class="token operator">:=</span> a<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span> + +a<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">4</span> + +fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span> +</code></pre></div><p><code>[1 2 4] [1 2 4]</code></p> <p><code>问题二:</code> <em><strong>怎样沿用扩容的思想对切片进行 “缩容</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code>a<span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +b <span class="token operator">:=</span> a<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token comment">// b = [1,2]</span> + +<span class="token comment">// 如果确定a的数据多余的没有任何的用途了</span> +nb <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span> +<span class="token function">copy</span><span class="token punctuation">(</span>nb<span class="token punctuation">,</span>b<span class="token punctuation">)</span> +</code></pre></div><p>所谓扩容的思想,就是创造一个新的底层数据</p> <p><code>问题三:</code> <em><strong>nil 切片和空切片 (比如 []int {}) 的区别</strong></em></p> <p>最大的区别就是指向的底层数组的地址不一样</p> <ul><li>nil 压根就没有地址</li> <li>空切片是有正儿八经的地址的,<strong>只不过这个地址指向的数组不占用空间</strong>,这个数组叫做 zero 数组,并且所有的空切片指向同一个数组就是这个 zero 数组,也可以说在 go 里,zero 数组是唯一的存在,它存在的目的就是为了空切片</li></ul> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span><span class="token function">Sizeof</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 0</span> +</code></pre></div><p>空的数据是不占内存空间的,还有类似的,比如空的 struct 也是一样的</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span><span class="token function">Sizeof</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 0</span> +</code></pre></div><p><code>问题四:</code> <em><strong>slice 和 array 的不同使用场景是什么</strong></em></p> <p>如果数据是固定的,可以用数组,否则还是切片更加灵活,实际上绝大多数情况下还是切片更好用</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://www.jianshu.com/p/9ea2fba64f06</li> <li>https://chai2010.cn/advanced-go-programming-book</li> <li>https://blog.csdn.net/kevin_tech/article/details/122138489</li> <li>https://blog.csdn.net/weixin_39927993/article/details/112099007</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/slice/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/25.831fd7ee.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/string/index.html" "b/\345\237\272\347\241\200/string/index.html" new file mode 100644 index 000000000..7a12fd591 --- /dev/null +++ "b/\345\237\272\347\241\200/string/index.html" @@ -0,0 +1,256 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>字符串 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/26.83ccb127.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>字符串</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#字符串的基础操作" class="sidebar-link">字符串的基础操作</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#字符串的基础知识" class="sidebar-link">字符串的基础知识</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#字符串的高效构造" class="sidebar-link">字符串的高效构造</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#字符串的底层" class="sidebar-link">字符串的底层</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#数据结构" class="sidebar-link">数据结构</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#类型转换" class="sidebar-link">类型转换</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/string/#for-range-字符串" class="sidebar-link">for-range 字符串</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="字符串">字符串</h1> <ul><li>字符串的基础操作</li> <li>字符串的基础知识</li> <li>字符串的底层操作</li></ul> <h2 id="字符串的基础操作">字符串的基础操作</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 声明</span> +<span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token string">"你好"</span><span class="token comment">// s := "你好"</span> +<span class="token comment">//读取</span> +fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token comment">// 转化为unicode码点存储,单个字符, 例如'你',也是使用的rune来存储的,、</span> +<span class="token comment">// 不过string底层本身是[]byte的方式存储的</span> +<span class="token boolean">_</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token comment">// 转化为字符存储</span> +<span class="token boolean">_</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token comment">// 字符的简单拼接</span> +s1 <span class="token operator">:=</span> <span class="token string">"你"</span> +s2 <span class="token operator">:=</span> <span class="token string">"好"</span> +s <span class="token operator">:=</span> s1 <span class="token operator">+</span> s2 +<span class="token comment">//多行字符</span> +s <span class="token operator">=</span> <span class="token string">` +你好 + +世界 +`</span> +<span class="token comment">// 多行字符也通常用在屏蔽 ""作用的地方</span> +s<span class="token operator">=</span> <span class="token string">`{"user": "shgopher", "links": ["https://github.com/shgopher"]}`</span> +</code></pre></div><h2 id="字符串的基础知识">字符串的基础知识</h2> <ul><li>字符串的数据是只读数据不可更改</li> <li>字符串的零值是可用的,<code>var s string</code> 结果是 <code>""</code></li> <li>获取字符串长度的操作时间复杂度是 <code>O(1)</code> 因为它是不可变的只读数据,所以长度被保存在了字段中,直接读这个字段即可</li> <li>字符串可以通过 <code>+</code>,<code>+=</code> 进行拼接</li> <li>字符串可以使用 <code>> < >= <= == =!</code> 运算符,比较的顺序是: +<ul><li>先比较长度</li> <li>再比较是否是指向一块内存地址</li> <li>如果都满足再比较具体数据</li></ul></li> <li>字符串原生支持 unicode 字符集,并且 go 默认支持 utf-8 的编码算法 +<ul><li>rune 存储 unicode 的一个码点</li> <li>byte 存储真实的底层字符 (比如 utf-8,三个字符来保存一个中文字符,rune 就只显示一个字符,byte 会显示三个)</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token string">"中"</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// output: [228 184 173] [20013]</span> +</code></pre></div></li> <li>使用``原生支持多行字符</li></ul> <h2 id="字符串的高效构造">字符串的高效构造</h2> <p>字符串的构造有以下这么几种</p> <ul><li>最常规的使用 <code>+</code> 和 <code>+=</code></li> <li>fmt.Sprintf</li> <li>strings.Join</li> <li>strings.Builder</li> <li>bytes.Buffer</li></ul> <p>让我们分别给出代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//最常规的使用`+`和 `+=`</span> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s1 <span class="token operator">:=</span> <span class="token string">"中"</span> + s2 <span class="token operator">:=</span> <span class="token string">"国"</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>s1 <span class="token operator">+</span> s2<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//fmt.Sprintf</span> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s1 <span class="token operator">:=</span> <span class="token string">"中"</span> + s2 <span class="token operator">:=</span> <span class="token string">"国"</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%s%s"</span><span class="token punctuation">,</span> s1<span class="token punctuation">,</span> s2<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//strings.Join</span> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"strings"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s1 <span class="token operator">:=</span> <span class="token string">"中"</span> + s2 <span class="token operator">:=</span> <span class="token string">"国"</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>strings<span class="token punctuation">.</span><span class="token function">Join</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">{</span>s1<span class="token punctuation">,</span> s2<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//strings.Builder</span> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"strings"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> b strings<span class="token punctuation">.</span>Builder + b<span class="token punctuation">.</span><span class="token function">Grow</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">// 给出猜测最终的string长度</span> + s1 <span class="token operator">:=</span> <span class="token string">"中"</span> + s2 <span class="token operator">:=</span> <span class="token string">"国"</span> + b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span> + b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>b<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//bytes.Buffer</span> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"bytes"</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> b bytes<span class="token punctuation">.</span>Buffer + s1 <span class="token operator">:=</span> <span class="token string">"中"</span> + s2 <span class="token operator">:=</span> <span class="token string">"国"</span> + b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span> + b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>s2<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>b<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>根据 benchmark,得出以下结论:</p> <ul><li>带有预估 string 长度的 strings.Builder 最快</li> <li>带有预估的 bytes.Buffer 和 strings.Join 性能第二档次</li> <li>没有预估长度的 strings.Builder 和 bytes.Buffer 以及 + += 第三档次</li> <li>fmt.Sprintf 最差劲</li></ul> <p>那么:</p> <ul><li>当能给出预估的情况下,优选使用 strings.Builder</li> <li>strings.Joins 性能最稳,没有预估的情况下,使用这个稳定啊 (实际上这个 join 就是调用了 string.Builder,并且给出了预估长度)</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Join</span><span class="token punctuation">(</span>elems <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">,</span> sep <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> +<span class="token keyword">switch</span> <span class="token function">len</span><span class="token punctuation">(</span>elems<span class="token punctuation">)</span> <span class="token punctuation">{</span> +<span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token string">""</span> +<span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> elems<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> +<span class="token punctuation">}</span> +<span class="token comment">// 这里是搞定string长度的</span> +n <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>sep<span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token function">len</span><span class="token punctuation">(</span>elems<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> +<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token function">len</span><span class="token punctuation">(</span>elems<span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + n <span class="token operator">+=</span> <span class="token function">len</span><span class="token punctuation">(</span>elems<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// 使用了builder</span> +<span class="token keyword">var</span> b Builder +b<span class="token punctuation">.</span><span class="token function">Grow</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span> +b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>elems<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> s <span class="token operator">:=</span> <span class="token keyword">range</span> elems<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span> <span class="token punctuation">{</span> + b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>sep<span class="token punctuation">)</span> + b<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">return</span> b<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><ul><li>操作符 + += 最直观,并且在字符短,以及编译器知道连接的字符串个数时,这种方式还能得到编译器的优化</li> <li>fmt.Sprintf 用在多类型组成字符串的时候是最好的,虽然它效率很差,但是人家能力强啊</li></ul> <p><strong>综上所诉</strong>:优先选 <code>strings.Join</code></p> <h2 id="字符串的底层">字符串的底层</h2> <h3 id="数据结构">数据结构</h3> <p>一个 string 的底层数据类似一个 slice,只不过这个 slice 是只读数据,它的底层不同于一般的 slice,是一个特别的 struct</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> stringStruct <span class="token keyword">struct</span><span class="token punctuation">{</span> + str unsafe<span class="token punctuation">.</span>Pointer + <span class="token builtin">len</span> <span class="token builtin">int</span> + <span class="token comment">// 注意常规的slice这里是有一个cap的</span> + <span class="token comment">//但是string因为是只读的关系只有length的含义</span> +<span class="token punctuation">}</span> +</code></pre></div><p><code>runtime/string.go</code> 中出现了这么一段代码</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// rawstring allocates storage for a new string. The returned</span> +<span class="token comment">// string and byte slice both refer to the same storage.</span> +<span class="token comment">// The storage is not zeroed. Callers should use</span> +<span class="token comment">// b to set the string contents and then drop b.</span> +<span class="token keyword">func</span> <span class="token function">rawstring</span><span class="token punctuation">(</span>size <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">,</span> b <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + p <span class="token operator">:=</span> <span class="token function">mallocgc</span><span class="token punctuation">(</span><span class="token function">uintptr</span><span class="token punctuation">(</span>size<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span> + + <span class="token function">stringStructOf</span><span class="token punctuation">(</span><span class="token operator">&</span>s<span class="token punctuation">)</span><span class="token punctuation">.</span>str <span class="token operator">=</span> p + <span class="token function">stringStructOf</span><span class="token punctuation">(</span><span class="token operator">&</span>s<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token builtin">len</span> <span class="token operator">=</span> size + + <span class="token operator">*</span><span class="token punctuation">(</span><span class="token operator">*</span>slice<span class="token punctuation">)</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span><span class="token operator">&</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">=</span> slice<span class="token punctuation">{</span>p<span class="token punctuation">,</span> size<span class="token punctuation">,</span> size<span class="token punctuation">}</span> + + <span class="token keyword">return</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们仔细看注释的这句话,当一个 string 导入数据的时候,运行时会给定一个辅助的 slice,用来辅助的导入数据,然后当数据导入完毕之后,这个 slice 的描述符,也就是这个代表了这个 slice 的 struct 就会被删除掉,所以说其实 string 不能跟 slice 划上等号,也不能简简单单的说它是一个只读的 slice,实际上它压根就不是 slice,slice 在生成 string 的过程中只是起到了辅助作用</p> <h3 id="类型转换">类型转换</h3> <p>字符串进行的转化只能是 string 和 <code>[]rune</code> or <code>[]byte</code> 互相转换</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token string">"【你好】"</span> + b <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + c <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">rune</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token comment">// []byte 是可以直接使用fmt包直接输出为string的,但是[]rune需要显式进行转换。</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"现在我们打印出原始数据%s,打印出[]byte转化后的数据%v,打印出[]rune转化后的数据%v,打印出逆转的数据%s 和 %s,"</span><span class="token punctuation">,</span> a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> c<span class="token punctuation">,</span> b<span class="token punctuation">,</span> <span class="token function">string</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>上文我们提到的字符串的构造,例如删除一个字符,追加一个字符,都无一例外需要改变这个 string,那么很明显任何数据的处理都是<strong>拷贝</strong>的数据,原数据是不会有任何变化的,所以这就告诫我们字符串的处理要小心非常有可能浪费大量的内存。</p> <p>我们看一下底层的转换代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span> tmpStringBufSize <span class="token operator">=</span> <span class="token number">32</span> + +<span class="token keyword">type</span> tmpBuf <span class="token punctuation">[</span>tmpStringBufSize<span class="token punctuation">]</span><span class="token builtin">byte</span> + +<span class="token keyword">func</span> <span class="token function">stringtoslicebyte</span><span class="token punctuation">(</span>buf <span class="token operator">*</span>tmpBuf<span class="token punctuation">,</span> s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> b <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span> + <span class="token keyword">if</span> buf <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token operator">&&</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token operator"><=</span> <span class="token function">len</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token operator">*</span>buf <span class="token operator">=</span> tmpBuf<span class="token punctuation">{</span><span class="token punctuation">}</span> + b <span class="token operator">=</span> buf<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">]</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + b <span class="token operator">=</span> <span class="token function">rawbyteslice</span><span class="token punctuation">(</span><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 这里就发生了拷贝</span> + <span class="token function">copy</span><span class="token punctuation">(</span>b<span class="token punctuation">,</span> s<span class="token punctuation">)</span> + <span class="token keyword">return</span> b +<span class="token punctuation">}</span> + +</code></pre></div><p>于此同时我们也能发现 string 的底层的真实存储是 <code>[]byte</code> 不是 <code>[]rune</code></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token string">"【你好】"</span> + <span class="token keyword">var</span> b <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span> + <span class="token function">copy</span><span class="token punctuation">(</span>b<span class="token punctuation">,</span> a<span class="token punctuation">)</span> + <span class="token keyword">var</span> c <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">rune</span> + <span class="token comment">// invalid argument: arguments to copy c (variable of type []rune) </span> + <span class="token comment">// and a (variable of type string) have different element types rune and byte</span> + <span class="token function">copy</span><span class="token punctuation">(</span>c<span class="token punctuation">,</span> a<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">,</span> c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>go 为某几种特别的情况优化了 string 和 slice 转换必须拷贝的情况,意思就是不需要拷贝就让这个 string 直接使用这个 slice 的底层,但是有个规定,只要是 slice 发生了改变,那么这个 string 立即失效</p> <p><code>b = []int{1,2}</code></p> <ul><li>string(b) 用在 map 的 key 中 <code>ma[string(b)]++</code></li> <li>string(b) 在字符串的拼接句子中 “a” + string(b)</li> <li>for-range 中的 string 到[]byte 的转换</li></ul> <h2 id="for-range-字符串">for-range 字符串</h2> <p>因为对一个字符串使用 range 的时候,go 默认使用 utf8 的编码方式,但是 string 的底层是[]byte 的存储方式,所以直接 range 的时候,将这个时候的字符转化为字符就会发生乱码的情况</p> <div class="language-go extra-class"><pre class="language-go"><code>s <span class="token operator">:=</span> <span class="token string">"你好"</span> +<span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> s <span class="token punctuation">{</span> + <span class="token comment">// äå </span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"%c"</span><span class="token punctuation">,</span>s<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>解决方法有两种:</p> <ol><li>直接获取 value 值</li></ol> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s <span class="token operator">:=</span> <span class="token string">"你好"</span> + <span class="token comment">// 这里的 v 就直接是 rune</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> s <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"%c"</span><span class="token punctuation">,</span> v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><ol start="2"><li>将 s 转化为 []rune 来获取真正的 unicode 编码:</li></ol> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s <span class="token operator">:=</span> <span class="token string">"你好"</span> + sr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">rune</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token comment">// 这里的 v 就直接是 rune</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> sr <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"%c"</span><span class="token punctuation">,</span> sr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/string/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/26.83ccb127.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\344\275\234\347\224\250\345\237\237/index.html" "b/\345\237\272\347\241\200/\344\275\234\347\224\250\345\237\237/index.html" new file mode 100644 index 000000000..f8ef251f5 --- /dev/null +++ "b/\345\237\272\347\241\200/\344\275\234\347\224\250\345\237\237/index.html" @@ -0,0 +1,145 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/27.d1524f5d.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/#代码块的类型" class="sidebar-link">代码块的类型</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/#if" class="sidebar-link">if</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/#for" class="sidebar-link">for</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E4%BD%9C%E7%94%A8%E5%9F%9F/#switch-select" class="sidebar-link">switch && select</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="作用域">作用域</h1> <p>先给出两个经典的案例:</p> <p>if 级变量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> a <span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span><span class="token boolean">false</span><span class="token punctuation">{</span> + + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> b <span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span><span class="token boolean">false</span><span class="token punctuation">{</span> + + <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token keyword">if</span> c <span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span><span class="token boolean">false</span><span class="token punctuation">{</span> + + <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">,</span>c<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>a b c 这三个变量的作用域属于 if 这整个结构,只要前面初始化过,那么后面就可以使用,所以你会发现 print 可以输出三个变量。</p> <p>loop 级变量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i<span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>因为 <strong>i 属于 loop 级别</strong>,通常来说 for 执行过程是快于新开辟一个 goroutine 的,所以导致这是个 goroutine 输出的都是最后一个 i,即都输出 10</p> <p>根据 go 1.20 的表述,以后这个 loop 级别的变量<strong>非常有可能</strong>会被修改成局部变量。如果没有被修改,我们可以开辟一个局部变量 (go 1.22 将这个 loop 级变量修改为局部变量)</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i<span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + i <span class="token operator">:=</span> i + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="代码块的类型">代码块的类型</h2> <p>代码块是代码执行的基本单位,代码执行流总是从一个代码块流转到另一个代码块。</p> <ul><li>显式代码块 +<ul><li>函数体</li> <li>for 循环体</li> <li>if 语句</li></ul></li> <li>隐式代码块 +<ul><li>宇宙代码块:所有的 go 源码都属于这个代码块</li> <li>包代码块:每一个包都有一个代码块,这个代码块包括了整个包的源码</li> <li>文件代码块:每一个文件都有一个代码块,这个代码块包括了整个文件的源码</li></ul></li></ul> <p>预定义的标识符,比如 make new cap len 作用域是宇宙代码块</p> <p>包级变量,包级常量的作用域是包代码块</p> <p>go 源代码中导入的包名称作用域是文件代码块</p> <p>方法接收器,函数参数,返回值,对应的作用域是函数作用域</p> <p>函数体内部声明的变量和常量作用域仅限于函数体内部的局部作用域</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token punctuation">{</span> + <span class="token keyword">const</span> A <span class="token operator">=</span> <span class="token number">12</span> <span class="token comment">// A的作用域就仅限于这个大括号里面</span> + + <span class="token punctuation">}</span> + +<span class="token punctuation">}</span> +</code></pre></div><h2 id="if">if</h2> <p>if 包含了一个隐式的代码块:</p> <div class="language-go extra-class"><pre class="language-go"><code>c <span class="token operator">:=</span> <span class="token number">12</span> +<span class="token keyword">if</span> a<span class="token operator">:=</span><span class="token number">1</span><span class="token punctuation">;</span>a<span class="token operator"><</span><span class="token number">2</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token keyword">if</span> b<span class="token operator">:=</span><span class="token number">3</span><span class="token punctuation">;</span>b <span class="token operator"><</span> c <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> +<span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>其实等于:</p> <div class="language-go extra-class"><pre class="language-go"><code> c<span class="token operator">:=</span> <span class="token number">12</span> +<span class="token punctuation">{</span> + a<span class="token operator">:=</span><span class="token number">1</span> + <span class="token keyword">if</span> a<span class="token operator"><</span><span class="token number">2</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + b <span class="token operator">:=</span> <span class="token number">3</span> + <span class="token keyword">else</span> <span class="token keyword">if</span> b <span class="token operator"><</span> c <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>所以,在 if 中的大括号里,是可以输出 a 的值的。</p> <h2 id="for">for</h2> <p>for 循环的作用域可以使用下面的两种方式展现。for 循环中的变量都属于 loop 级,不属于每次的那个小循环的局部变量,所以在整个的 loop 过程中,变量是唯一的,就是那一个。只不过不同的时间点,这个变量的值有可能是不同的。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">for</span> i<span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> + +<span class="token comment">// 等价于</span> + +<span class="token punctuation">{</span> + i<span class="token operator">:=</span><span class="token number">0</span> + <span class="token keyword">for</span> <span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这里需要注意一下,一旦 go 在后续的版本中修改了 loop 级变量这个设定,这个等价就不成立了。上文有讲。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">for</span> k<span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> slice <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +<span class="token comment">// 等价于</span> +<span class="token punctuation">{</span> + k<span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">,</span><span class="token number">0</span> + <span class="token keyword">for</span> k<span class="token punctuation">,</span>v <span class="token operator">=</span> <span class="token keyword">range</span> slice <span class="token punctuation">{</span> + + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="switch-select">switch && select</h2> <p>这两种结构的等价是相同的,都是 case 级。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">switch</span> expression<span class="token punctuation">:</span> +<span class="token keyword">case</span> list1<span class="token punctuation">:</span> +<span class="token keyword">case</span> list2<span class="token punctuation">:</span> +<span class="token keyword">default</span><span class="token punctuation">:</span> + +等价于 + +<span class="token keyword">switch</span> expression<span class="token punctuation">:</span> +<span class="token keyword">case</span> list1<span class="token punctuation">:</span> +<span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">case</span> list2<span class="token punctuation">:</span> +<span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">default</span><span class="token punctuation">:</span> +<span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>select 稍微有点不同,因为 select 中的 case 是可以新建一个变量的,除了我们说的每一个 case 是一个作用域之外,case 上新建的这个变量也只是属于下面这个小的作用域。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/作用域/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/22/2024, 9:15:19 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/27.d1524f5d.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\205\266\344\273\226\345\206\205\345\256\271/index.html" "b/\345\237\272\347\241\200/\345\205\266\344\273\226\345\206\205\345\256\271/index.html" new file mode 100644 index 000000000..2e0e0d5c3 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\205\266\344\273\226\345\206\205\345\256\271/index.html" @@ -0,0 +1,155 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>其他内容 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/28.69e5608b.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>其他内容</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/#指针" class="sidebar-link">指针</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/#go-的引用类型和非引用类型" class="sidebar-link">go 的引用类型和非引用类型</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/#全局变量和局部变量" class="sidebar-link">全局变量和局部变量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/#go-init-函数的执行顺序" class="sidebar-link">go init 函数的执行顺序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/#go-可比较类型" class="sidebar-link">go 可比较类型</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%85%B6%E4%BB%96%E5%86%85%E5%AE%B9/#go-可寻址类型" class="sidebar-link">go 可寻址类型</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="其他内容">其他内容</h1> <h2 id="指针">指针</h2> <p>go 语言的指针类型是 unsafe.Pointer,<code>uintptr</code> 是指针的计算类型,也就是说,地址必须通过 unsafe.Pointer 提取以后,再转为 uintptr 才能进行计算,uintptr 的实质是一个整数类型,并且完全可以容纳所有的指针的数据。</p> <p>go 语言使用 <code>*</code> 符号用来表示指针类型,以及取指针类型实际数据这个操作,使用 <code>&</code> 取变量的指针 (地址),我们看一下操作</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 使用 内置函数 new() 去取结构体的地址</span> + <span class="token keyword">var</span> p <span class="token operator">*</span>People <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>People<span class="token punctuation">)</span> + <span class="token operator">*</span>p <span class="token operator">=</span> People<span class="token punctuation">{</span> + <span class="token string">"1"</span> + <span class="token punctuation">}</span> + <span class="token comment">// 使用 取值符号去取得 变量 p 的地址</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>p<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span><span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>我们看一下如何直接计算指针类型</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// a ,string 类型</span> + <span class="token keyword">var</span> a <span class="token builtin">string</span> + + <span class="token comment">// b ,a变量的地址</span> + <span class="token keyword">var</span> b <span class="token operator">*</span><span class="token builtin">string</span> <span class="token operator">=</span> <span class="token operator">&</span>a + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"打印初始a变量的地址"</span><span class="token punctuation">,</span> b<span class="token punctuation">)</span> + + <span class="token comment">// c,转为可计算的指针类型之后的变量</span> + c <span class="token operator">:=</span> <span class="token function">uintptr</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// uintptr(unsafe.Pointer())</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"打印可计算指针类型c"</span><span class="token punctuation">,</span> c<span class="token punctuation">)</span> + c<span class="token operator">++</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"打印可计算指针类型c++"</span><span class="token punctuation">,</span> c<span class="token punctuation">)</span> + + <span class="token comment">// 将c再转化为 a 的地址</span> + b <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// (*string)(unsafe.Pointer())</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"打印转换后的a的指针"</span><span class="token punctuation">,</span> b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code>打印初始a的指针地址 <span class="token number">0x14000096230</span> +打印可计算指针类型c <span class="token number">1374390149680</span> +打印可计算指针类型c<span class="token operator">++</span> <span class="token number">1374390149681</span> +打印转换后的a的指针 <span class="token number">0x14000096231</span> +</code></pre></div><h2 id="go-的引用类型和非引用类型">go 的引用类型和非引用类型</h2> <table><thead><tr><th style="text-align:center;">引用类型</th> <th style="text-align:center;">非引用类型</th></tr></thead> <tbody><tr><td style="text-align:center;">slice, interface, chan, map</td> <td style="text-align:center;">其余</td></tr></tbody></table> <p>引用类型的实质其实就是 fat pointer 即:胖指针,整个类型使用 struct 作为底层数据,data 是一个指针地址,它指向的是要使用的数据。</p> <h2 id="全局变量和局部变量">全局变量和局部变量</h2> <p>全局变量,引用类型分配在堆上,值类型分配在栈上</p> <p>局部变量,一般分配在栈上,当局部对象过大的时候分配在堆上,如果对局部变量做逃逸分析,发现它逃逸到了堆上,那么就将其分配到堆上</p> <h2 id="go-init-函数的执行顺序">go init 函数的执行顺序</h2> <p>init 函数在一个包内的执行顺序:对同一个 <code>go</code> 文件的 <code>init()</code> 调用顺序是从上到下的,对同一个 <code>package</code> 中的不同文件,将文件名按字符串进行 “从小到大” 排序 (数字排在前面),之后顺序调用各文件中的 <code>init()</code> 函数</p> <p>对于不同的包,如果不相互依赖的话,按照 main 包中 import 的顺序调用其包中的 <code>init()</code> 函数,如果包存在依赖,例如:导入顺序 main –> A –> B –> C,则执行顺序为 C –> B –> A –> main</p> <p><strong>go 会先执行全局变量再执行 init</strong>,当然多包全局变量的初始化跟 init 的执行顺序是一致的</p> <h2 id="go-可比较类型">go 可比较类型</h2> <blockquote><p>https://go.dev/ref/spec#Comparison_operators</p></blockquote> <p>不可以的</p> <ul><li>切片,map func (这几种都是因为自己本身变来变去,同样的变量,不同时间,内部值就变了,所以他们不可以参与 == 的比较) 变量无法参与一般的比较,但是他们可以和 nil 作对比</li></ul> <p>可以的:</p> <ul><li>数字类型,bool,string 这种常见类型可比较 +<ul><li><code>a := make(chan []int)</code> 即使是这样的内部含有不可比较的通道变量本身也是可以比较的。</li></ul></li> <li>chan 当两个 chan 类型的变量进行比较时,只有它们都为 nil 或者指向同一个通道时才返回 true,否则返回 false。</li> <li>内部字段都必须是可比较类型的数组和结构体可以比较</li> <li>指针可以比较,指针的实质是一个整数类型</li> <li>接口类型是可比较类型</li></ul> <p>所以,接口变量是可以作为 map 的 key 值的,因为接口可以比较</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + b <span class="token operator">:=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> s Some + b<span class="token punctuation">[</span>s<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">[</span><span class="token boolean">nil</span><span class="token punctuation">]</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Some <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">methods</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="go-可寻址类型">go 可寻址类型</h2> <p>以下内容是<strong>不可寻址</strong>的量</p> <blockquote><p>字面量的解释 var a int = 12,12 就是字面量,也就是所谓的那个值本身;结果值的解释:就是这个结果这个 value 的值</p></blockquote> <ul><li><p>常量 <code>const a = 12</code> &a 不可寻址</p></li> <li><p>基本类型值的字面量 <code>a := 12</code> &12 不可寻址</p></li> <li><p>算术操作的结果值 <code>a := 12 b := 12 &(b+a)</code></p></li> <li><p>对各种字面量的索引表达式和切片表达式的结果值。不过有一个例外,对切片字面量的索引结果值却是可寻址的</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">}</span> + <span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> a <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>a<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">// 无法寻址,这个数据属于临时的,可变的数据</span> + <span class="token punctuation">}</span> + + b <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + + <span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> b <span class="token punctuation">{</span> + + <span class="token comment">// 这个可以寻址,每个切片值都会持有一个底层数组,</span> + <span class="token comment">// 而这个底层数组中的每个元素值都是有一个确切的内存地址</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator">&</span>b<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +</code></pre></div></li> <li><p>切片字面量的切片结果值为什么却是不可寻址?<code>a := []int{1,2}, &(a[:1])</code> 原因是切片表达式字面量的切片属于临时值跟字面量的结果值不一样,后者属于结果值有效值</p></li> <li><p>对字符串变量的索引表达式和切片表达式的结果值。<code>a := "a" &("a") &a[0]</code></p></li> <li><p>对字典变量的索引表达式的结果值。<code>a := map[int]int{1:1} &(a[1])</code></p></li> <li><p>函数字面量和方法字面量,以及对它们的调用表达式的结果值。<code>&(func ())</code></p></li> <li><p>结构体字面量,见下面例子</p></li> <li><p>类型转换表达式的结果值</p></li> <li><p>类型断言表达式的结果值</p></li> <li><p>接收表达式的结果值</p></li></ul> <p>我们看一道<strong>面试题</strong>:</p> <p>这道题就是因为中间变量无法获取地址造成的 bug</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 此处go会自动调用值的指针来运行 SetName 但是因为 return Dog{name} 是一个临时的值,所以无法获取到指针</span> + <span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"nihao"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">SetName</span><span class="token punctuation">(</span><span class="token string">"monster"</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">New</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span> Dog <span class="token punctuation">{</span> + <span class="token keyword">return</span> Dog<span class="token punctuation">{</span>name<span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Dog <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>d <span class="token operator">*</span>Dog<span class="token punctuation">)</span> <span class="token function">SetName</span><span class="token punctuation">(</span>n <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + d<span class="token punctuation">.</span>name <span class="token operator">=</span> n +<span class="token punctuation">}</span> +</code></pre></div><p>我们可以这么改</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + +a <span class="token operator">:=</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"nihao"</span><span class="token punctuation">)</span> +a<span class="token punctuation">.</span> <span class="token function">SetName</span><span class="token punctuation">(</span><span class="token string">"monster"</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">New</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span> Dog <span class="token punctuation">{</span> + <span class="token keyword">return</span> Dog<span class="token punctuation">{</span>name<span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Dog <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>d <span class="token operator">*</span>Dog<span class="token punctuation">)</span> <span class="token function">SetName</span><span class="token punctuation">(</span>n <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + d<span class="token punctuation">.</span>name <span class="token operator">=</span> n +<span class="token punctuation">}</span> + +</code></pre></div><p>另外自增 ++ 自减 -- 左边的表达式都必须是可寻址的类型,否则也是无法操作的。</p> <blockquote><p>字典字面量和字典变量索引表达式的结果值是个例外例如 ma [“12”] ++</p></blockquote> <p>在赋值语句中,赋值操作符左边的表达式的结果值必须可寻址的,但是对字典的索引结果值也是可以的</p> <p>总结一下:</p> <ul><li><code>常量</code> + string 这种无法更改的数据无法寻址,函数通常来说也可以算作 “常量”,应该它就是一段代码,不可更改</li> <li><code>结果值/字面量</code> 因为其无法更改所以寻址将没有意义</li> <li><code>中间值</code> 或者 <code>临时对象</code> 比如说 &(a + b) 这类临时的变量的内存地址没有意义</li> <li><code>不安全的操作</code> 比如 map 中的 k-v 经常要从一个哈希桶迁移到另一个桶,所以你获取地址,它经常会改变,外界还不得而知,所以获取到这个 key-value 的地址是不安全的</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/其他内容/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/28.69e5608b.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/0.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/0.html" new file mode 100644 index 000000000..deea38467 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/0.html" @@ -0,0 +1,112 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/29.742dd6e8.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="反转控制">反转控制</h1> <p>概念:控制逻辑与业务逻辑分享,让业务逻辑依赖控制逻辑。</p> <p>大概的思路就是***将控制代码剥离,然后在逻辑代码中去调用控制代码即可***,具体实现的时候,就是在逻辑代码中内嵌控制代码的类型,这样即可。</p> <p>首先需要明确的是 “控制逻辑是什么” 这个问题,我们举一个例子:有一个数据库,数据库的增删改查就是控制逻辑,使用这些基础的动作去将用户的名字存入数据库,删除用户的名字,这叫业务逻辑,我们所说的反转控制,就是将基础的控制剥离出来,下面我们看一个例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 这是控制代码,我们把控制代码先揪出来。</span> +<span class="token keyword">type</span> Undo <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>undo <span class="token operator">*</span>Undo<span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>function <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token operator">*</span>undo <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span><span class="token operator">*</span>undo<span class="token punctuation">,</span> function<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// 这段代码的作用:恢复</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>undo <span class="token operator">*</span>Undo<span class="token punctuation">)</span> <span class="token function">Undo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + functions <span class="token operator">:=</span> <span class="token operator">*</span>undo + <span class="token keyword">if</span> <span class="token function">len</span><span class="token punctuation">(</span>functions<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"No functions to undo"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + index <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>functions<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span> + <span class="token keyword">if</span> function <span class="token operator">:=</span> functions<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span> function <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// For garbage collection</span> + functions<span class="token punctuation">[</span>index<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + <span class="token comment">// 这里是为了规避在调用delelte的时候,又调用了add的情况</span> + <span class="token comment">// 因为 delete的时候会调用add,add的时候会再次调用delete</span> + <span class="token comment">// 为了防止这种情况,我们认为的将这个切片减去一个即可。</span> + <span class="token operator">*</span>undo <span class="token operator">=</span> functions<span class="token punctuation">[</span><span class="token punctuation">:</span>index<span class="token punctuation">]</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们将控制逻辑嵌入到业务逻辑中</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> IntSet <span class="token keyword">struct</span> <span class="token punctuation">{</span> + data <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">bool</span> + undo Undo +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewIntSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span> IntSet <span class="token punctuation">{</span> + <span class="token keyword">return</span> IntSet<span class="token punctuation">{</span>data<span class="token punctuation">:</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">bool</span><span class="token punctuation">)</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 直接继承</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>set <span class="token operator">*</span>IntSet<span class="token punctuation">)</span> <span class="token function">Undo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> set<span class="token punctuation">.</span>undo<span class="token punctuation">.</span><span class="token function">Undo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>set <span class="token operator">*</span>IntSet<span class="token punctuation">)</span> <span class="token function">Contains</span><span class="token punctuation">(</span>x <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> set<span class="token punctuation">.</span>data<span class="token punctuation">[</span>x<span class="token punctuation">]</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>set <span class="token operator">*</span>IntSet<span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>x <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token operator">!</span>set<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 增加一个数据</span> + set<span class="token punctuation">.</span>data<span class="token punctuation">[</span>x<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">true</span> + <span class="token comment">// 如果是恢复的话,是需要删除一个数据的</span> + <span class="token comment">// 所以这里的操作就是删除</span> + set<span class="token punctuation">.</span>undo<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> set<span class="token punctuation">.</span><span class="token function">Delete</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + set<span class="token punctuation">.</span>undo<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>set <span class="token operator">*</span>IntSet<span class="token punctuation">)</span> <span class="token function">Delete</span><span class="token punctuation">(</span>x <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> set<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">delete</span><span class="token punctuation">(</span>set<span class="token punctuation">.</span>data<span class="token punctuation">,</span> x<span class="token punctuation">)</span> + set<span class="token punctuation">.</span>undo<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> set<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + set<span class="token punctuation">.</span>undo<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/0.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/29.742dd6e8.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/1.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/1.html" new file mode 100644 index 000000000..419045ba8 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/1.html" @@ -0,0 +1,92 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/30.4aafb94a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="map-filter-reduce">map-filter-reduce</h1> <p>map filter reduce 这三个操作经常用在数据的处理上,比如数据的统计业务。</p> <p>下面看一下这三者基本的做法是什么</p> <p>我们用做饭来进行类比:</p> <ul><li>map 30 个进,30 个出,类似于洗菜的过程</li> <li>filter 30 个进,15 个出,类似于摘菜</li> <li>reduce 15 个进,1 个出,类似于炒菜的过程</li></ul> <p>下面这个案例,我们要对于一组 string 进行数据处理。map 的过程,我们对这堆 string 进行全部的修饰,filer 过程我们挑选出合适的 string,reduce 过程我们最终输出要的成品</p> <p>map 的举例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">MapStr</span><span class="token punctuation">(</span>s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">,</span>f <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> newS <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> s<span class="token punctuation">{</span> + newS <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>newS<span class="token punctuation">,</span><span class="token function">f</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> newS +<span class="token punctuation">}</span> +</code></pre></div><p>filter 的举例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">FilterStr</span><span class="token punctuation">(</span>s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">,</span>f <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token builtin">bool</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> newS <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> s<span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token function">f</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">{</span> + newS <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>newS<span class="token punctuation">,</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> newS +<span class="token punctuation">}</span> +</code></pre></div><p>reduce 的举例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">ReduceStr</span><span class="token punctuation">(</span>s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">,</span>f <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token builtin">string</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> newS <span class="token builtin">string</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> s<span class="token punctuation">{</span> + newS <span class="token operator">+=</span> <span class="token function">f</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> newS +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">{</span><span class="token string">"李明月"</span><span class="token punctuation">,</span> <span class="token string">"李月"</span><span class="token punctuation">,</span> <span class="token string">"百伯"</span><span class="token punctuation">,</span> <span class="token string">"张兰"</span><span class="token punctuation">,</span> <span class="token string">"武滴滴"</span><span class="token punctuation">,</span> <span class="token string">"叶赫那拉"</span><span class="token punctuation">,</span> <span class="token string">"迪丽热巴"</span><span class="token punctuation">}</span> + ns <span class="token operator">:=</span> <span class="token function">MapStr</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>v <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> v <span class="token operator">+</span> <span class="token string">"同学"</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>ns<span class="token punctuation">)</span> + ns <span class="token operator">=</span> <span class="token function">FilterStr</span><span class="token punctuation">(</span>ns<span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>v <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">rune</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">4</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>ns<span class="token punctuation">)</span> + sum <span class="token operator">:=</span> <span class="token function">ReduceStr</span><span class="token punctuation">(</span>ns<span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>v <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> v <span class="token operator">+</span> <span class="token string">"-"</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>sum<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码的意思就是首先,我们有一堆学生的名字,我们在名字后面先加上同学,然后我们要把名字本身大于两个字的同学挑出来,并且把他们组成一句话。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">map</span> <span class="token punctuation">:</span><span class="token punctuation">[</span>李明月同学 李月同学 百伯同学 张兰同学 武滴滴同学 叶赫那拉同学 迪丽热巴同学<span class="token punctuation">]</span> +filter <span class="token punctuation">:</span><span class="token punctuation">[</span>李明月同学 武滴滴同学 叶赫那拉同学 迪丽热巴同学<span class="token punctuation">]</span> +reduce <span class="token punctuation">:</span>李明月同学<span class="token operator">-</span>武滴滴同学<span class="token operator">-</span>叶赫那拉同学<span class="token operator">-</span>迪丽热巴同学<span class="token operator">-</span> +</code></pre></div><p>通过这个案例我们发现,map-filter-reduce 本身只是控制逻辑,真正的业务逻辑其实是那个函数类型,所以说 map-filter reduce 也是标准的 <code>控制代码-业务代码</code> 分离设计</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/1.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/30.4aafb94a.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/2.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/2.html" new file mode 100644 index 000000000..ef7df84df --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/2.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/31.87baab0b.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-generation">go generation</h1> <p>// go 已经推出了泛型,因此没有写的必要了。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/2.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">4/5/2023, 3:48:20 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/31.87baab0b.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/3.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/3.html" new file mode 100644 index 000000000..83b27c748 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/3.html" @@ -0,0 +1,98 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/32.1ea926c5.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html#具体案例" class="sidebar-link">具体案例</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/3.html#多修饰器的-pipeline-串型调用" class="sidebar-link">多修饰器的 pipeline (串型调用)</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="修饰器">修饰器</h1> <p>简单的描述:一个修饰器函数,参数是函数,返回一个运行了这个参数函数的跟参数函数保持相同的函数。</p> <p>如果是接口,那么就是一个修饰器函数,参数是一个接口,返回值还是这个接口。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">D</span><span class="token punctuation">(</span>f <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">f</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"done"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">D</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="具体案例">具体案例</h2> <p>http 处理 cookie 和 header 的案例:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + http<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">,</span><span class="token function">WithHeader</span><span class="token punctuation">(</span>hello<span class="token punctuation">)</span><span class="token punctuation">)</span> + http<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span><span class="token string">"/s"</span><span class="token punctuation">,</span><span class="token function">WithCookie</span><span class="token punctuation">(</span>hello<span class="token punctuation">)</span><span class="token punctuation">)</span> + http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":8080"</span><span class="token punctuation">,</span><span class="token boolean">nil</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">hello</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span>r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Fprintln</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span><span class="token string">"hello"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">WithHeader</span><span class="token punctuation">(</span>h http<span class="token punctuation">.</span>HandlerFunc<span class="token punctuation">)</span>http<span class="token punctuation">.</span>HandlerFunc<span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span>r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span><span class="token punctuation">{</span> + w<span class="token punctuation">.</span><span class="token function">Header</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span><span class="token string">"Server"</span><span class="token punctuation">,</span> <span class="token string">"HelloServer"</span><span class="token punctuation">)</span> + <span class="token function">h</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span>r<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">WithCookie</span><span class="token punctuation">(</span>h http<span class="token punctuation">.</span>HandlerFunc<span class="token punctuation">)</span> http<span class="token punctuation">.</span>HandlerFunc <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">{</span> + cookie <span class="token operator">:=</span> <span class="token operator">&</span>http<span class="token punctuation">.</span>Cookie<span class="token punctuation">{</span>Name<span class="token punctuation">:</span> <span class="token string">"auth"</span><span class="token punctuation">,</span> Value<span class="token punctuation">:</span> <span class="token string">"123456"</span><span class="token punctuation">,</span> Path<span class="token punctuation">:</span> <span class="token string">"/"</span><span class="token punctuation">}</span> + http<span class="token punctuation">.</span><span class="token function">SetCookie</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> cookie<span class="token punctuation">)</span> + <span class="token function">h</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> r<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="多修饰器的-pipeline-串型调用">多修饰器的 pipeline (串型调用)</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Hander <span class="token keyword">func</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span>HandlerFunc<span class="token punctuation">)</span>http<span class="token punctuation">.</span>HandlerFunc + +<span class="token keyword">func</span> <span class="token function">DealWith</span><span class="token punctuation">(</span>h http<span class="token punctuation">.</span>HandlerFunc<span class="token punctuation">,</span>handlers <span class="token operator">...</span>Hander<span class="token punctuation">)</span>http<span class="token punctuation">.</span>HandlerFunc<span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> handlers <span class="token punctuation">{</span> + d <span class="token operator">:=</span> handlers<span class="token punctuation">[</span><span class="token function">len</span><span class="token punctuation">(</span>handlers<span class="token punctuation">)</span> <span class="token operator">-</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span> + h <span class="token operator">=</span> <span class="token function">d</span><span class="token punctuation">(</span>h<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> h +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + http<span class="token punctuation">.</span><span class="token function">HandleFunc</span><span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">,</span><span class="token function">DealWith</span><span class="token punctuation">(</span>hello<span class="token punctuation">,</span>WithCookie<span class="token punctuation">,</span>WithHeader<span class="token punctuation">)</span><span class="token punctuation">)</span> + http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":8080"</span><span class="token punctuation">,</span><span class="token boolean">nil</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/3.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/32.1ea926c5.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/4.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/4.html" new file mode 100644 index 000000000..b0865aff2 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/4.html" @@ -0,0 +1,120 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/33.4d31d0db.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="pipeline">pipeline</h1> <p>pipeline 模式,它将一系列的小命令组合成一个大的命令,它可以将***一个大命令拆分为一个一个的高内聚的小命令***,我们可以使用这一系列的小命令组合更多更复杂的命令。</p> <p>下面给出一个需求,我们将这个需求写成 pipeline 的模式。</p> <p>需求是:对一个 int 的切片做 “平方”,“过滤奇函数”,“求和” 的操作,并且使用 pipeline 的方式去调用这一系列的高内聚的小函数。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 初始函数</span> +<span class="token keyword">func</span> <span class="token function">echo</span><span class="token punctuation">(</span>data <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + out <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> data <span class="token punctuation">{</span> + out <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 平方</span> +<span class="token keyword">func</span> <span class="token function">sq</span><span class="token punctuation">(</span>in <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + out <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> in <span class="token punctuation">{</span> + out <span class="token operator"><-</span> v <span class="token operator">*</span> v + <span class="token punctuation">}</span> + <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 过滤奇函数</span> +<span class="token keyword">func</span> <span class="token function">odd</span><span class="token punctuation">(</span>in <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + out <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> in <span class="token punctuation">{</span> + <span class="token keyword">if</span> v<span class="token operator">%</span><span class="token number">2</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token punctuation">{</span> + out <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 求和</span> + +<span class="token keyword">func</span> <span class="token function">sum</span><span class="token punctuation">(</span>in <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + out <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + sum <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> in <span class="token punctuation">{</span> + sum <span class="token operator">+=</span> v + <span class="token punctuation">}</span> + out <span class="token operator"><-</span> sum + <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">type</span> EchoFunction <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator"><-</span> <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> +<span class="token keyword">type</span> PipeFunction <span class="token keyword">func</span> <span class="token punctuation">(</span><span class="token operator"><-</span> <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator"><-</span> <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + +<span class="token comment">// pipeline 处理</span> +<span class="token keyword">func</span> <span class="token function">Handle</span><span class="token punctuation">(</span>a <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> e EchoFunction<span class="token punctuation">,</span> ps <span class="token operator">...</span>PipeFunction<span class="token punctuation">)</span> <span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">e</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> ps <span class="token punctuation">{</span> + ch <span class="token operator">=</span> <span class="token function">v</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> ch +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// main函数</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">}</span> + data <span class="token operator">:=</span> <span class="token operator"><-</span><span class="token function">Handle</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> echo<span class="token punctuation">,</span> sq<span class="token punctuation">,</span> odd<span class="token punctuation">,</span> sum<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/4.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/33.4d31d0db.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/5.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/5.html" new file mode 100644 index 000000000..c2b41e582 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/5.html" @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/34.7610889f.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="k8s-visitor">k8s visitor</h1> <p>这是一种将算法和数据结构分离的编程模式。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Visitor <span class="token keyword">func</span><span class="token punctuation">(</span>shap Shap<span class="token punctuation">)</span> + +<span class="token keyword">type</span> Shap <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">Accept</span><span class="token punctuation">(</span>Visitor<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们创造一个函数类型,它接受一个接口作为参数。</p> <p>我们定义刚才那个接口,并且在接口中我们定义一个函数,这个函数中的参数是刚才的函数类型。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> result1 <span class="token keyword">struct</span> <span class="token punctuation">{</span> + data <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>r result1<span class="token punctuation">)</span> <span class="token function">Accept</span><span class="token punctuation">(</span>v Visitor<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">v</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> result2 <span class="token keyword">struct</span> <span class="token punctuation">{</span> + data <span class="token builtin">int</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>r result2<span class="token punctuation">)</span> <span class="token function">Accept</span><span class="token punctuation">(</span>v Visitor<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">v</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们实现了两个 struct。</p> <p>接下来,我们定义一些函数,这些函数是 visitor 函数。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">n1</span><span class="token punctuation">(</span>shap Shap<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>shap<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">n2</span><span class="token punctuation">(</span>shap Shap<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>shap<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>接下来我们在 mian 函数中调用这个 visitor 函数。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + r1 <span class="token operator">:=</span> result1<span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">}</span> + r2 <span class="token operator">:=</span> result2<span class="token punctuation">{</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">"shgopher"</span><span class="token punctuation">}</span> + result <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>Shap<span class="token punctuation">{</span>r1<span class="token punctuation">,</span> r2<span class="token punctuation">}</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> result <span class="token punctuation">{</span> + v<span class="token punctuation">.</span><span class="token function">Accept</span><span class="token punctuation">(</span>n1<span class="token punctuation">)</span> + v<span class="token punctuation">.</span><span class="token function">Accept</span><span class="token punctuation">(</span>n2<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>数据是 r1,和 r2,算法是 n1 和 n2,这样,我们就可以将算法和数据给分开,互相不会有耦合。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/5.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/34.7610889f.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/6.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/6.html" new file mode 100644 index 000000000..9290945b2 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/6.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/35.32a9ec30.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="k8s-builder">k8s builder</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/6.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">4/10/2023, 4:16:27 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/35.32a9ec30.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/7.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/7.html" new file mode 100644 index 000000000..0ace72f47 --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/7.html" @@ -0,0 +1,176 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>综合题 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/36.8d562ec5.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>综合题</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html#k8s-visitor-修饰器-pipeline" class="sidebar-link">k8s visitor + 修饰器 + pipeline</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/7.html#修饰器-k8s-visitor-pipeline" class="sidebar-link">修饰器 + k8s visitor + pipeline</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="综合题">综合题</h1> <blockquote><p>本内容选自 <a href="https://github.com/kubernetes/kubernetes/blob/cea1d4e20b4a7886d8ff65f34c6d4f95efcb4742/staging/src/k8s.io/cli-runtime/pkg/resource/visitor.go" target="_blank" rel="noopener noreferrer">k8s<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p></blockquote> <h2 id="k8s-visitor-修饰器-pipeline">k8s visitor + 修饰器 + pipeline</h2> <p>这种写法,以 k8s 的 visitor 作为主要的实现方法,修饰器和 pipeline 作为辅助的实现手法</p> <p>首先我们实现这段代码的目的是为了将数据结构和算法分离,并且,我们希望每段的算法处理数据结构的一部分。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 行为</span> +<span class="token keyword">type</span> visitorFunc <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token operator">*</span>info<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> +<span class="token comment">// 抽象层</span> +<span class="token keyword">type</span> Visitor <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Visit</span><span class="token punctuation">(</span>visitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> +<span class="token punctuation">}</span> +<span class="token comment">// 数据</span> +<span class="token keyword">type</span> info <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>i <span class="token operator">*</span>info<span class="token punctuation">)</span> <span class="token function">Visit</span><span class="token punctuation">(</span>v visitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">v</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们基础部分已经写好了,这样就具备了基本的 visitor 的模式,接下来我们来写算法的实现</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 多态</span> +<span class="token keyword">type</span> OneDeal <span class="token keyword">struct</span> <span class="token punctuation">{</span> + visitor Visitor +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>o OneDeal<span class="token punctuation">)</span> <span class="token function">Visit</span><span class="token punctuation">(</span>v visitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> o<span class="token punctuation">.</span>visitor<span class="token punctuation">.</span><span class="token function">Visit</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token operator">*</span>info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + e <span class="token operator">:=</span> <span class="token function">v</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> err<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"one deal"</span><span class="token punctuation">,</span> i<span class="token punctuation">.</span>name<span class="token punctuation">)</span> + <span class="token keyword">return</span> e + <span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> twoDeal <span class="token keyword">struct</span> <span class="token punctuation">{</span> + visitor Visitor +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>o twoDeal<span class="token punctuation">)</span> <span class="token function">Visit</span><span class="token punctuation">(</span>v visitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> o<span class="token punctuation">.</span>visitor<span class="token punctuation">.</span><span class="token function">Visit</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token operator">*</span>info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + e <span class="token operator">:=</span> <span class="token function">v</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> err<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"two deal"</span><span class="token punctuation">,</span> i<span class="token punctuation">.</span>addr<span class="token punctuation">,</span> i<span class="token punctuation">.</span>year<span class="token punctuation">)</span> + <span class="token keyword">return</span> e + <span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当算法搞定以后,我们在 main 调用一下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + o <span class="token operator">:=</span> <span class="token operator">&</span>info<span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> v Visitor <span class="token operator">=</span> o + v <span class="token operator">=</span> OneDeal<span class="token punctuation">{</span>v<span class="token punctuation">}</span> + v <span class="token operator">=</span> twoDeal<span class="token punctuation">{</span>v<span class="token punctuation">}</span> + l <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token operator">*</span>info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + i<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"liu"</span> + i<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token number">2020</span> + i<span class="token punctuation">.</span>addr <span class="token operator">=</span> <span class="token string">"beijing"</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + v<span class="token punctuation">.</span><span class="token function">Visit</span><span class="token punctuation">(</span>l<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>可以看到,visitor,pipline,以及修饰器的模式都运用了</p> <ul><li>visitor:上面一个 type func,下面的 interface,连在一起就是 visitor 模式</li> <li>pipline:可以看到 visitor 的变量在不停的传递,然后调用的时候肯定会一直的调用不同的 visit func 函数,这就是 pipline</li> <li>修饰器:不同的 function,在不停的增加内容,并且输出的还是这个 function,这就是修饰器模式</li></ul> <p>可以看到,这个模式下,visitor 是主要的模式,其他的模式都是因这个模式而附带的效果,所以也可以说,visitor 自带 pipline 和修饰器模式,所以这种写法就单单的只是 visitor 而已。</p> <p>接下来,我们将修饰器模式作为主要的模式,另外加上 visitor 和 pipline</p> <h2 id="修饰器-k8s-visitor-pipeline">修饰器 + k8s visitor + pipeline</h2> <p>同样的我们需要先构造一个 visitor 系统</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">type</span> VisitorFunc <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token operator">*</span>Info<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> + +<span class="token keyword">type</span> Visitor <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Visit</span><span class="token punctuation">(</span>VisitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Info <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>i <span class="token operator">*</span>Info<span class="token punctuation">)</span> <span class="token function">Visit</span><span class="token punctuation">(</span>v VisitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">v</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>接下来我们创建一个修饰器系统</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> VisitorBox <span class="token keyword">struct</span> <span class="token punctuation">{</span> + visitor Visitor <span class="token comment">// 行为</span> + visitorFucs <span class="token punctuation">[</span><span class="token punctuation">]</span>VisitorFunc <span class="token comment">// 代表数据的桥梁</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewVisitorBox</span><span class="token punctuation">(</span>v Visitor<span class="token punctuation">,</span> fn <span class="token operator">...</span>VisitorFunc<span class="token punctuation">)</span> Visitor <span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token function">len</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> v + <span class="token punctuation">}</span> + <span class="token keyword">return</span> VisitorBox<span class="token punctuation">{</span>visitorFucs<span class="token punctuation">:</span> fn<span class="token punctuation">,</span> visitor<span class="token punctuation">:</span> v<span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>vi VisitorBox<span class="token punctuation">)</span> <span class="token function">Visit</span><span class="token punctuation">(</span>v VisitorFunc<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> vi<span class="token punctuation">.</span>visitor<span class="token punctuation">.</span><span class="token function">Visit</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token operator">*</span>Info<span class="token punctuation">,</span> e <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> e <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> e + <span class="token punctuation">}</span> + + <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">v</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + + <span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> vi<span class="token punctuation">.</span>visitorFucs <span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> vi<span class="token punctuation">.</span>visitorFucs<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + + <span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>接下来让我们调用一下</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + loadFile <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>info <span class="token operator">*</span>Info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + info<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"li"</span> + info<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token number">10</span> + info<span class="token punctuation">.</span>addr <span class="token operator">=</span> <span class="token string">"bj"</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + func1 <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>info <span class="token operator">*</span>Info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>name<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + func2 <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>info <span class="token operator">*</span>Info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>year<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + func3 <span class="token operator">:=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>info <span class="token operator">*</span>Info<span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>info<span class="token punctuation">.</span>addr<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + + info <span class="token operator">:=</span> <span class="token operator">&</span>Info<span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> v Visitor <span class="token operator">=</span> info + v <span class="token operator">=</span> <span class="token function">NewVisitorBox</span><span class="token punctuation">(</span>v<span class="token punctuation">,</span> func1<span class="token punctuation">,</span> func2<span class="token punctuation">,</span> func3<span class="token punctuation">)</span> + v<span class="token punctuation">.</span><span class="token function">Visit</span><span class="token punctuation">(</span>loadFile<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这种写法跟上面的写法改变之处在于创建了一个修饰器的 struct,并且装在了一个 pipline 的切片,然后我们就不用依次调用不同的算法结构体了,我们只需要在 new box 的时候将要执行的函数放入进去即可。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/7.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/36.8d562ec5.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/index.html" "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/index.html" new file mode 100644 index 000000000..b0f2a813e --- /dev/null +++ "b/\345\237\272\347\241\200/\345\207\275\346\225\260\346\226\271\346\263\225/index.html" @@ -0,0 +1,1050 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>函数和方法 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/8.ff976029.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>函数和方法</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#函数的初始化顺序" class="sidebar-link">函数的初始化顺序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#init-函数" class="sidebar-link">init 函数</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#defer-函数" class="sidebar-link">defer 函数</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#defer-函数因为无法-return-造成的内存泄露-bug" class="sidebar-link">defer 函数因为无法 return 造成的内存泄露 bug</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#再次强调-有无返回值具体变量对于-defer-的影响" class="sidebar-link">再次强调:有无返回值具体变量对于 defer 的影响</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#变长参数" class="sidebar-link">变长参数</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#使用变长函数去模拟重载函数" class="sidebar-link">使用变长函数去模拟重载函数</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#使用变长函数去实现默认参数" class="sidebar-link">使用变长函数去实现默认参数</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#类型嵌入来完成继承" class="sidebar-link">类型嵌入来完成继承</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#define-类型的方法集合" class="sidebar-link">define 类型的方法集合</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#类型别名的方法集合" class="sidebar-link">类型别名的方法集合</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#函数式编程" class="sidebar-link">函数式编程</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#函数式编程的实际应用" class="sidebar-link">函数式编程的实际应用</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#这里还有关于函数式编程其它相关内容" class="sidebar-link">这里还有关于函数式编程其它相关内容:</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="函数和方法">函数和方法</h1> <p>重点内容前情提要</p> <ul><li>函数初始化的顺序</li> <li>init 函数</li> <li>defer 的运用</li> <li>变长参数</li> <li>类型嵌入来完成继承</li> <li>define 类型的方法集合</li> <li>类型别名的方法集合</li> <li>函数式编程</li></ul> <p>go 语言中函数的基本使用方法如下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数的一般用法, go 拥有多个返回值</span> +<span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +<span class="token comment">// 返回值具有变量的返回模式</span> +<span class="token keyword">func</span> <span class="token function">Post</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>value <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + value <span class="token operator">=</span> <span class="token number">1</span> + <span class="token keyword">return</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 函数作为value值赋值给一个变量变量</span> +<span class="token keyword">var</span> Get0 <span class="token operator">=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">0</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="函数的初始化顺序">函数的初始化顺序</h2> <p><img src="/GOFamily/assets/img/gofunc.32e2f0aa.svg" alt=""></p> <ul><li>main 函数是所有 go 可执行函数的起始位置</li> <li>在 main 函数运行前,需要先运行导入子包的流程</li> <li>在导包的过程中,最先运行的是最深层的子包</li> <li>按照<strong>全局常量,全局变量,init 函数</strong>的顺序进行初始化的操作</li> <li>子包初始化之后,开始返回前一层的包中进行常量,全局变量,init 函数的初始化,图示流程非常清晰的画出了这个过程。</li> <li>多个相同的包只会导入一次,并且取相同包不同版本的可满足的最小版本导入,例如 <code>v1.1.0 v1.2.0</code>,只导入 <code>v1.2.0</code>,不会默认导入最新的版本。</li></ul> <h2 id="init-函数">init 函数</h2> <p>在一个包中,以及在一个包的某个文件中,可以存在多个 init 函数,一般来说,同一个包的不同 file,按照文件字符串比较的 “从小到大” 的顺序先被编译 file 中的 init 先执行,同一个 file 中的 init 函数按照先后顺序执行,但是 go 语言规范告诉我们,不要依赖 init 的执行顺序。</p> <p>init 函数无法主动执行,它的执行是系统自动执行的,所以显式的去调用 init 函数会发生报错。</p> <p>通常来说,init 的目的就是系统的初始化,因为它一定会被执行,下面我们介绍一下 init 函数的几个用途。</p> <p><em><strong>重置包级变量值。</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// src/context/context.go</span> + +<span class="token keyword">var</span> closedchan <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>closedchan<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们的包级变量是一个 chan,并且需要它是一个已经关闭的 chan,我们使用 init 来确保它提前一定处于一个已关闭的状态。</p> <p><em><strong>对包级变量进行初始化,保证其后续可用。</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> <span class="token punctuation">(</span> + OutBox <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> + InBox <span class="token keyword">chan</span> <span class="token builtin">int</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + OutBox <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> + InBox <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>init 函数中的注册模式。</strong></em></p> <p>这种模式在 go 中有两处经典的案例,其一是 <code>database/sql</code> 包的使用,其二是 image 包的使用。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// databsae/sql 包的使用</span> + +<span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"database/sql"</span> + <span class="token boolean">_</span> <span class="token string">"github.com/lib/pq"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + db<span class="token punctuation">,</span> err <span class="token operator">:=</span> sql<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"postgres"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这里使用 <code>import _</code> 就是只有导包的过程,并没有任何除了 init 函数之外的函数调用。那么这么做的原因是什么呢?</p> <p><code>工厂方法 + 导包的顺序</code></p> <p>下面我们看一下这两个包的源码</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// github.com/golnag/go/src/database/sql/sql.go</span> +<span class="token keyword">var</span> drivers <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span>driver<span class="token punctuation">.</span>Driver<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">Open</span><span class="token punctuation">(</span>driverName<span class="token punctuation">,</span> dataSourceName <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>DB<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + driveri<span class="token punctuation">,</span> ok <span class="token operator">:=</span> drivers<span class="token punctuation">[</span>driverName<span class="token punctuation">]</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">Register</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> driver driver<span class="token punctuation">.</span>Driver<span class="token punctuation">)</span> <span class="token punctuation">{</span> + drivers<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> driver +<span class="token punctuation">}</span> +</code></pre></div><ul><li>sql 包有一个全局的 map,这里存放了所有的 driver,这个 map 的 key 是 driver 的名字,value 是 driver.Driver 的接口类型,通常来说存入的都是实现了这个接口的动态类型。</li> <li>open 函数会直接判断是否拥有含有这个 key 的 value 值</li> <li>register 函数,也就是注册函数,这个函数通常由实现了 sql.driver 的数据库第三方库的 init 函数去进行最终的注册。</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// github.com/lib/pq</span> + +<span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + sql<span class="token punctuation">.</span><span class="token function">Register</span><span class="token punctuation">(</span><span class="token string">"postgres"</span><span class="token punctuation">,</span> <span class="token operator">&</span>Driver<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><ul><li>这里就是实现了 sql.Driver 的 pq.Driver 结构体进行了名为 “postgress” 的注册。</li></ul> <p>下面我们进行整体的分析:</p> <ul><li>在 pq 包实现的时候,它引入了 “database/sql”,“database/sql/driver” 这两个包,它将实现的数据库实例注册到 sql 的 map 中</li> <li>用户调用的时候,我们调用了 <code>sql.Open</code> 使用不同的 name 就可以使用不同的数据库,这里是工厂方法设计模式的运用</li></ul> <p>这种方法可以使 pq 这个包完全没有暴露到用户面前,仅需要使用 sql 包就可以间接的使用 pq 的代码,很好的做了隔绝。</p> <p>下面看一下 image 包的运用。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"image"</span> + <span class="token boolean">_</span> <span class="token string">"image/png"</span> + <span class="token boolean">_</span> <span class="token string">"image/gif"</span> + <span class="token boolean">_</span> <span class="token string">"image/jpeg"</span> + <span class="token string">"os"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + + width<span class="token punctuation">,</span>height<span class="token punctuation">,</span><span class="token builtin">error</span> <span class="token operator">:=</span> <span class="token function">image</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span>Args<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token builtin">error</span> <span class="token operator">!=</span> <span class="token boolean">nil</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token builtin">error</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token function">println</span><span class="token punctuation">(</span>width<span class="token punctuation">,</span> height<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">image</span><span class="token punctuation">(</span>f <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + file<span class="token punctuation">,</span>err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>f<span class="token punctuation">)</span> + <span class="token keyword">defer</span> file<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + img<span class="token punctuation">,</span> <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> image<span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span>err + <span class="token punctuation">}</span> + + b <span class="token operator">:=</span> img<span class="token punctuation">.</span><span class="token function">Bounds</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> b<span class="token punctuation">.</span>Max<span class="token punctuation">.</span>X<span class="token punctuation">,</span>b<span class="token punctuation">.</span>Max<span class="token punctuation">.</span>Y<span class="token punctuation">,</span><span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们发现,image.Decode(f) 应该就如同上文提到的 Open 函数一样的功能,也就是工厂方法中的工厂。</p> <p>下面我们看一下 image/gif 包中的 init 函数:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//https://github.com/golang/go/blob/master/src/image/gif/reader.go</span> + +<span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + image<span class="token punctuation">.</span><span class="token function">RegisterFormat</span><span class="token punctuation">(</span><span class="token string">"gif"</span><span class="token punctuation">,</span> <span class="token string">"GIF8?a"</span><span class="token punctuation">,</span> Decode<span class="token punctuation">,</span> DecodeConfig<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>可以看到,这个 gif 包也是调用了 image 包,并且通过 init 函数,将动态类型注册到了 image 提供的注册器中。</p> <p><em><strong>init 函数中检查失败的处理方法。</strong></em></p> <p>使用 init 去检查某些数据的正确性,相当于做最后的质检工作,一旦发生了错误,直接使用 Panic,快速停掉程序。</p> <h2 id="defer-函数">defer 函数</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + f<span class="token punctuation">,</span>err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"test.txt"</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span><span class="token punctuation">{</span> + <span class="token function">panic</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 此处就是 defer 函数</span> + <span class="token keyword">defer</span> f<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>defer 函数有下面几个规则</p> <ul><li>defer 后面只能跟函数或者是方法</li> <li>一个函数中的 defer 函数,会使用 “栈” 的方式运行</li> <li>defer 后面的函数和方法,返回值会被直接舍弃</li></ul> <p>下面看一下 defer 函数的几种用法</p> <p><em><strong>配合 recover 函数处理 panic</strong></em></p> <p>在 go 里,如果要处理函数内的 panic,有且仅有一种方法,那就是使用 recover 函数。而且 recover 函数必须运行在 defer 之中。那么让我们看一下具体的代码实现</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"recoverd"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"panic"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>修改函数的具名返回值</strong></em></p> <p>具名返回值,就是返回值带有变量的,比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span>y <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + x <span class="token operator">++</span> + y <span class="token operator">++</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + x <span class="token operator">=</span> a<span class="token operator">+</span>b + y <span class="token operator">=</span> a<span class="token operator">-</span>b + <span class="token keyword">return</span> +<span class="token punctuation">}</span> +<span class="token comment">// hi(1,3) 返回值为 (5,-1)</span> +</code></pre></div><p>在分析这段代码的时候,我们要牢记一句话,在具名返回值的函数中,go 的 return 并不会立刻 return,它会等待 defer 执行完毕后再真的 return。也就是说,它 return 的是 x y 的最后时刻。</p> <p>那么,让我们看一下非具名的函数:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> x<span class="token punctuation">,</span>y <span class="token builtin">int</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + x <span class="token operator">++</span> + y <span class="token operator">++</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"defer 会执行的"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + x <span class="token operator">=</span> a<span class="token operator">+</span>b + y <span class="token operator">=</span> a<span class="token operator">-</span>b + <span class="token keyword">return</span> x<span class="token punctuation">,</span> y +<span class="token punctuation">}</span> +<span class="token comment">// hi(1,3) </span> + +<span class="token comment">// output:</span> +<span class="token comment">// defer 会执行的 5 -1</span> +<span class="token comment">// 4 -2</span> +</code></pre></div><p>在非具名的函数中,return x,y 的时候就已经决定返回值的最终结果了,但是这个 defer 还是会执行,这个是真的,xy 的值确实也是在 defer 里改变了,但是 return 的是之前的中间量,defer 里面的 xy,并不会左右之前已经设定好的 x y 的复制值了。</p> <p>所以输出的是 4 -2,而且 defer 里面的输出 “defer 会执行的 5 -1” 也执行了。</p> <p>defer 函数虽然是先入后出,在所有的正式指令执行完成以后执行,但是它的变量初始化可是***顺序的***,这里强调一下,仅仅是变量的初始化是顺序执行,defer 函数是不会顺序执行的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + j <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token comment">// j 顺序的初始化数据了,</span> + <span class="token comment">// println却不会顺序执行!</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span>j <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span> + j<span class="token operator">++</span> + <span class="token keyword">return</span> +<span class="token punctuation">}</span> +<span class="token comment">// output: 0</span> +</code></pre></div><p>这里的 defer 顺序执行完变量的初始化,所以它里面的 j 变量完成了值的复制,为 0,那么下文的 j++ 就不会对上面的复制品起任何作用了,即便 prinln(j) 确实发生在 j++ 之后,总结一句话,defer 函数执行是最后,但是初始化是正常的先后顺序。</p> <p>如果想得到 1 的答案,可以这么改:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + j <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>j<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + j<span class="token operator">++</span> + <span class="token keyword">return</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这里的 j <strong>就会</strong>受到下面 j++的影响了。</p> <p>还有一点要注意,defer 函数的作用域也是正常的作用域,也就是说,上文 hi 函数演示内容,j:= 0 必须声明在 defer 函数之前,虽然我们知道 defer 的内容最后执行,但是它也遵循正常的作用域。如果 j := 0 发生在 defer 之后,它就会无法找到这个变量。</p> <p>看了上面那么多容易搞混的 defer 用法,这里要说明一下,正常的使用方法是这样的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span>y <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + x <span class="token operator">++</span> + y <span class="token operator">++</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + x <span class="token operator">=</span> a<span class="token operator">+</span>b + y <span class="token operator">=</span> a<span class="token operator">-</span>b + <span class="token keyword">return</span> +<span class="token punctuation">}</span> +</code></pre></div><p>也就是我们第一种使用的惯例,它的效果就是最后改变返回值,这也是这几种方式中最常用的方式。</p> <p>看了上文关于 defer 函数的初始化 int 类型参数以后,我们还得注意切片在 defer 函数初始化参数的问题,因为它更容易出现误判。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span>v <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span>s1<span class="token punctuation">)</span> + s1 <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span>v <span class="token operator">*</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token operator">&</span>s1<span class="token punctuation">)</span> + s1 <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><ul><li>前者输出 1 2 3</li> <li>后者输出 4 5 6</li></ul> <p>我们分析一下:</p> <blockquote><p><strong>❗️ 这个地方很容易搞错,望周知。</strong></p></blockquote> <p>首先我们确定的一件事就是:<strong>defer 函数的参数初始化是顺序执行的</strong>,它顺序执行之后,将数据保存在了一个专用的栈中。</p> <p>所以,第一个函数中,v 就等于 []int {1,2,3},换言之,v 初始化的时候等于一个指向底层数据是 1 2 3 的数组,所以当 s1 重新指向一个新的数据 4 5 6 的时候,v 的数据并不会有任何的影响,它仍然执行的还是底层数据是 1 2 3 的数组,所以它的最终结果就是输出 1 2 3</p> <p>第二个函数,在初始化阶段,v 正常的初始化,它的值是 s1 的地址,那么当下文中 s1 重新指向了一个新的底层数组为 4 5 6 的数据之后,v 的数据是一直跟着 s1 走的,因为它的本质是 s1 的地址,这把钥匙一直都没有变化,所以它的最终结果就是新的内容 4 5 6</p> <p>最后提一嘴,defer 函数的性能消耗 (go 1.14+),跟不使用 defer 相比,几乎没有差距,所以放心大胆的使用 defer。</p> <p><em><strong>输出调试信息</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">trace</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token builtin">string</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"prepare"</span><span class="token punctuation">,</span>s<span class="token punctuation">)</span> + <span class="token keyword">return</span> s +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">un</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"out"</span><span class="token punctuation">,</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">un</span><span class="token punctuation">(</span><span class="token function">trace</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"in a"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">b</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">un</span><span class="token punctuation">(</span><span class="token function">trace</span><span class="token punctuation">(</span><span class="token string">"b"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"in b"</span><span class="token punctuation">)</span> + <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">b</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// prepare b</span> +<span class="token comment">// in b</span> +<span class="token comment">// prepare a</span> +<span class="token comment">// in a</span> +<span class="token comment">// out a</span> +<span class="token comment">// out b </span> +</code></pre></div><p>这是 go 文档提供的一个日志记录的例子,接下来我们分析一下</p> <ul><li>首先 b 的执行,b 中的 defer 函数 un 开始初始化,它的初始化就是执行 trace (“b”),所以最先执行的是 prepare b</li> <li>然后开始执行 println (“in b”)</li> <li>接下来执行 a,跟 b 一样,先执行初始化的 un 中的 trace (“a”) 函数,然后执行 println (“in a”)</li> <li>然后开始执行 a 的 defer 函数,所以 a 的 out 先执行,(因为它后入,先出)</li> <li>接下来最后执行的是 b 中的 defer,那么就是 out b</li></ul> <p><em><strong>还原变量的旧值</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + oldfile <span class="token operator">:=</span> firstfile + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + firstfile <span class="token operator">=</span> oldfile + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + firstfile <span class="token operator">=</span> <span class="token string">"README.md"</span> + <span class="token comment">//...</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>我们知道,defer 后面只能放置函数,包括自匿名函数,或者是自定义的函数以及方法 (如果有返回值自动舍弃),那么 go 内置的函数是否可以放到 defer 后面执行呢?</strong></em></p> <p>答案是,部分内置函数可以直接放到 defer 后面,部分不能直接放到 defer 后面执行,需要放到一个匿名或者自定义函数中。</p> <ul><li>可以直接放到 defer 后面的函数有:close copy delete print recover</li> <li><strong>不能</strong>直接放到 defer 后面的函数有:append cap len make new</li></ul> <p>但是通常来说,我们使用 defer 的时候都是会跟一个匿名函数或者是自定义的函数,并不会直接跟一个内置函数。</p> <p>比如直接跟匿名函数的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"error"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>跟一个自定义函数的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + f<span class="token punctuation">,</span>err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"README.md"</span><span class="token punctuation">)</span> + + <span class="token comment">// defer 后面是一个方法,并且舍弃了这个方法的error参数</span> + <span class="token keyword">defer</span> f<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="defer-函数因为无法-return-造成的内存泄露-bug">defer 函数因为无法 return 造成的内存泄露 bug</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">readFiles</span><span class="token punctuation">(</span>ch <span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> path <span class="token operator">:=</span> <span class="token keyword">range</span> ch <span class="token punctuation">{</span> + file<span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> file<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// Do something with file</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在这个案例中,defer 函数用于关闭一个文件的句柄,假设我们在读取文件的过程中发生了 bug,readFile 永远无法 return nil,那么这个 defer 函数就永远不会实行,就会造成内存的泄露。</p> <p>改正的话,我们可以给 defer 函数 wrap 一层函数,在这个子函数中只要能 return,运行 defer 函数即可</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">readFiles</span><span class="token punctuation">(</span>ch <span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> path <span class="token operator">:=</span> <span class="token keyword">range</span> ch <span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">readFile</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +<span class="token comment">// 我们设置了一个新的函数,只要在这个函数里可以正常return 即可</span> +<span class="token keyword">func</span> <span class="token function">readFile</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + file<span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> file<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// Do something with file</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="再次强调-有无返回值具体变量对于-defer-的影响">再次强调:有无返回值具体变量对于 defer 的影响</h3> <p>有返回变量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 13</span> + <span class="token comment">// 12</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + i<span class="token operator">++</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">//13</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + i<span class="token operator">++</span> + i <span class="token operator">+=</span> <span class="token number">10</span> + <span class="token keyword">return</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>执行顺序是这样的: +1。i 初始化为原始数据 0 +2。i++ +3。i+= 10 +4。i++ +5。fmt.Println(i+1) // 13 +6。return 这个时候最终的 i // 12</p> <p>所以当拥有返回值变量的时候,return 返回的是最终的 i,就连 defer 中的 i 的变量也算上。</p> <p>无返回变量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 3</span> + <span class="token comment">// 11</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + i<span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + i<span class="token operator">++</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">//3</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + i<span class="token operator">++</span> + + <span class="token keyword">return</span> i <span class="token operator">+</span> <span class="token number">10</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>执行的顺序: +1。i 初始化为 0 +2。i++ +3。执行 i + 10 并把这个数据记录到 return 上去,但是并不会真的 return +4。i++ +5。fmt.Println(i+1)// 3 +6。defer 执行完毕以后,return 开始返回之前记录的那个值。</p> <p>为什么在这个没有返回变量的时候,i 在 defer 中的变化不会影响返回值呢,因为返回值记录的那个值发生在 defer 之前,所以 defer 再将 i 变化也不会影响之前记录的那个值了,那个值是已经固定的了,它没有立即返回是因为要执行 defer,你也可以理解为</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + i<span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + i<span class="token operator">++</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">//3</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + i<span class="token operator">++</span> + a <span class="token operator">:=</span> i<span class="token operator">+</span><span class="token number">10</span> + <span class="token keyword">return</span> a +<span class="token punctuation">}</span> +</code></pre></div><p>所以 a 的值是不会再受到 defer 中的 i 的变化的。</p> <h2 id="变长参数">变长参数</h2> <p>举个变长参数函数的例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Println</span><span class="token punctuation">(</span>a <span class="token operator">...</span>any<span class="token punctuation">)</span> <span class="token punctuation">(</span>n <span class="token builtin">int</span><span class="token punctuation">,</span> err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">Fprintln</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span>Stdout<span class="token punctuation">,</span> a<span class="token operator">...</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们平时使用的 <code>fmt.Println(...any)</code> 就是标准的变长参数的例子。</p> <p>它的组织形式就是 <code>...</code> + <code>类型</code>,比如 <code>...int</code> <code>...string</code></p> <ol><li>一个函数的参数中只能有一个变长参数,且必须为最后一位</li> <li>变长参数在函数内部以 slice 的方式存在</li> <li>变长参数只能接受两种形式的值,其一就是多个同样类型的值,例如 <code>fmt.Println("hi","there",12)</code>,或者直接接受一个 <code>slice...</code>,例如 <code>fmt.Println([]any{1, 2, "hi"}...)</code>,并且,这两种用法不能混用,比如 <code>fmt.Println(1,2,[]any{1,2}...)</code> 这种混写的方法错误。</li></ol> <p>any 类型和 string 类型是绝对的不同的两种类型,因为 any 是 interface {} 的别名 (<code>type any = interface{}</code>),string 类型虽然实现了空接口,但是它不是空接口类型,如果要转换成空接口,必须显式的转换:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">12</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + b <span class="token operator">:=</span> <span class="token function">any</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>go 语言在 append 字符串到[]byte 的时候提供了一个语法糖</strong></em></p> <p><code>func append(slice []Type, elems ...Type) []Type</code></p> <div class="language-go extra-class"><pre class="language-go"><code> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> b <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"ee"</span> + a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token operator">...</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这种语法糖只适用于 append 内置函数。底层应该是帮你把字符串转化为了 <code>[]byte()</code></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 类似这种转换</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> b <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"ee"</span> + c <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> c<span class="token operator">...</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>如果自己实现一个的时候不进行转换就会报错。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token builtin">byte</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + + <span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"123"</span><span class="token operator">...</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// ❌</span> +<span class="token comment">//cannot use "123" (untyped string constant)</span> +<span class="token comment">// as []byte value in argument to get</span> + +</code></pre></div><h3 id="使用变长函数去模拟重载函数">使用变长函数去模拟重载函数</h3> <p>重载函数就是同一个作用域下,可以有相同名称的函数,只不过他们的参数不同,go 语言是不支持这种类型的函数的。</p> <p>类似这种</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">get</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>如果真的想使用这种重载函数,我们可以使用这种方法来间接实现:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">,</span> args <span class="token operator">...</span>any<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> args <span class="token punctuation">{</span> + <span class="token keyword">switch</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token builtin">int8</span><span class="token punctuation">,</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">int16</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>vi<span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token builtin">string</span><span class="token punctuation">:</span> + + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +</code></pre></div><h3 id="使用变长函数去实现默认参数">使用变长函数去实现默认参数</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">CheckIn</span><span class="token punctuation">(</span><span class="token string">"shgopher"</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">,</span> <span class="token string">"男"</span><span class="token punctuation">)</span> + <span class="token function">CheckIn</span><span class="token punctuation">(</span><span class="token string">"jackie"</span><span class="token punctuation">,</span><span class="token number">20</span><span class="token punctuation">,</span><span class="token string">"男"</span><span class="token punctuation">,</span><span class="token string">"上海"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Contents <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Name <span class="token builtin">string</span> + Age <span class="token builtin">int</span> + Sex <span class="token builtin">string</span> + Address <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">CheckIn</span><span class="token punctuation">(</span>arges <span class="token operator">...</span>any<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>Contents<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + c <span class="token operator">:=</span> <span class="token operator">&</span>Contents<span class="token punctuation">{</span> + Address<span class="token punctuation">:</span> <span class="token string">"Beijing "</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> arges <span class="token punctuation">{</span> + <span class="token keyword">switch</span> k <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + name<span class="token punctuation">,</span> ok <span class="token operator">:=</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"name is not a string"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + c<span class="token punctuation">.</span>Name <span class="token operator">=</span> name + <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + age<span class="token punctuation">,</span> ok <span class="token operator">:=</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"age is not a int"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + c<span class="token punctuation">.</span>Age <span class="token operator">=</span> age + <span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span> + sex<span class="token punctuation">,</span> ok <span class="token operator">:=</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"sex is not a string"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + c<span class="token punctuation">.</span>Sex <span class="token operator">=</span> sex + <span class="token keyword">case</span> <span class="token number">3</span><span class="token punctuation">:</span> + address<span class="token punctuation">,</span> ok <span class="token operator">:=</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"address is not a string"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + c<span class="token punctuation">.</span>Address <span class="token operator">=</span> address + <span class="token keyword">default</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"unknown argument"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> c<span class="token punctuation">,</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码的意思就是先给定一个默认值,比如这里地址是默认值的,也即是它是可选的内容,鉴于这段代码标识的意义,这个可省略的一定是在最后一位的。</p> <h1 id="方法">方法</h1> <p>接下来,我们介绍方法,所谓方法,其实只是函数的一种语法糖,它跟函数并没有本质的区别,我们看一个简单的例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span><span class="token function">GetName</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s<span class="token punctuation">.</span>name <span class="token operator">=</span> name +<span class="token punctuation">}</span> +</code></pre></div><p>可以看到,这是一个定义在指针类型 <code>*student</code> 上的方法 <code>GetName</code>,实际上,它完全等于函数的这种形态:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">GetName</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">,</span> name <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s<span class="token punctuation">.</span>name <span class="token operator">=</span> name +<span class="token punctuation">}</span> +</code></pre></div><p>go 语言本身对于方法的使用是很宽泛的:</p> <ul><li>指针类型的变量可以使用值类型的方法</li> <li>值类型的变量可以使用指针类型的方法</li></ul> <p>这跟后文要讲的接口绝对是差距极大,因为接口的要求非常严格,这个可以看接口和函数的对比。</p> <p>值类型的变量可以使用指针类型的方法</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span><span class="token function">GetName</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s<span class="token punctuation">.</span>name <span class="token operator">=</span> name +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + s<span class="token punctuation">.</span><span class="token function">GetName</span><span class="token punctuation">(</span><span class="token string">"张三"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当值类型来使用指针类型的方法时,系统默认会调用这个值的指针,因此这是系统给予的语法糖。</p> <p>指针类型的变量可以使用值类型的方法</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>s Student<span class="token punctuation">)</span><span class="token function">GetName</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s<span class="token punctuation">.</span>name <span class="token operator">=</span> name +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student<span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">GetName</span><span class="token punctuation">(</span><span class="token string">"张三"</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"out:"</span><span class="token punctuation">,</span> s<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token comment">//out:</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当指针类型来使用值类型的方法时,系统默认会调用这个指针指向的值,因此这是系统给予的语法糖。</p> <p>这个例子其实是错误的行为,因为 s 的方法是定义在值类型的,使用一个 s 去调用它上面的 GetName,改变的只是方法中,s 的***复制品上***的值,外部调用的这个 s,实际上是不会有任何的改变的,我们如果从实质出发 <code>func GetName(s Student, name string)</code>,就能看出来了。</p> <p>跟函数以及全局变量,常量是一样的,方法也是首字母大写可以导出包,小写无法导出包。</p> <p>这里有个细节要注意一下,不能跨越包去定义方法,go 语言不支持,比如,原生类型 <code>(int,map,slice,bool 等)</code> 是无法提供方法的,例如</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>所以通常来说,我们就定义一个底层为 int 的新类型才可以</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A <span class="token builtin">int</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>a A<span class="token punctuation">)</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>那么我们总结一下关于方法的几个小细节:</p> <ul><li>方法首字母的大小写注定了是否可以导出包</li> <li>不能跨越包去定义方法</li> <li>每一个方法只能被一个类型去定义,不能俩类型去定义一个方法</li> <li><em><strong>指针类型和接口类型不能作为方法的基底类型</strong></em></li></ul> <p>最后一条,我们详细展开一下:</p> <p>以下定义是错误的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌ 指针类型不能有自己的方法</span> +<span class="token keyword">type</span> A <span class="token operator">*</span><span class="token builtin">int</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>a A<span class="token punctuation">)</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token comment">// ✅ 类型的指针可以有自己的方法</span> +<span class="token keyword">type</span> A <span class="token builtin">int</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>a <span class="token operator">*</span>A<span class="token punctuation">)</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// ❌ 接口类型不能有自己的方法</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>A<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌ 以接口为基底的类型不能有自己的方法</span> +<span class="token keyword">type</span> A xxInterface +<span class="token keyword">func</span><span class="token punctuation">(</span>a A<span class="token punctuation">)</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +</code></pre></div><h2 id="类型嵌入来完成继承">类型嵌入来完成继承</h2> <p>go 语言使用类型的嵌入来实现继承母体的对象以及对象上的方法。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>p <span class="token operator">*</span>People<span class="token punctuation">)</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>name<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>现在我们将类型嵌入到一个新的类型来实现继承:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + People + address <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span><span class="token function">Address</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>address<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + s<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Address</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们还可以重写继承的方法来完成重载操作:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>People<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">"学生"</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>当发生嵌入类型和本类型,字段重合的时候,优先调用本类型的字段,嵌入类型的只需要加上前缀就可以了。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + People + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + s<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"1"</span> + s<span class="token punctuation">.</span>People<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"2"</span> +<span class="token punctuation">}</span> +</code></pre></div><p>如果你不想直接嵌入,也可以在前面加上变量名称:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token comment">// 不嵌入也可以</span> + people People + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + s<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"1"</span> + s<span class="token punctuation">.</span>people<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"2"</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>不过,如果是不嵌入的方式,就无法直接调用方法了,需要加上前缀。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + s<span class="token punctuation">.</span>people<span class="token punctuation">.</span><span class="token function">name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>内置类型也可以作为字段直接嵌入到新类型中</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> a <span class="token keyword">struct</span><span class="token punctuation">{</span> + <span class="token builtin">int</span> + <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>不过使用的时候比较非常规了:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a1 a + a1<span class="token punctuation">.</span><span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">1</span> + a1<span class="token punctuation">.</span><span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"2"</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a1<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>指针类型也可以直接嵌入:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">type</span> a <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token builtin">int</span> + <span class="token builtin">string</span> + <span class="token operator">*</span>b +<span class="token punctuation">}</span> +<span class="token keyword">type</span> b <span class="token keyword">struct</span> <span class="token punctuation">{</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a1 a <span class="token operator">=</span> a<span class="token punctuation">{</span> + <span class="token builtin">int</span><span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> + <span class="token builtin">string</span><span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">,</span> + b<span class="token punctuation">:</span> <span class="token operator">&</span>b<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a1<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们可以看到,直接嵌入的时候,其实是省略了写法。但是通常,int string,这种内置的类型我们都会指定一个变量给他们。例如常规写法:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A <span class="token keyword">struct</span> <span class="token punctuation">{</span> + People + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + b <span class="token operator">*</span>b +<span class="token punctuation">}</span> +</code></pre></div><p>无论嵌入的是值类型还是指针类型,函数都可以直接调用他们身上的方法:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> People <span class="token keyword">struct</span><span class="token punctuation">{</span> + name <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>p <span class="token operator">*</span>People<span class="token punctuation">)</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>name<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Address <span class="token keyword">struct</span><span class="token punctuation">{</span> + value <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>a <span class="token operator">*</span>Address<span class="token punctuation">)</span><span class="token function">Value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">.</span>value<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + People + <span class="token operator">*</span>Address +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + <span class="token comment">//由于这里的address字段是指针,所以我们必须给address赋予实际的值的地址:</span> + s <span class="token operator">=</span> Student<span class="token punctuation">{</span> + Address<span class="token punctuation">:</span> <span class="token operator">&</span>Address<span class="token punctuation">{</span> + value<span class="token punctuation">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + s<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Value</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>s 是指针类型和值类型在调用实质上还是区别的,但是在实际使用中,并不会有什么区别,这主要还是因为要看方法是定义在值类型还是指针类型上。</p> <p>值类型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + s <span class="token operator">=</span> Student<span class="token punctuation">{</span> + Address<span class="token punctuation">:</span> <span class="token operator">&</span>Address<span class="token punctuation">{</span> + value<span class="token punctuation">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + s<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Value</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">*</span>Student + <span class="token comment">//由于这里的address字段是指针,所以我们必须给address赋予实际的值的地址:</span> + s <span class="token operator">=</span> <span class="token operator">&</span>Student<span class="token punctuation">{</span> + Address<span class="token punctuation">:</span> <span class="token operator">&</span>Address<span class="token punctuation">{</span> + value<span class="token punctuation">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + s<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Value</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当 s 是值时,它调用的就是 People 的方法 + *Address 的方法,</p> <p>但是如果 s 这里是指针类型的话,那么它调用的就是 *People 的方法 +*Address 的方法</p> <p>不过即便 s 是值的时候,people 上本身是定义在指针上的方法,那么它在底层调用的时候也势必是 *People</p> <p>总结一下:结构体变量是什么类型不重要,重要的是定义方法时使用的是什么类型。</p> <p>你也可以不使用嵌入,使用 <code>s.Address.Value()</code> 来调用方法:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + People People + Address <span class="token operator">*</span>Address +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s Student + <span class="token comment">//由于这里的address字段是指针,所以我们必须给address赋予实际的值的地址:</span> + s <span class="token operator">=</span> Student<span class="token punctuation">{</span> + Address<span class="token punctuation">:</span> <span class="token operator">&</span>Address<span class="token punctuation">{</span> + value<span class="token punctuation">:</span> <span class="token string">"1"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + s<span class="token punctuation">.</span>People<span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span>Address<span class="token punctuation">.</span><span class="token function">Value</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="define-类型的方法集合">define 类型的方法集合</h2> <p>define 就是 <code>type A int</code> 的意思 (type A = int 是另一个意思表示 alias),其中新类型 A 叫做 define 类型,int 叫做 underlying 类型</p> <p>define 类型的底层如果是接口,那么它完全可以 “继承” 底层数据的方法,比如底层接口拥有三个抽象函数,那么它也有三个一模一样的三个抽线函数</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Hello, 世界"</span><span class="token punctuation">)</span> + + <span class="token keyword">var</span> b B + <span class="token keyword">var</span> d D + b <span class="token operator">=</span> d + b<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> A <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> B A + +<span class="token keyword">type</span> D <span class="token builtin">int</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>D<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>但是,如果不是接口类型,那么这个类型上就什么方法都没有。它跟它底层的 underlying 将没有任何的联系。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Hello, 世界"</span><span class="token punctuation">)</span> + <span class="token keyword">var</span> a1 a + a1<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token keyword">var</span> b1 b + b1<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> a <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> b a + +<span class="token comment">// error: b1.get undefined (type b has no field or method get)</span> +</code></pre></div><h2 id="类型别名的方法集合">类型别名的方法集合</h2> <p>接下来我们介绍一个类型的别名 alias</p> <p>使用方法是这样的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> <span class="token builtin">rune</span> <span class="token operator">=</span> <span class="token builtin">int32</span> +</code></pre></div><p>可以看到跟</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> <span class="token builtin">rune</span> <span class="token builtin">int32</span> +</code></pre></div><p>非常像,但是,我要强调一下,这两者是完全不同的东西。前者是类型别名,rune 就是 int32 的一个分身,它跟 int32 完全拥有相同的权利,后者,rune 和 int32 是完全两个类型,只是 rune 使用了 int32 作为自己的底层数据而已。</p> <p>我们看一个例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Hello, 世界"</span><span class="token punctuation">)</span> + + <span class="token keyword">var</span> h hiInterface + <span class="token keyword">var</span> hi hiStruct + h <span class="token operator">=</span> hi + + h<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> myInterface <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> myStruct <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>myStruct<span class="token punctuation">)</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> hiInterface <span class="token operator">=</span> myInterface +<span class="token keyword">type</span> hiStruct <span class="token operator">=</span> myStruct + +</code></pre></div><p>可以看到,别名和类型之间,完全相同,完全等价,不管是接口还是结构体,亦或者是其它的东西。</p> <h2 id="函数式编程">函数式编程</h2> <p>函数就是一个普通的类型,它跟 int,string,拥有相同的地位,所以你会发现函数式编程在 go 语言的代码里运用的很广泛。</p> <p>比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a<span class="token punctuation">,</span> <span class="token boolean">_</span> <span class="token operator">:=</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">,</span> f <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">f</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>函数作为 go 语言中的一等公民,拥有以下特征:</p> <ul><li>在源码的顶层正常的创建函数</li> <li>函数可以存在于函数内部</li> <li>函数可以作为类型</li> <li>函数可以赋值给一个变量</li> <li>函数可以作为参数</li> <li>函数可以作为返回值,并且拥有闭包</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 在源码的顶层正常的创建函数</span> +<span class="token comment">// main.go</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数可以存在于函数内部</span> + +fun <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token function">println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数可以作为类型</span> +<span class="token keyword">type</span> A <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数可以赋值给一个变量</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token function">println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数可以作为参数</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">,</span> f1 <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">f1</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 函数可以作为返回值,并且拥有闭包</span> +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + g <span class="token operator">:=</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span><span class="token string">"hello"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span><span class="token string">"world"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span><span class="token string">"--------------------------------"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">g</span><span class="token punctuation">(</span><span class="token string">"你好"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + i <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + i<span class="token operator">++</span> + <span class="token keyword">return</span> i + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token comment">//out</span> +<span class="token comment">//hello</span> +<span class="token comment">// 1</span> +<span class="token comment">// world</span> +<span class="token comment">// 2</span> +<span class="token comment">// --------------------------------</span> +<span class="token comment">// 3</span> +<span class="token comment">// hi</span> +<span class="token comment">// 4</span> +<span class="token comment">// 你好</span> +<span class="token comment">// 5</span> + +</code></pre></div><h3 id="函数式编程的实际应用">函数式编程的实际应用</h3> <p><em><strong>柯里化函数</strong></em></p> <p>概念:接受多个参数的函数,变成接受一个单一参数的函数,并且返回接受剩余参数以及返回值的新函数。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">sum</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> c <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> x <span class="token operator">+</span> y <span class="token operator">+</span> c +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">partialSum</span><span class="token punctuation">(</span>x <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>y<span class="token punctuation">,</span> c <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">sum</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> c<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + t1 <span class="token operator">:=</span> <span class="token function">partialSum</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + t2 <span class="token operator">:=</span> <span class="token function">partialSum</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + t3 <span class="token operator">:=</span> <span class="token function">partialSum</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">t1</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">t2</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">t3</span><span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p><em><strong>函子</strong></em></p> <p>概念:functor (函子) 本身是一个容器 (slice map channel),容器类型实现一个方法,该方法接受一个函数类型参数,并且每一个容器参数都要被这个函数去改变,这里会得到一个新的 functor,原有的容器没有任何的影响。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">type</span> IntSliceFunctor <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Fmap</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">)</span> IntSliceFunctor +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> IntSliceFunctorImpl <span class="token keyword">struct</span> <span class="token punctuation">{</span> + ints <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>f IntSliceFunctorImpl<span class="token punctuation">)</span> <span class="token function">Fmap</span><span class="token punctuation">(</span>f1 <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">)</span> IntSliceFunctor <span class="token punctuation">{</span> + newInts <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>f<span class="token punctuation">.</span>ints<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> f<span class="token punctuation">.</span>ints <span class="token punctuation">{</span> + newInts<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">f1</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> IntSliceFunctorImpl<span class="token punctuation">{</span>newInts<span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewIntSliceFunctorImpl</span><span class="token punctuation">(</span>ints <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">)</span> IntSliceFunctor <span class="token punctuation">{</span> + <span class="token keyword">return</span> IntSliceFunctorImpl<span class="token punctuation">{</span>ints<span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + i <span class="token operator">:=</span> <span class="token function">NewIntSliceFunctorImpl</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + m1 <span class="token operator">:=</span> i<span class="token punctuation">.</span><span class="token function">Fmap</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> i <span class="token operator">*</span> <span class="token number">2</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + m1p <span class="token operator">:=</span> i<span class="token punctuation">.</span><span class="token function">Fmap</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> i <span class="token operator">*</span> <span class="token number">20</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + m2 <span class="token operator">:=</span> m1<span class="token punctuation">.</span><span class="token function">Fmap</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> i <span class="token operator">*</span> <span class="token number">20</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m1<span class="token punctuation">,</span> m1p<span class="token punctuation">,</span> m2<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p><em><strong>配置选项问题</strong></em></p> <p><em><strong>最基础的方法就是全部暴露出去</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Server <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + Port <span class="token builtin">int</span> + Protocol <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewDefalutServer</span><span class="token punctuation">(</span>addr <span class="token builtin">string</span><span class="token punctuation">,</span>port <span class="token builtin">int</span><span class="token punctuation">,</span>protocol <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator">*</span>Server <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token operator">&</span>Server<span class="token punctuation">{</span> + addr<span class="token punctuation">,</span> + port<span class="token punctuation">,</span> + protocol<span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewPortServer</span><span class="token punctuation">(</span>addr <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">*</span>Server <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token operator">&</span>Server<span class="token punctuation">{</span> + addr<span class="token punctuation">,</span> + <span class="token string">"8080"</span><span class="token punctuation">,</span> + <span class="token string">"tcp"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>直接暴露这是一种最基础的方案,这种方法可扩展性很差。</p> <p>如果想改进,完全可以把非固定的字段单独的封装在一个 struct 中,比如这种写法:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Server <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + options <span class="token operator">*</span>Options + +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Options <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Port <span class="token builtin">string</span> + Protocol <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewServer</span><span class="token punctuation">(</span>addr <span class="token builtin">string</span><span class="token punctuation">,</span> options <span class="token operator">*</span>Options<span class="token punctuation">)</span> <span class="token operator">*</span>Server <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token operator">&</span>Server<span class="token punctuation">{</span> + addr<span class="token punctuation">,</span> + options<span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>还有一种场景是这样的,我们输出的 API 是一定的,但是我们的配置信息,因为是共同使用的,它可能会越来越多,这个时候改如何处理呢?</p> <p><em><strong>设置一个固定的 struct,以及一个可共用的 opintions struct</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Server <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + Port <span class="token builtin">int</span> + Protocol <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Options <span class="token keyword">struct</span><span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + Port <span class="token builtin">int</span> + Protocol <span class="token builtin">string</span> + +<span class="token punctuation">}</span> + <span class="token comment">// 这种写法,API内容不变,共同的options即便是变化了也无关紧要。</span> +<span class="token keyword">func</span> <span class="token function">NewServer</span><span class="token punctuation">(</span>options <span class="token operator">*</span>Options<span class="token punctuation">)</span> <span class="token operator">*</span>Server <span class="token punctuation">{</span> + <span class="token keyword">var</span> addr <span class="token builtin">string</span> + <span class="token keyword">var</span> port <span class="token builtin">int</span> + <span class="token keyword">var</span> protocol <span class="token builtin">string</span> + + <span class="token keyword">if</span> options <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + addr <span class="token operator">=</span> options<span class="token punctuation">.</span>Addr + port <span class="token operator">=</span> options<span class="token punctuation">.</span>Port + protocol <span class="token operator">=</span> options<span class="token punctuation">.</span>Protocol + <span class="token punctuation">}</span> + + <span class="token keyword">return</span> <span class="token operator">&</span>Server<span class="token punctuation">{</span> + addr<span class="token punctuation">,</span> + port<span class="token punctuation">,</span> + protocol<span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>我们还可以使用链式调用的方式去写这种参数</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Server <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + Port <span class="token builtin">int</span> + Protocol <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> ServerBulder <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Server +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>sb <span class="token operator">*</span>ServerBulder<span class="token punctuation">)</span> <span class="token function">Build</span><span class="token punctuation">(</span>addr <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator">*</span>ServerBulder <span class="token punctuation">{</span> + sb<span class="token punctuation">.</span>Addr <span class="token operator">=</span> addr + <span class="token keyword">return</span> sb +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>sb <span class="token operator">*</span>ServerBulder<span class="token punctuation">)</span> <span class="token function">BuildWithPort</span><span class="token punctuation">(</span>port <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">*</span>ServerBulder <span class="token punctuation">{</span> + sb<span class="token punctuation">.</span>Port <span class="token operator">=</span> port + <span class="token keyword">return</span> sb +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>sb <span class="token operator">*</span>ServerBulder<span class="token punctuation">)</span> <span class="token function">BuildWithProtocol</span><span class="token punctuation">(</span>protocol <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">*</span>ServerBulder <span class="token punctuation">{</span> + sb<span class="token punctuation">.</span>Protocol <span class="token operator">=</span> protocol + <span class="token keyword">return</span> sb +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>sb <span class="token operator">*</span>ServerBulder<span class="token punctuation">)</span> <span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>Server<span class="token punctuation">{</span> + <span class="token keyword">return</span> sb<span class="token punctuation">.</span>Server +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>functional Options --- 功能选项模式</strong></em></p> <p>使用场景:在一个配置中心,我们并不想把配置的 struct 暴漏出去,那么我们可以将这个 struct 定义为非导出类型,然后我们定义一个可导出的函数类型,将这个 struct 设置为函数的参数,使用这个可导出的函数来完成配置的操作。</p> <p>首先是定义一个函数类型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Option <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token operator">*</span>server<span class="token punctuation">)</span> + +<span class="token keyword">type</span> server <span class="token keyword">struct</span> <span class="token punctuation">{</span> + addr <span class="token builtin">string</span> + port <span class="token builtin">int</span> + protocol <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们使用函数式的方式去定义一组函数</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">WithPort</span><span class="token punctuation">(</span>port <span class="token builtin">int</span><span class="token punctuation">)</span> Options <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>server<span class="token punctuation">)</span> <span class="token punctuation">{</span> + s<span class="token punctuation">.</span>port <span class="token operator">=</span> port + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">WithProtocol</span><span class="token punctuation">(</span>protocol <span class="token builtin">string</span><span class="token punctuation">)</span> Options <span class="token punctuation">{</span> + retrun <span class="token keyword">func</span><span class="token punctuation">(</span>s <span class="token operator">*</span>server<span class="token punctuation">)</span> <span class="token punctuation">{</span> + s<span class="token punctuation">.</span>protocol <span class="token operator">=</span> protocol + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewServer</span><span class="token punctuation">(</span>addr <span class="token builtin">string</span><span class="token punctuation">,</span> options <span class="token operator">...</span>Option<span class="token punctuation">)</span> <span class="token operator">*</span>server <span class="token punctuation">{</span> + serv <span class="token operator">:=</span> server<span class="token punctuation">{</span> + addr<span class="token punctuation">,</span> + <span class="token string">"8080"</span><span class="token punctuation">,</span> + <span class="token string">"tcp"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> opt <span class="token operator">:=</span> <span class="token keyword">range</span> options <span class="token punctuation">{</span> + <span class="token function">opt</span><span class="token punctuation">(</span><span class="token operator">&</span>serv<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 接下来的处理</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"xx/example"</span> +<span class="token punctuation">)</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + example<span class="token punctuation">.</span><span class="token function">NewServer</span><span class="token punctuation">(</span><span class="token string">"bj"</span><span class="token punctuation">,</span>example<span class="token punctuation">.</span><span class="token function">WithPort</span><span class="token punctuation">(</span><span class="token string">"8080"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>example<span class="token punctuation">.</span><span class="token function">WithProtocol</span><span class="token punctuation">(</span><span class="token string">"tcp"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>如你所见,使用了函数作为返回值,函数作为参数,变长函数以及闭包等知识,去完成了 “functional options” 这种函数式编程的模式。 +在这个场景下,我们扩展配置变得非常容易,并不需要更改现有的代码,并且也防止了配置 struct 的外漏。</p> <h3 id="这里还有关于函数式编程其它相关内容">这里还有关于函数式编程其它相关内容:</h3> <blockquote><p>这里的主要内容来自酷壳 https://coolshell.cn/?s=GO+编程模式 (R.I.P 耗子叔)</p></blockquote> <ul><li><a href="/GOFamily/基础/函数方法/0.html">反转控制</a></li> <li><a href="/GOFamily/基础/函数方法/1.html">map-reduce</a></li> <li><a href="/GOFamily/基础/函数方法/3.html">修饰器</a></li> <li><a href="/GOFamily/基础/函数方法/4.html">pipeline</a></li> <li><a href="/GOFamily/基础/函数方法/5.html">k8s visitor</a></li> <li>k8s builder</li> <li><a href="/GOFamily/基础/函数方法/7.html">综合题</a></li></ul> <h2 id="issues">issues</h2> <p><code>问题一:</code> <em><strong>关于方法的一道题:判断输出</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">*</span>Student<span class="token punctuation">{</span> + <span class="token punctuation">{</span><span class="token string">"一"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span><span class="token string">"二"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span><span class="token string">"三"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> a <span class="token punctuation">{</span> + <span class="token keyword">go</span> v<span class="token punctuation">.</span><span class="token function">pName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + + <span class="token keyword">var</span> b <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>Student<span class="token punctuation">{</span> + <span class="token punctuation">{</span><span class="token string">"四"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span><span class="token string">"五"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span><span class="token string">"六"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> b <span class="token punctuation">{</span> + <span class="token keyword">go</span> v<span class="token punctuation">.</span><span class="token function">pName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span> <span class="token function">pName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>name<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>答案是:</p> <div class="language-go extra-class"><pre class="language-go"><code>三 +六 +六 +一 +二 +六 +</code></pre></div><p>回答:</p> <p>可以看到,我们期望的一二三四五六并没有输出,这里不考虑顺序,那么四和五为什么没有输出呢?这个时候我们应该考虑方法的本质。</p> <p>首先我们定了一个在指针类型上的方法 pName,所以第一个 for 循环中,实际上的运行是,每一个指针类型,然后定义在他们上面的方法,并且输出,但是第二个他们是值类型,go 的编译器自动给引出了指针类型,所以说按照指针的实质</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">pName</span><span class="token punctuation">(</span>s <span class="token operator">*</span>Student<span class="token punctuation">)</span> <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>这里放置的就是 &v,还有个大的原因,就是整个 for 循环比开辟一个新的 goroutine 并且运行完毕远远的快,所以当三个 goroutine 开辟完成的时候,所引用的&v 就是同一个数据了。所以这个时候输出的就是同样的最后的数据值,也就是 “六”,不过这里如果 for 的每一次循环事件都很长,那么 goroutine 运行将会输出 “四五六”。</p> <p>如果想正常的输出,可以把定义在指针上的方法,改成定义在值上的方法即可。</p> <p><code>问题二:</code> <em><strong>panic(nil) 时,defer 函数中的 recover() == nil 成立吗</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"reflect"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> + + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token boolean">nil</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>答案是:</p> <p>当 go1.21+ 的时候,不成立,在小于 1.21 的版本中是成立的。</p> <p>在 1.21 以下,panic 中的 nil 是会传递给 recover() 函数的,所以必定是 true,但是在 1.21+的版本中,<code>panic(nil)</code> 在编译时,底层修改为了 <code>panic(new(runtime.PanicNilError))</code></p> <p>所以说,nil 是不等于 *runtime.PanicNilError 的,综上所述,小于 1.21 的版本成立,大于 1.21 的版本不成立。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://book.douban.com/subject/35720728/ 170 页 - 243 页</li> <li>https://coolshell.cn/?s=GO+编程模式</li> <li>https://github.com/golang/go/blob/06264b740e3bfe619f5e90359d8f0d521bd47806/src/database/sql/sql.go#L813</li> <li>https://github.com/lib/pq/blob/922c00e176fb3960d912dc2c7f67ea2cf18d27b0/conn.go#L60</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/函数方法/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/16/2024, 9:10:50 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/8.ff976029.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\217\230\351\207\217\345\243\260\346\230\216/index.html" "b/\345\237\272\347\241\200/\345\217\230\351\207\217\345\243\260\346\230\216/index.html" new file mode 100644 index 000000000..8ae18f2fa --- /dev/null +++ "b/\345\237\272\347\241\200/\345\217\230\351\207\217\345\243\260\346\230\216/index.html" @@ -0,0 +1,145 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>变量声明 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/37.18cb13d8.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>变量声明</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#变量声明符号-var-和" class="sidebar-link">变量声明符号 var 和 :=</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#常见的变量声明方式" class="sidebar-link">常见的变量声明方式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#go-语言可导出变量" class="sidebar-link">go 语言可导出变量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#包级变量" class="sidebar-link">包级变量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#函数级变量" class="sidebar-link">函数级变量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#小心-shadow-的变量" class="sidebar-link">小心 shadow 的变量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="变量声明">变量声明</h1> <h2 id="变量声明符号-var-和">变量声明符号 <code>var</code> 和 <code>:=</code></h2> <p>在 go 语言中,我们使用 <code>var</code> 来表示声明一个变量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> a <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"hello world"</span> +</code></pre></div><p>这就是一个标准的变量声明方式,var 符号在最前面,接着就是变量 a,变量后面紧跟着是变量的类型,这里是 string 类型,也就是字符串类型,<code>=</code> 后面是要赋值的具体值</p> <p>我们也可以直接声明不赋予初始值,go 语言默认,声明即赋予初始值,那么这里的字符串类型初始值就是一个空字符串 <code>""</code></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> a <span class="token builtin">string</span> +</code></pre></div><p>go 语言具有类型推断能力,所以我们可以省略类型,让 go 语言的编译器去推断类型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token string">"hello world"</span> +</code></pre></div><p>编译器会自动推断 a 为 string 类型</p> <p>在函数体内部 (这是一个先决条件) 我们<strong>也</strong>可以使用省略的写法,就是使用一个符号 <code>:=</code> 来充当 <code>var</code> 的角色,也就是初始化的工作,比如说</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token string">"hello world"</span> +<span class="token punctuation">}</span> +</code></pre></div><p>可以看到,整个的用法是 <code>[变量] [:=] [初始值]</code> 这三者缺一不可,而且还不能多,不能在 a 后面带有类型,不能省略初始值,且仅限于函数/方法内部使用</p> <p>go 语言支持多变量同时赋值</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> a<span class="token punctuation">,</span> b <span class="token builtin">string</span> + +<span class="token keyword">var</span> c<span class="token punctuation">,</span> d <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"1"</span><span class="token punctuation">,</span> <span class="token string">"2"</span> + +a<span class="token punctuation">,</span> b <span class="token operator">:=</span> <span class="token string">"hello world"</span><span class="token punctuation">,</span><span class="token number">12</span> +</code></pre></div><p>其中,使用 var 进行声明的时候,如果是多个变量同时声明,必须是相同类型;使用 <code>:=</code> 进行多变量赋值时,多个变量可以不同类型,因为全靠编译器推断</p> <h2 id="常见的变量声明方式">常见的变量声明方式</h2> <p>从广义上来说,go 语言只有两种变量,包一级的变量和函数一级的变量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> DefaultValue <span class="token builtin">int</span> + +<span class="token keyword">func</span> <span class="token function">NewMethod</span><span class="token punctuation">(</span>n <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>其中 <code>DefaultValue</code> 就是包级变量,<code>n</code> 就是函数级变量 (也是形式变量)</p> <p>下面我列举一些常见的声明方式</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> <span class="token punctuation">(</span> + a <span class="token builtin">string</span> + b <span class="token builtin">int32</span> <span class="token operator">=</span> <span class="token number">1</span> +<span class="token punctuation">)</span> + +<span class="token keyword">var</span> c <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">string</span> <span class="token comment">//包级变量</span> + +<span class="token keyword">func</span> <span class="token function">hi</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + d <span class="token operator">:=</span> <span class="token number">12</span> <span class="token comment">//仅限函数内部使用,变量后面不能有类型</span> + <span class="token keyword">var</span> c <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">string</span> <span class="token comment">// 函数级变量</span> + <span class="token keyword">var</span> e <span class="token operator">=</span> <span class="token string">"hello world"</span> <span class="token comment">//自动推断变量类型</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>可以说声明的方式很多,不过呢,在一个项目中应该尽量保证声明方式的一致性,因为可以加强代码的统一性,减少理解代码的难度。</p> <h2 id="go-语言可导出变量">go 语言可导出变量</h2> <p>go 语言跟一般的语言不同,它使用变量<strong>首</strong>字母的大小写来区分变量的可导出性质,大写 (如果使用中文作为变量名称,默认是可导出的) 代表可导出,小写代表仅限包内部使用 (包这一级,多个文件只要是同一个包就可以使用)</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> Example + +<span class="token keyword">var</span> OutPutName <span class="token operator">=</span> <span class="token number">0o77</span> +<span class="token keyword">var</span> inName <span class="token operator">=</span> <span class="token number">0x99</span> +</code></pre></div><p>其中 <code>OutPutName</code> 是一个可导出的变量,<code>inName</code> 是不可导出变量</p> <p>go 语言还拥有比如函数,方法,结构体,接口,等等各类型的组件,这里你可以先不懂到底是什么,你先有一个印象,但凡首字母是大写的都是可以导出的,小写就是包内使用,没错,go 语言就是这么简单</p> <h2 id="包级变量">包级变量</h2> <p><code>第一种声明形式</code>:<strong>声明的同时,显式初始化</strong></p> <ul><li><code>var a = method("t")</code> go 编译器根据右侧的返回值自动确定左侧变量的类型</li> <li><code>var a = 3.14</code> 在没有具体返回值,没有具体类型的情况下,go 赋予它默认类型,比如 float 的默认类型就是 float64,int 类型的默认类型就是 int</li> <li>如果要显式的赋予类型,并且保证命名的一致性 <code>var a int = 12</code> 的行为应该避免,应该写成 <code>var a = int(12)</code> 用来保证一致性<div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token number">3.14</span> + b <span class="token operator">=</span> <span class="token function">int</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span> + e <span class="token operator">=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"EOF"</span><span class="token punctuation">)</span> +<span class="token punctuation">)</span> +</code></pre></div></li></ul> <p><code>第二种声明形式</code>:<strong>声明但是延迟初始化</strong></p> <p>只有 <code>var a int64</code> 这一种方式,不过呢,go 语言的声明是直接赋予零值的,比如说这里的 a 默认就是 <code>0</code></p> <p>go 语言变量声明的聚集和就近原则:将同一类型的放在一个 var() 内部;或者另一种分类方法:将有初始值的放在一个 var 里,将延迟初始化的放在另一个 var 里。</p> <p>分类一</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span><span class="token punctuation">(</span> +a <span class="token builtin">int</span> +b <span class="token builtin">int</span> +c <span class="token builtin">int</span> +<span class="token punctuation">)</span> +<span class="token keyword">var</span><span class="token punctuation">(</span> +d <span class="token builtin">string</span> +e <span class="token builtin">string</span> +f <span class="token builtin">string</span> +<span class="token punctuation">)</span> +</code></pre></div><p>分类二</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token number">12</span> + b <span class="token operator">=</span> <span class="token string">"string"</span> + c <span class="token operator">=</span> <span class="token string">"string"</span> +<span class="token punctuation">)</span> +<span class="token keyword">var</span><span class="token punctuation">(</span> + d <span class="token builtin">int</span> + c <span class="token builtin">string</span> + f <span class="token builtin">bool</span> +<span class="token punctuation">)</span> +</code></pre></div><p>接下来谈一谈就近原则,变量的声明和变量的使用尽量的近,不要都声明在头部,如果一个变量被全局大量使用,那么可以放在头部,如果就是仅仅使用少量的次数,还是应该在使用的前面就进进行声明</p> <h2 id="函数级变量">函数级变量</h2> <p><code>第一种声明形式</code>:<strong>延迟初始化</strong></p> <p>在函数体内使用 var</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">Method</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><p>如果变量特别多,也可以使用 <code>var()</code> 的方法在函数内部使用</p> <p><code>第二种声明形式</code>:<strong>声明且显式初始化的局部变量</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token number">12</span> + b <span class="token operator">:=</span> <span class="token function">int32</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span> <span class="token comment">// 改变默认类型</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="小心-shadow-的变量">小心 shadow 的变量</h2> <p>我们知道,当有两个两个以上的变量在赋值时,如果其中有一个未被提前声明,那么就需要使用 <code>:=</code>,这个时候系统会自动判断有哪些未提前声明,然而有一种场景下系统会发生误判,准确的来说这是一种歧义,系统的判断会跟程序员的心理不一致,出现了变量 shadow 的行为,让我们看一下代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">WithName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token builtin">string</span> + <span class="token comment">// tracing 为 bool 类型</span> + <span class="token keyword">if</span> tracing<span class="token punctuation">{</span> + a<span class="token punctuation">,</span>err <span class="token operator">:=</span> example<span class="token punctuation">.</span><span class="token function">Method</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + a<span class="token punctuation">,</span>err <span class="token operator">:=</span> example<span class="token punctuation">.</span><span class="token function">Method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在外层,a 已经提前声明,但是在 if 这个作用域中,由于 err 并未提前声明,所以使用了 <code>:=</code>,由于系统<strong>无法获知</strong>这里的 a 是否需要再次声明,所以 go 语言默认 a 是一个新的变量,这样外层的 a 就无法得到新的值,外层 a 也就被内层的 a 给 shadow 了。</p> <p>如果想改变这种 bug,我们可以将 err 也提前声明:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">WithName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token builtin">string</span> + <span class="token keyword">var</span> err <span class="token builtin">error</span> + <span class="token comment">// tracing 为 bool 类型</span> + <span class="token keyword">if</span> tracing<span class="token punctuation">{</span> + a<span class="token punctuation">,</span>err <span class="token operator">=</span> example<span class="token punctuation">.</span><span class="token function">Method</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + a<span class="token punctuation">,</span>err <span class="token operator">=</span> example<span class="token punctuation">.</span><span class="token function">Method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>或者也可以改变内部的变量名称,来改变这种 shadow:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">WithName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token builtin">string</span> + <span class="token comment">// tracing 为 bool 类型</span> + <span class="token keyword">if</span> tracing<span class="token punctuation">{</span> + ai<span class="token punctuation">,</span>err <span class="token operator">:=</span> example<span class="token punctuation">.</span><span class="token function">Method</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + a <span class="token operator">=</span> ai + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + ai<span class="token punctuation">,</span>err <span class="token operator">:=</span> example<span class="token punctuation">.</span><span class="token function">Method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + a <span class="token operator">=</span> ai + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="参考资料">参考资料</h2> <ul><li>https://juejin.cn/post/7241452578125824061</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/变量声明/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/37.18cb13d8.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\244\215\345\220\210\345\255\227\351\235\242\351\207\217/index.html" "b/\345\237\272\347\241\200/\345\244\215\345\220\210\345\255\227\351\235\242\351\207\217/index.html" new file mode 100644 index 000000000..2fefde9ab --- /dev/null +++ "b/\345\237\272\347\241\200/\345\244\215\345\220\210\345\255\227\351\235\242\351\207\217/index.html" @@ -0,0 +1,94 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>复合字面量作为构造器 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/38.53670642.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>复合字面量作为构造器</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="复合字面量作为构造器">复合字面量作为构造器</h1> <p>go 的复杂类型经常采用复合字面量的方式进行初始化,例如 struct,数组,slice map,比如:</p> <div class="language-go extra-class"><pre class="language-go"><code>a <span class="token operator">:=</span> Some<span class="token punctuation">{</span> + name<span class="token punctuation">:</span><span class="token string">"hi there"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span><span class="token number">12</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> +arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">}</span> + +sl <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + +m <span class="token operator">:=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token number">1</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span> + <span class="token number">2</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">,</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当 struct 需要使用 <code>{key :value}</code> 来构建时,即使可以按照顺序省略掉 key,也千万不要这么做,加上 key 就可以将结构体的<strong>使用和设计解耦</strong>,可以乱序进行 struct 的赋值,即使某些字段没有赋值,那么系统也会自动的赋予它的初始值。</p> <p>当获取 struct 的指针时,最好是在字面量上取 <code>&</code>,比取变量的指针地址更加符合具体的含义,即:获取结构体的指针类型并且复制给一个变量。比如 <code>a := &Some{}</code> 就比 <code>a := Some{} , &a</code> 更好,另外当我们要获取一个结构体的初始值的时候使用 <code>a := Some{}</code> 比 <code>a = new(Some)</code> 更加常用。</p> <p>数组和切片的复合体跟 struct 不同,它使用下标来作为 key,它们几乎不会使用 key:value 的形式,不过下面两种情况还是会出现的:</p> <ul><li>为了省略中间元素</li> <li>为了显著的体现下标</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//为了省略中间元素</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">12</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span> + b <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token char">'a'</span><span class="token punctuation">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token char">'b'</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token comment">// 这里 '' 代表了 rune类型</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span>b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//为了显著的体现下标</span> +<span class="token keyword">var</span> data <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span> <span class="token number">0</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">:</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">:</span><span class="token number">3</span> <span class="token punctuation">}</span> +</code></pre></div><p>当 slice 和 array 含有复合类型的时候,可以直接省略复合类型的类型名称,直接用 <code>{}</code> 即可</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>Some<span class="token punctuation">{</span> + <span class="token punctuation">{</span> + name<span class="token punctuation">:</span> <span class="token string">"12"</span><span class="token punctuation">,</span> <span class="token comment">// 这里尽量不要省略字段名称,方便解除跟结构体设计时的耦合</span> + year<span class="token punctuation">:</span> <span class="token number">12</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span> + name<span class="token punctuation">:</span> <span class="token string">"12"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span> <span class="token number">12</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Some <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> + p <span class="token builtin">bool</span> +<span class="token punctuation">}</span> +</code></pre></div><p>map 字面量作为初始值的时候,非常自然的就会使用 key-value 的方式,需要注意两点</p> <ul><li>当 value 或者 key 是复合类型的时候 (key 必须是<a href="/GOFamily/基础/其他内容/#go可比较类型">可比较的</a>) 可以省略复合类型的类型名称</li> <li>如果是指针类型,那么连指针也可以省略</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/复合字面量/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/38.53670642.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\345\270\270\351\207\217\345\243\260\346\230\216/index.html" "b/\345\237\272\347\241\200/\345\270\270\351\207\217\345\243\260\346\230\216/index.html" new file mode 100644 index 000000000..4c45a60ad --- /dev/null +++ "b/\345\237\272\347\241\200/\345\270\270\351\207\217\345\243\260\346\230\216/index.html" @@ -0,0 +1,146 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 语言常量 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/39.9c8315fb.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 语言常量</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/#局部常量" class="sidebar-link">局部常量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/#常量不可包含计算" class="sidebar-link">常量不可包含计算</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E5%B8%B8%E9%87%8F%E5%A3%B0%E6%98%8E/#枚举常量-iota" class="sidebar-link">枚举常量 iota</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-语言常量">go 语言常量</h1> <p>go 使用 const 来声明常量,常量表达式的运算在编译期就可以完成了,并且 go 常量是类型安全的,编译器优化友好的元素。</p> <p>常量中的数据类型只可以是布尔、数字 (整数、浮点和复数) 以及字符串型。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + startOne <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">2</span> + startTwo <span class="token operator">=</span> <span class="token number">1.0</span> + startThree <span class="token operator">=</span> <span class="token number">3.14</span> + isTrue <span class="token operator">=</span> <span class="token boolean">true</span> + hi <span class="token operator">=</span> <span class="token string">"hi"</span> +<span class="token punctuation">)</span> +</code></pre></div><p>go 推崇无类型常量,这主要是因为 go 不支持隐式的类型转化,只能显式转换,所以一旦常量给定类型,那么它跟变量之间或许就要将常量转化类型才能进行运算。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">const</span> <span class="token punctuation">(</span> + PI <span class="token operator">=</span> <span class="token number">3.14</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token builtin">float32</span> <span class="token operator">=</span> PI + <span class="token keyword">var</span> b <span class="token builtin">float64</span> <span class="token operator">=</span> PI +<span class="token punctuation">}</span> + +</code></pre></div><p>可以看到,如果是没有类型的常量,可以非常灵活的赋予 float32 或者 float64 都可以。</p> <h2 id="局部常量">局部常量</h2> <p>在 Go 中,局部常量在编译期常量折叠 (compile-time constant folding) 时会被编译器处理成字面值,因此局部常量在编译时会被编译。</p> <p>例如,下面的代码定义了一个局部常量 x,并使用它来初始化一个变量 y:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">const</span> x <span class="token operator">=</span> <span class="token number">42</span> + <span class="token keyword">var</span> y <span class="token operator">=</span> x <span class="token operator">*</span> <span class="token number">2</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在编译时,x 将被处理成字面值 42,因此编译器将 y 初始化为 84,如下所示:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> y <span class="token operator">=</span> <span class="token number">84</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>可见,局部常量在编译期已经被折叠成了字面值,因此在运行时不会再进行计算了。</p> <h2 id="常量不可包含计算">常量不可包含计算</h2> <p>在 Go 中,常量必须在编译时就可以确定其值。因此,常量的值必须是一个编译时的常量表达式,不能包含运行时的计算。</p> <p>不过,常量表达式可以包含一些简单的运算,例如加、减、乘、除、取模等算术运算,以及位运算、逻辑运算等。例如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span> <span class="token punctuation">(</span> + x <span class="token operator">=</span> <span class="token number">2</span> <span class="token operator">+</span> <span class="token number">3</span> <span class="token comment">// 常量表达式,结果为 5</span> + y <span class="token operator">=</span> <span class="token punctuation">(</span>x <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">10</span> <span class="token comment">// 常量表达式,结果为 0</span> + z <span class="token operator">=</span> x <span class="token operator">==</span> <span class="token number">5</span> <span class="token operator">||</span> y <span class="token operator">==</span> <span class="token number">0</span> <span class="token comment">// 常量表达式,结果为 true</span> +<span class="token punctuation">)</span> +</code></pre></div><p>常量表达式还可以使用一些内置函数,例如 <code>len</code>、<code>cap</code>、<code>make</code>、<code>new</code> 等,以及可以在编译期计算的一些标准库函数,例如 <code>math.Sin</code>、<code>math.Pi</code> 等。</p> <p>总之,常量必须在编译期就可以确定其值,因此不能包含运行时的计算,但可以包含一些简单的算术、位运算、逻辑运算等。</p> <h2 id="枚举常量-iota">枚举常量 iota</h2> <p>go 语言提供隐式重复前一个非空表达式的机制</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">const</span> <span class="token punctuation">(</span> + PI <span class="token operator">=</span> <span class="token number">3.14</span> + a + b + c + d + e + f +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>PI<span class="token punctuation">,</span> a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> c<span class="token punctuation">,</span> d<span class="token punctuation">,</span> e<span class="token punctuation">,</span> f<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码将会全部输出 3.14</p> <p>iota 是 go 语言的一个预定义标识符,它表示 const 声明块中,每一个常量所处位置的偏移量,它本身也是一个无类型的常量,它的初始值是 0,意思是说此处的 iota 跟第一行比偏移了 0 个位置</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator"><<</span> <span class="token boolean">iota</span> + b + c + d + e + f +<span class="token punctuation">)</span> +</code></pre></div><p>同一行的常量 iota 值是一样的,可以理解为偏移量相同</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + a<span class="token punctuation">,</span>b <span class="token operator">=</span> <span class="token boolean">iota</span> + c<span class="token punctuation">,</span>d +<span class="token punctuation">)</span> +</code></pre></div><p>如果要让 iota 的初始值是 1,那么可以这么做</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + <span class="token boolean">_</span> <span class="token operator">=</span> <span class="token boolean">iota</span> + a + b + c + d +<span class="token punctuation">)</span> +</code></pre></div><p>iota 只需要在一个 const 群中出现一次即可,出现多次跟出现一次的效果一样</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token boolean">iota</span> + b <span class="token operator">=</span> <span class="token boolean">iota</span> + c <span class="token operator">=</span> <span class="token boolean">iota</span> +<span class="token punctuation">)</span> +<span class="token comment">// 一样</span> +<span class="token keyword">const</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token boolean">iota</span> + b + c +<span class="token punctuation">)</span> +</code></pre></div><p>当 iota 群中出现异类该如何处理</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token boolean">iota</span> + b <span class="token operator">=</span> <span class="token number">12</span> + c <span class="token operator">=</span> <span class="token boolean">iota</span> + d + e + f + g +<span class="token punctuation">)</span> +</code></pre></div><p>答案就是异类输出自己的,其它的常量不受影响,比如这里的输出就是 <code>0 12 2 3 4 5 6</code>,只要记住 iota 是偏移位置就可以理解为什么是这么输出的了。</p> <p>如果不考虑常量的灵活性,极致追求安全性,那么也可以给 iota 常量加上类型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + a <span class="token builtin">int</span> <span class="token operator">=</span> <span class="token boolean">iota</span> + b + c + d +<span class="token punctuation">)</span> +</code></pre></div><p>这种就要求变量类型必须是 int 才能被这些枚举类型接纳,但是一般常量还是用无类型的较为常见。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/常量声明/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/39.9c8315fb.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\346\225\260\345\255\227\347\261\273\345\236\213/index.html" "b/\345\237\272\347\241\200/\346\225\260\345\255\227\347\261\273\345\236\213/index.html" new file mode 100644 index 000000000..bca323093 --- /dev/null +++ "b/\345\237\272\347\241\200/\346\225\260\345\255\227\347\261\273\345\236\213/index.html" @@ -0,0 +1,119 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 数字类型 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/9.e2b0263e.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 数字类型</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/#int" class="sidebar-link">int</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/#float" class="sidebar-link">float</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/#基础浮点数-math-big-包-decimal-三方包的对比" class="sidebar-link">基础浮点数,math/big 包,decimal 三方包的对比</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/#complex-复数" class="sidebar-link">complex 复数</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%95%B0%E5%AD%97%E7%B1%BB%E5%9E%8B/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-数字类型">go 数字类型</h1> <p><strong>导读:</strong></p> <ul><li>int</li> <li>float</li> <li>complex</li> <li>issues</li></ul> <h2 id="int">int</h2> <p>int 是 go 语言的整数类型,一共分为下面这么几类</p> <table><thead><tr><th style="text-align:center;">类型</th> <th style="text-align:center;">描述</th></tr></thead> <tbody><tr><td style="text-align:center;">int</td> <td style="text-align:center;">有符号的整数类型,具体占几个字节要看操作系统的分配,不过至少分配给32位</td></tr> <tr><td style="text-align:center;">uint</td> <td style="text-align:center;">非负整数类型,具体占几个字节要看操作系统的分配,不过至少分配给32位</td></tr> <tr><td style="text-align:center;">int8</td> <td style="text-align:center;">有符号的整数类型,占8位bit,1个字节。范围从负的2的7次方到正的2的7次方减1</td></tr> <tr><td style="text-align:center;">int16</td> <td style="text-align:center;">有符号的整数类型,占16位bit,2个字节。范围从负的2的15次方到正的2的15次方减1</td></tr> <tr><td style="text-align:center;">int32</td> <td style="text-align:center;">有符号的整数类型,占32位bit,4个字节。范围从负的2的31次方到正的2的31次方减1</td></tr> <tr><td style="text-align:center;">int64</td> <td style="text-align:center;">有符号的整数类型,占64位bit,8个字节。范围从负的2的63次方到正的2的63次方减1</td></tr> <tr><td style="text-align:center;">uint8</td> <td style="text-align:center;">无符号的正整数类型,占8位,从0到2的8次方减1.也就是0到255</td></tr> <tr><td style="text-align:center;">uint16</td> <td style="text-align:center;">无符号的正整数类型,占16位,从0到2的16次方减1</td></tr> <tr><td style="text-align:center;">uint32</td> <td style="text-align:center;">无符号的正整数类型,占32位,从0到2的32次方减1</td></tr> <tr><td style="text-align:center;">uint64</td> <td style="text-align:center;">无符号的正整数类型,占64位,从0到2的64次方减1</td></tr> <tr><td style="text-align:center;">uintptr</td> <td style="text-align:center;">无符号整数类型。它大到足以容纳任何指针</td></tr> <tr><td style="text-align:center;">rune</td> <td style="text-align:center;">int32的别名,代表一个 UTF-8 字符</td></tr> <tr><td style="text-align:center;">byte</td> <td style="text-align:center;">uint8别名,代表了ASCII 码的一个字符</td></tr></tbody></table> <p>go 使用 <code>'\x12'</code> 或者使用 <code>0x12</code> 来表示 16 进制</p> <p>go 使用 <code>'\012'</code> 或者使用 <code>012</code> 来表示 8 进制</p> <p>go 不能直接显示 2 进制,使用 <code>fmt.Printf("%b",12)</code> <code>1000</code> 来输出一个二进制</p> <h2 id="float">float</h2> <table><thead><tr><th style="text-align:center;">类型</th> <th style="text-align:center;">描述</th></tr></thead> <tbody><tr><td style="text-align:center;">float32</td> <td style="text-align:center;">浮点型,包括正负小数,IEEE-754 32位的集合,提供大约 6 个十进制数的精度,math.MaxFloat32 表示 float32 能取到的最大数值,math.SmallestNonzeroFloat32表示最小值</td></tr> <tr><td style="text-align:center;">float64</td> <td style="text-align:center;">浮点型,包括正负小数,IEEE-754 64位的集合,提供约 15 个十进制数的精度,math.MaxFloat64 表示 float64 能取到的最大数值,math.SmallestNonzeroFloat64表示最小值</td></tr></tbody></table> <p>浮点数使用 <code>fmt.Printf("%.4f\n", math.Pi)</code>,<code>%.nf</code> 来控制保留几位小数</p> <p>我们知道根据 IEEE 754 标准,使用有限个位置的二进制数字去代表无限个数字,那么必然是不精确的,是近似的。</p> <p>由于浮点数计算的时候并不精确,容易发生较大误差,所以我们可以使用现有的高精度第三方库进行替换:https://github.com/shopspring/decimal</p> <h3 id="基础浮点数-math-big-包-decimal-三方包的对比">基础浮点数,math/big 包,decimal 三方包的对比</h3> <p>让我们看一下著名的 0.1 + 0.2 != 0.3 这个问题</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">0.1</span> + <span class="token keyword">var</span> b <span class="token operator">=</span> <span class="token number">0.2</span> + + <span class="token comment">// false</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token operator">+</span>b <span class="token operator">==</span> <span class="token number">0.3</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>基础浮点数 IEEE 754 详细介绍</strong></em></p> <p>这是一个 IEEE 754 的内部存储示意图,这个标准下,数字使用二进制的方式进行存储:</p> <p><img src="data:image/png;base64,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" alt="IEEE 754"></p> <table><thead><tr><th style="text-align:center;">sign</th> <th style="text-align:center;">exponent</th> <th style="text-align:center;">fraction</th></tr></thead> <tbody><tr><td style="text-align:center;">代表正负的符号位</td> <td style="text-align:center;">指数位</td> <td style="text-align:center;">尾数</td></tr></tbody></table> <ul><li><p>sign:<code>(-1)^sign</code>,所以当 sign 等于 0 时,就是正数,当 sign 等于 1 时就是负数</p></li> <li><p>exponent:指数,也就是 2 的指数,在计算的时候,我们要减去一个偏移量 (127 或者 1023,这取决于 32 位还是 64 位),在 32 位的情况下,0 - 255,然后减去偏移量 127,结果是:[-126,127] (正常情况下,不算上 00000000 和 11111111 这两种情况)</p></li> <li><p>fraction:尾数,表示为 1.fraction 或者 0。fraction 的样子,后者通常表示的极小浮点数</p></li></ul> <p>例如,图示的 0.15625,使用 IEEE 754 来表示:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">^</span><span class="token number">0</span> <span class="token operator">*</span> <span class="token number">2</span><span class="token operator">^</span><span class="token number">1111100</span> <span class="token operator">*</span> <span class="token number">1.01</span> + +<span class="token operator">=</span> <span class="token number">2</span><span class="token operator">^</span><span class="token punctuation">(</span><span class="token number">124</span> <span class="token operator">-</span> <span class="token number">127</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">1.01</span> + +<span class="token number">2</span><span class="token operator">^</span><span class="token operator">-</span><span class="token number">3</span> <span class="token operator">*</span> <span class="token number">1.01</span> + +<span class="token operator">=</span> <span class="token number">0.00101</span>(二进制) +<span class="token operator">=</span> <span class="token number">0.15625</span> (十进制) +</code></pre></div><p>可以看到,一个十进制的 0.15625 要转化为一个 2 进制的信息进行保存,那么问题来了,为什么浮点数的 0.1 不等于整数的 0.1 呢?</p> <blockquote><p>10 进制小数转化为 2 进制:使用十进制的小数部分乘以 2,然后取整数部分,然后再把这个数的小数部分再次乘以 2... 直到小数部分为零结束;十进制的整数部分就按照普通的除法,每次都除以 2,然后取余数,直到商为 0:</p></blockquote> <blockquote><p>举一个例子:十进制 8.35;</p></blockquote> <blockquote><p>整数部分是 8,8 /2 = 4 余 0,4/2 = 2 余 0,2/2 = 1 余 0,1/2=0 余 1,那么根据倒序排列来得出结果就是 1000;</p></blockquote> <blockquote><p>小数部分是 0.35,0.35 <em>2 = 0.7 整数部分是 0,0.7</em> 2 = 1.4 整数部分是 1,0.4 <em>2 = 0.8 整数部分是 0,0.8</em> 2 = 1.6 整数部分是 1,0.6 <em>2 = 1.2 整数部分是 1,0.2</em> 2 = 0.4 整数部分是 0,0.4 <em>2 = 0.8 整数部分是 0,0.8</em>2 = 1.6 ... 那么小数部分就是 0.01011001... 那么在满足某个精度的情况下,它的值用二进制表示就是 1000.01011001;</p></blockquote> <blockquote><p>将它还原也很简单,整数部分按照 2 的指数,小数部分按照 2 的负指数:1*2^3 + 2^-2 + 2^-4 + 2^-5 = 8.34375</p></blockquote> <p>第一步,我们需要将 0.1 转化为二进制,那么等于多少呢?</p> <p>答案是:0.0001100110011...</p> <p>看到了吧,除不尽啊,那么我们取它的尾数 1.1001100110011001100 * 2^-4</p> <p>如果填入他们的图就是</p> <ul><li>sign 为 0</li> <li>指数的十进制为 -4 + 127 = 123,也就是 <code>1111011</code> 填入上面的内容就是 01111011</li> <li>尾数是 100110011001100</li></ul> <p>所以你会发现从这里的存储再转化为 10 进制的结果就是</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token number">2</span><span class="token operator">^</span><span class="token operator">-</span><span class="token number">4</span> <span class="token operator">*</span> <span class="token number">1.1001100110011</span> + +<span class="token operator">=</span> <span class="token number">0.00011001100110011</span> + +<span class="token operator">=</span> <span class="token number">0.0999984741210937</span> +</code></pre></div><p>总结:由于某些数字,从 10 进制转化为 2 进制的时候,无法得到精确值,除不尽,所以,浮点数存储数字,有些数字不能精确存储</p> <p><em><strong>math/big 包详细介绍</strong></em></p> <p>big 拥有下面三个类型</p> <ul><li>Int</li> <li>Float</li> <li>Rat (有理数)</li></ul> <p>big 包提供的 <code>big.Int</code> 底层数据是一个切片,所以说它可以保存超过 <code>uint64</code> 的数据;<code>big.Rat</code> 的底层数据是,分子和分母分别都是一个 <code>big.Int</code> 类型,所以说它也可以保存超过 uint64 的数据。</p> <p>big.Float 类型是 Go 语言中提供的一个高精度的浮点数计算库,它使用了任意精度的浮点数表示,可以处理大数和小数,并提供了一系列的计算方法</p> <p>虽然它是高精度的浮点数计算,但是仍然不够精确,如果是绝对的精确的浮点数计算,通常要使用有理数,或者使用整数去取代真正的小数,下面这个第三方包就是使用整数去取代浮点数的方式来获取精确的浮点数运行结果。</p> <p><em><strong>decimal</strong></em></p> <p>这个第三方包底层使用 <code>big.Int</code> 进行处理数据,也就是说,它使用整数存储,计算然后得出结论的时候再把之前的指数还原即可,所以它可以进行精确的浮点数运算</p> <p>https://github.com/shopspring/decimal</p> <p>这个包中,0.1 + 0.2 就等于 0.3 了</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 创建一个新的Float类型</span> + a <span class="token operator">:=</span> decimal<span class="token punctuation">.</span><span class="token function">NewFromFloat</span><span class="token punctuation">(</span><span class="token number">0.1</span><span class="token punctuation">)</span> + b <span class="token operator">:=</span> decimal<span class="token punctuation">.</span><span class="token function">NewFromFloat</span><span class="token punctuation">(</span><span class="token number">0.2</span><span class="token punctuation">)</span> + c <span class="token operator">:=</span> decimal<span class="token punctuation">.</span><span class="token function">NewFromFloat</span><span class="token punctuation">(</span><span class="token number">0.3</span><span class="token punctuation">)</span> + value <span class="token operator">:=</span> a<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + <span class="token comment">// 0</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>value<span class="token punctuation">.</span><span class="token function">Cmp</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="complex-复数">complex 复数</h2> <table><thead><tr><th style="text-align:center;">类型</th> <th style="text-align:center;">描述</th></tr></thead> <tbody><tr><td style="text-align:center;">complex64</td> <td style="text-align:center;">实部和虚部是 float32</td></tr> <tr><td style="text-align:center;">complex128</td> <td style="text-align:center;">实部和虚部都是 float64</td></tr></tbody></table> <p><code>c := complex(3, 4)</code> 创建一个复数,实部为 3,虚部为 4</p> <p>或者还可以这样:<code>c := 3 + 4i</code></p> <p>使用 go 语言内置的函数 <code>real()</code> 和 <code>imag()</code> 来分别获取到复数的实部和虚部</p> <h2 id="issues">issues</h2> <p>***问题一:***go 语言数字之间的类型转化是如何进行的</p> <p>go 语言的类型转换是显性转化的,数字类型之间可以使用这种方法</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> i <span class="token builtin">int</span> +f <span class="token operator">:=</span> <span class="token function">float64</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> +</code></pre></div><p>***问题二:***能说说 <code>uintptr</code> 和 <code>unsafe.Pointer</code> 的区别吗</p> <ul><li><code>unsafe.Pointer</code> 是通用指针类型,它不能参与计算</li> <li><code>uintptr</code> 是指针运算的工具,但是它不能持有指针对象 (意思就是它跟指针对象不能互相转换)</li> <li><code>unsafe.Pointer</code> 和 <code>uintptr</code> 可以相互转换,<code>unsafe.Pointer</code> 和指针对象可以相互转换,但是 <code>uintptr</code> 和指针对象不能相互转换</li> <li>unsafe.Pointer 是指针对象进行运算 (也就是 uintptr) 的桥梁</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"unsafe"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 指针对象</span> + v <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token comment">// 将指针对象转化为通用指针类型</span> + vp <span class="token operator">:=</span> unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token comment">// 将通用指针类型转换为指针对象</span> + vo <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span>vp<span class="token punctuation">)</span> + + <span class="token comment">//将通用指针对象转化为uintptr</span> + uv <span class="token operator">:=</span> <span class="token function">uintptr</span><span class="token punctuation">(</span>vp<span class="token punctuation">)</span> + <span class="token comment">//将uintptr转换为通用指针对象</span> + vpp <span class="token operator">:=</span> unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span>uv<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>v<span class="token punctuation">,</span> vp<span class="token punctuation">,</span> vo<span class="token punctuation">,</span> uv<span class="token punctuation">,</span> vpp<span class="token punctuation">)</span> + + <span class="token comment">// 对指针对象的地址进行计算</span> + t <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> + <span class="token comment">// 首先先将t转化为unsafe.Pointer类型</span> + pt <span class="token operator">:=</span> unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span> + <span class="token comment">// 然后将pointer再转化为 uintptr</span> + rt <span class="token operator">:=</span> <span class="token function">uintptr</span><span class="token punctuation">(</span>pt<span class="token punctuation">)</span> + <span class="token comment">//进行计算</span> + npt <span class="token operator">:=</span> rt <span class="token operator">+</span> <span class="token function">uintptr</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token comment">// 计算完毕后,再将uintptr转化为unsafe.Pointer再转换为*string类型</span> + nt <span class="token operator">:=</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span>unsafe<span class="token punctuation">.</span><span class="token function">Pointer</span><span class="token punctuation">(</span>npt<span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> pt<span class="token punctuation">,</span> rt<span class="token punctuation">,</span> npt<span class="token punctuation">,</span> nt<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>***问题三:***rune 和 byte 的区别</p> <p>rune 是 int32,byte 是 uint8,相比 byte 来说,rune 可以容纳的字符个数要多很多,所以 utf8 编码的字符使用 rune,而 ascii 使用 byte,例如 ‘中’ byte 无法承受,“中” 转为 <code>[]byte</code> 的时候是 <code>[228 184 173]</code>,“中” 转换为 <code>[]rune</code> 则是等于 <code>[20013]</code> 因为 rune 可承受的数值更大,并且一个 utf8 的字符就等于一个 rune 的数值,如果是使用 ‘中’ 那默认就是 rune 类型</p> <blockquote><p>unicode 是一种字符编码,让每个字符和一个数字对应起来,仅此而已,至于这个数字如何存储它就不管了。utf8 就是定义了如何具体存储这个编码数字的一种方法</p></blockquote> <h2 id="参考资料">参考资料</h2> <ul><li>https://zhuanlan.zhihu.com/p/145220416</li> <li>http://www.manongjc.com/article/50416.html</li> <li>http://c.biancheng.net/view/18.html</li> <li>https://zhuanlan.zhihu.com/p/353013671</li> <li>https://developer.aliyun.com/article/673258</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/数字类型/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/9.e2b0263e.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\346\261\202\345\200\274\351\241\272\345\272\217/index.html" "b/\345\237\272\347\241\200/\346\261\202\345\200\274\351\241\272\345\272\217/index.html" new file mode 100644 index 000000000..31e3b951d --- /dev/null +++ "b/\345\237\272\347\241\200/\346\261\202\345\200\274\351\241\272\345\272\217/index.html" @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>求值顺序 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/40.3bf1fd84.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>求值顺序</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/#包级变量声明语句中的表达式求值顺序" class="sidebar-link">包级变量声明语句中的表达式求值顺序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/#普通求值顺序" class="sidebar-link">普通求值顺序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/#赋值语句中的求值顺序" class="sidebar-link">赋值语句中的求值顺序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/#switch-select-中的表达式的求值顺序" class="sidebar-link">switch select 中的表达式的求值顺序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B1%82%E5%80%BC%E9%A1%BA%E5%BA%8F/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="求值顺序">求值顺序</h1> <h2 id="包级变量声明语句中的表达式求值顺序">包级变量声明语句中的表达式求值顺序</h2> <ul><li>按照变量的声明顺序,<strong>从上到下,从左到右</strong>,进行求值</li> <li>如果 a 求值时有依赖项 b,或者是间接的依赖项 b,那么先求值 b</li> <li>在求值的过程中会一直对于变量是否拥有依赖项进行查找,直到查询到没有依赖项的变量将其求值,然后重复这个查找,最后全部求值。</li> <li>同一个包不同文件的处理,原则上如果 a 文件在 b 文件前面,那么 a 文件中的所有变量求值比 b 文件中的更早,除非 a 文件变量依赖了 b 中的变量。</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> <span class="token punctuation">(</span> + a <span class="token operator">=</span> c <span class="token operator">+</span> b + b <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token boolean">_</span> <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + c <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + d <span class="token operator">=</span> <span class="token number">3</span> +<span class="token punctuation">)</span> +<span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + d <span class="token operator">++</span> + <span class="token keyword">return</span> d +<span class="token punctuation">}</span> +</code></pre></div><ol><li>查找没有依赖项的变量将其求值,这一轮中是 d,此时只有 [d=3]</li> <li>查找没有依赖项的变量进行求值,这一轮中 a 还是不符合,但是 b 符合了,所以现在是 [b=4,d=4]</li> <li>查找没有依赖项的变量进行求值,这一轮中是 _,此时 [b=4,d=5]</li> <li>查找没有依赖项的变量进行求值,这一轮中是 c,此时 [b=4,c=6,d=6]</li> <li>查找没有依赖项的变量进行求值,这一轮中是 a,此时 [a=10,b=4,c=6,d=6]</li></ol> <p>输出 10 4 6 6</p> <h2 id="普通求值顺序">普通求值顺序</h2> <p>这包括了,函数,方法,channel 中的求值顺序。</p> <ul><li>规定是从左到右</li></ul> <p>y[f()],ok = g(h(),i()+x[j()], <-c),k()</p> <p>这个语句的求值顺序就是 f() h() i() j() x[] <-c g() k()</p> <p>普通值求值顺序和包级变量求值依赖顺序一起使用的时候,包级变量优先级更高,并且它在导入包的时候就已经求值了,而普通的求值顺序只有调用的时候才会求值。</p> <h2 id="赋值语句中的求值顺序">赋值语句中的求值顺序</h2> <p>赋值语句求值有两个阶段 --- “先算后赋”</p> <ul><li>对等号左边的下标表达式,指针解引用表达式,以及等号右边的表达式,从左到右的依次求值</li> <li>按照从左到右的顺序将变量进行赋值</li></ul> <p>例如</p> <div class="language-go extra-class"><pre class="language-go"><code>n0 <span class="token operator">:=</span> <span class="token number">1</span> +n1 <span class="token operator">:=</span> <span class="token number">2</span> +n0<span class="token punctuation">,</span>n1 <span class="token operator">=</span> n0<span class="token operator">+</span>n1<span class="token punctuation">,</span>n0 +</code></pre></div><ol><li>左边没有要处理的表达式,右侧有,那么第一个位置就是 n0+n1,因为 n0 和 n1 已经存在了初始化的内容了,所以这里直接就是 3,no = 1,这时 n0 和 n1 还是 1 2,因为还没有赋值呢。</li> <li>开始赋值:右侧一个是 3 一个是 1,那么最新的 no 和 n1 就是 3 1</li></ol> <h2 id="switch-select-中的表达式的求值顺序">switch select 中的表达式的求值顺序</h2> <p>这里主要想说一下惰性求值:就是只有需求的时候才会进行求值</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span>n <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> n +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">switch</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"--"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>首先先求值的是 switch 后面的 f (2)</p> <p>然后对 f(1) f(2) 求值;f(3) 不会求值,因为 f (2) 已经满足了要求。</p> <p>在 select case 中,如果 case 中存在表达式,最开始会依次计算所有的表达式,只有一种除外,收 case 中,位于左侧的表达式,它会在接受数据之前才会计算,然后赋值。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/ref/spec#Order_of_evaluation</li> <li>https://book.douban.com/subject/35720728/ 132 页 - 142 页</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/求值顺序/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/40.3bf1fd84.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\346\263\233\345\236\213/index.html" "b/\345\237\272\347\241\200/\346\263\233\345\236\213/index.html" new file mode 100644 index 000000000..8d82c1450 --- /dev/null +++ "b/\345\237\272\347\241\200/\346\263\233\345\236\213/index.html" @@ -0,0 +1,453 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>泛型 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/41.73deb46e.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>泛型</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#约束" class="sidebar-link">约束</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#泛型是类型-约束是类型的约束" class="sidebar-link">泛型是类型,约束是类型的约束</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#约束的嵌套" class="sidebar-link">约束的嵌套</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#泛型-2" class="sidebar-link">泛型</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#使用方法" class="sidebar-link">使用方法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#实现原理" class="sidebar-link">实现原理</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#跟其它语言的泛型进行对比" class="sidebar-link">跟其它语言的泛型进行对比</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#为什么-java-编译器不在编译期就完成泛型的装箱操作呢" class="sidebar-link">为什么 Java 编译器不在编译期就完成泛型的装箱操作呢?</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#用例子学泛型" class="sidebar-link">用例子学泛型</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#函数泛型-map-filter-reduce" class="sidebar-link">函数泛型 map-filter-reduce</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#例子二-方法上的泛型-sets" class="sidebar-link">例子二:方法上的泛型 sets</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#例子三-外部定义的约束-实现一个sort接口类型" class="sidebar-link">例子三:外部定义的约束 实现一个sort接口类型</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#关于泛型中的零值" class="sidebar-link">关于泛型中的零值</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#无法识别使用了底层数据的其它类型" class="sidebar-link">无法识别使用了底层数据的其它类型</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#即便约束一致-类型也是不同的" class="sidebar-link">即便约束一致,类型也是不同的</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E6%B3%9B%E5%9E%8B/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="泛型">泛型</h1> <p><strong>导读:</strong></p> <ul><li>约束</li> <li>使用方法</li> <li>实现原理</li> <li>跟其它语言的泛型进行对比</li> <li>用例子学泛型</li> <li>issues</li></ul> <blockquote><p>泛型需满足 <code>go1.18+</code></p></blockquote> <h2 id="约束">约束</h2> <p>go 使用 interface 作为约束,约束的意思是约束了这个泛型都具有哪些实际类型。所以可以理解为,go 将 interface 的职责给扩展了,让接口不仅仅作为接口 --- 解耦的,抽象化的结构体,还具有了约束,对于类型的约束作用。</p> <p>go 可以将所有的接口 (包括经典接口,和泛型以后的接口) 都用作约束,但是可以不代表应该,要有选择的去使用约束,但是约束并不是都可以作为传统的接口来使用的,例如传统的接口只能存在方法,并不能存在类型,<strong>只要存在类型就自动归纳为约束</strong></p> <p>综上所述,第一,约束的概念大于接口,只有传统接口可以作为抽象类型去使用,约束只能存在于函数方法或者类型之中,不能单独使用。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a1 a +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> a <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token builtin">int</span><span class="token operator">|</span><span class="token builtin">float64</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># 不能在类型约束之外使用类型 a:接口包含类型约束</span> +cannot use <span class="token builtin class-name">type</span> a outside a <span class="token builtin class-name">type</span> constraint: interface contains <span class="token builtin class-name">type</span> constraints + +</code></pre></div><p>第二,不要把传统接口用在约束的地方,这种用法是不合适的,通常来说传统接口的模式就用作抽象类型的解耦即可 (用了也不错,只是不建议)。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 不建议</span> +<span class="token keyword">type</span> Writer <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">hi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> Get<span class="token punctuation">[</span>T Writer<span class="token punctuation">]</span><span class="token punctuation">(</span>v T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + v<span class="token punctuation">.</span><span class="token function">hi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="泛型是类型-约束是类型的约束">泛型是类型,约束是类型的约束</h3> <p>请认识到,泛型是一种类型,约束是一种类型的约束,请不要把约束当作泛型。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> st <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token builtin">int</span> <span class="token operator">|</span> <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这里 st 约束拥有 int 和 string,请注意这里的 st 是约束,不是泛型类型</p> <p>go 内置了很多约束,比如说 any 和 comparable,意思是任何类型和可以比较的类型。以后***应该***会有一个新的内置约束的包叫做 <code>package constraints</code> 例如 any comparable,Ordered 等等约束都会内置到标准库中</p> <p>约束不仅仅可以单独写出来,还可以内置于函数内部。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> Age<span class="token punctuation">[</span>T <span class="token builtin">int</span><span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">,</span> B <span class="token builtin">float64</span><span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">]</span><span class="token punctuation">(</span>i T<span class="token punctuation">,</span>j B<span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>这种形式下,T 和 B 的约束就是仅限此函数使用</p> <p>下面我们看一种形式,这种情况下约束的不仅仅是 string 和 int,而是包含了底层是他们的所有数据,比如说 <code>type DD int</code> 也符合这个约束,请记住只能使用在底层类型上,如果使用 <code>~DD</code> 是不被允许的</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> st <span class="token keyword">interface</span><span class="token punctuation">{</span> + ~<span class="token builtin">string</span> <span class="token operator">|</span> ~<span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="约束的嵌套">约束的嵌套</h3> <p>约束跟接口是一样的也是可以嵌套的</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> ComparableHasher <span class="token keyword">interface</span> <span class="token punctuation">{</span> + comparable + <span class="token function">Hash</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">uintptr</span> +<span class="token punctuation">}</span> + +<span class="token comment">// or</span> + +<span class="token keyword">type</span> ImpossibleConstraint <span class="token keyword">interface</span> <span class="token punctuation">{</span> + comparable + <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这里的意义就是 <strong>and</strong> 的意思就是说这个约束是可以比较的还是必须得支持 <code>hash()uintptr</code></p> <p>下面这种方式也是可以的</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> NumericAbs<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> + ~<span class="token builtin">int</span> <span class="token operator">|</span> ~<span class="token builtin">int8</span> <span class="token operator">|</span> ~<span class="token builtin">int16</span> <span class="token operator">|</span> ~<span class="token builtin">int32</span> <span class="token operator">|</span> ~<span class="token builtin">int64</span> <span class="token operator">|</span> + ~<span class="token builtin">uint</span> <span class="token operator">|</span> ~<span class="token builtin">uint8</span> <span class="token operator">|</span> ~<span class="token builtin">uint16</span> <span class="token operator">|</span> ~<span class="token builtin">uint32</span> <span class="token operator">|</span> ~<span class="token builtin">uint64</span> <span class="token operator">|</span> ~<span class="token builtin">uintptr</span> <span class="token operator">|</span> + ~<span class="token builtin">float32</span> <span class="token operator">|</span> ~<span class="token builtin">float64</span> <span class="token operator">|</span> + ~<span class="token builtin">complex64</span> <span class="token operator">|</span> ~<span class="token builtin">complex128</span> + <span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> T +<span class="token punctuation">}</span> +</code></pre></div><p>上面的类型意思是满足数字类型,下面的意思是满足这个方法,所以最终实现这个约束的对象就是一个数字类型,并且实现了这个接口的 <code>Abs()T</code> 方法。</p> <h2 id="泛型-2">泛型</h2> <p>当结构体中使用泛型的时候,泛型不能直接作为嵌入使用</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Lockable<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span> + T <span class="token comment">// 正确的方法应该是 t T ; 将 T 作为类型参数,不可直接嵌入</span> + mu sync<span class="token punctuation">.</span>Mutex +<span class="token punctuation">}</span> + +</code></pre></div><p>错误提示:<code>embedded field type cannot be a (pointer to a) type parameter</code>;<code>嵌入式字段类型不能是(指向)类型参数</code></p> <p>我们再看一下当泛型结构体嵌入到其它结构体中如何使用</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span> + T T +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> B<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token comment">// 这里使用 A[T] 输入了实际类型,</span> + A<span class="token punctuation">[</span>T<span class="token punctuation">]</span> + T T +<span class="token punctuation">}</span> +</code></pre></div><p>可以看出关键点,泛型结构体被嵌入其它结构体的时候,泛型要给实际的类型才可以</p> <p>结构体泛型和方法中的泛型做对比:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>a A<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>方法里的泛型是可以直接从 struct 定义的地方继承这个泛型 T 的,当这个结构体使用时,指定实际的类型即可。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> d1 d + <span class="token keyword">var</span> a <span class="token operator">=</span> A<span class="token punctuation">[</span>d<span class="token punctuation">]</span><span class="token punctuation">{</span> + d1<span class="token punctuation">,</span> + <span class="token punctuation">}</span> + a<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// 只要没有类型就不是约束,是接口,在go语言中,接口可以充当一个一般类型</span> +<span class="token keyword">type</span> d <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> A<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span> + T T +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>a A<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><em><strong>约束里的泛型同样不能直接嵌入使用</strong></em></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌</span> +<span class="token keyword">type</span> B<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> + T +<span class="token punctuation">}</span> +</code></pre></div><p>错误提示:<code>cannot embed a type parameter</code></p> <p>泛型只能充当类型:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> EmbeddedParameter<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> + ~<span class="token builtin">int</span> <span class="token operator">|</span> ~<span class="token builtin">uint</span> + <span class="token function">me</span><span class="token punctuation">(</span><span class="token punctuation">)</span> T +</code></pre></div><p>使用约束中的泛型还是需要注意一下的,稍微有些复杂:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> Abs<span class="token punctuation">[</span>T EmbeddedParameter<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span>T<span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>解释一下,中括号里面泛型的两个 T 表达的意思是不一样的,后面的 T 表达的是<strong>约束里的泛型</strong>,表示 any,前面的 T 表示的是满足后面的这个约束的类型 T,但是这里注意,后面 T 虽然之前定义的时候是 any 但是这里被赋予为 T 之后,改变了,改变为了必须满足约束 <code>EmbeddedParameter</code> 的类型,如果说的通俗点,从 any 变成了,满足 <code>int | uint and 实现 me()T方法</code> 后文会有代码进行解释。</p> <p>当然了,后面的 T 没有也行,如果没有后面的 T 就是相当于不改变后面的 T 的约束类型了</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Differ<span class="token punctuation">[</span>T1 any<span class="token punctuation">]</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Diff</span><span class="token punctuation">(</span>T1<span class="token punctuation">)</span> <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> IsClose<span class="token punctuation">[</span>T2 Differ<span class="token punctuation">]</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b T2<span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> a<span class="token punctuation">.</span><span class="token function">Diff</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> <span class="token operator"><</span> <span class="token number">2</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>当使用了泛型之后,是无法使用断言的,这是非法的,那么如果一定要在运行时的时候去判断类型怎么办呢?答案就是转变成 <code>any</code> (type any = interface {}) 即可,因为我们知道任何对象都已经实现了空接口,那么就可以被空接口去转化</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> GeneralAbsDifference<span class="token punctuation">[</span>T Numeric<span class="token punctuation">]</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b T<span class="token punctuation">)</span> T <span class="token punctuation">{</span> + <span class="token keyword">switch</span> <span class="token function">any</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">int8</span><span class="token punctuation">,</span> <span class="token builtin">int16</span><span class="token punctuation">,</span> <span class="token builtin">int32</span><span class="token punctuation">,</span> <span class="token builtin">int64</span><span class="token punctuation">,</span> + <span class="token builtin">uint</span><span class="token punctuation">,</span> <span class="token builtin">uint8</span><span class="token punctuation">,</span> <span class="token builtin">uint16</span><span class="token punctuation">,</span> <span class="token builtin">uint32</span><span class="token punctuation">,</span> <span class="token builtin">uint64</span><span class="token punctuation">,</span> <span class="token builtin">uintptr</span><span class="token punctuation">,</span> + <span class="token builtin">float32</span><span class="token punctuation">,</span> <span class="token builtin">float64</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token function">OrderedAbsDifference</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token builtin">complex64</span><span class="token punctuation">,</span> <span class="token builtin">complex128</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token function">ComplexAbsDifference</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>下面看一下别名的真实类型是泛型的情况</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>T + +<span class="token keyword">type</span> AliasA <span class="token operator">=</span> A <span class="token comment">// 错误 ❌</span> + +<span class="token keyword">type</span> AliasA <span class="token operator">=</span> A<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span> <span class="token comment">// 正确</span> +</code></pre></div><p>其中错误的问题是别名不能直接使用泛型类型 <code>cannot use generic type A[T any] without instantiation</code>,它需要泛型实际赋值</p> <h2 id="使用方法">使用方法</h2> <p>下面展示一下 go 泛型的基本使用方法</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"%v"</span><span class="token punctuation">,</span>Age<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> Age<span class="token punctuation">[</span>T any<span class="token punctuation">]</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span> T<span class="token punctuation">{</span> + <span class="token keyword">return</span> t +<span class="token punctuation">}</span> +</code></pre></div><p>这是函数使用泛型的写法,当函数使用泛型的时候,需要在变量前使用中括号标注泛型的具体约束,然后后面才能使用这个泛型类型,使用泛型函数的时候,中括号是可以省略的 <code>Age(12)</code> 系统会自动推算泛型的具体实现。顺便说一下,泛型类型使用 <code>%v</code> 作为占位符,也就是默认的类型,泛型类型无法进行断言。</p> <p>当然了,我么也可以不用 any,自定义一个约束</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + Age<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> st <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token builtin">int</span> <span class="token operator">|</span> <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> Age<span class="token punctuation">[</span>T st<span class="token punctuation">]</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>看完了在函数内的泛型,我们在看一下在方法中如何使用泛型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">new</span><span class="token punctuation">(</span>Age<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Post</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span> + + <span class="token keyword">var</span> dd DD<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span> + dd<span class="token punctuation">.</span><span class="token function">TT</span><span class="token punctuation">(</span><span class="token number">12</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Age<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span> + I T +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>Age<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Post</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">.</span>I<span class="token punctuation">,</span> t<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> DD<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>T + +<span class="token keyword">func</span><span class="token punctuation">(</span>dd <span class="token operator">*</span>DD<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token function">TT</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span><span class="token function">len</span><span class="token punctuation">(</span><span class="token operator">*</span>dd<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在 age 结构体声明的时候,声明了一个泛型 T,在 struct 体内就可以使用这个 T,方法内部仅可以使用定义在这个结构体对象上的泛型</p> <p>下面是一个<strong>错误案例</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>Age<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span>Post<span class="token punctuation">[</span>B any<span class="token punctuation">]</span><span class="token punctuation">(</span>t T<span class="token punctuation">,</span>b B<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">.</span>I<span class="token punctuation">,</span> t<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><code>syntax error: method must have no type parameters</code></p> <p>接下来我们看一下,如何使用有类型也有方法的泛型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> d DDD + <span class="token keyword">var</span> i DDD + d <span class="token operator">=</span> <span class="token number">1</span> + i <span class="token operator">=</span> <span class="token number">2</span> + io <span class="token operator">:=</span> AbsDifference<span class="token punctuation">[</span>DDD<span class="token punctuation">]</span><span class="token punctuation">(</span>d<span class="token punctuation">,</span> i<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>io<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> DDD <span class="token builtin">int</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>ddd DDD<span class="token punctuation">)</span> <span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> DDD <span class="token punctuation">{</span> + <span class="token keyword">return</span> ddd <span class="token operator">+</span> ddd +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> NumericAbs<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> + ~<span class="token builtin">int</span> <span class="token operator">|</span> ~<span class="token builtin">int8</span> <span class="token operator">|</span> ~<span class="token builtin">int16</span> <span class="token operator">|</span> ~<span class="token builtin">int32</span> <span class="token operator">|</span> ~<span class="token builtin">int64</span> <span class="token operator">|</span> + ~<span class="token builtin">uint</span> <span class="token operator">|</span> ~<span class="token builtin">uint8</span> <span class="token operator">|</span> ~<span class="token builtin">uint16</span> <span class="token operator">|</span> ~<span class="token builtin">uint32</span> <span class="token operator">|</span> ~<span class="token builtin">uint64</span> <span class="token operator">|</span> ~<span class="token builtin">uintptr</span> <span class="token operator">|</span> + ~<span class="token builtin">float32</span> <span class="token operator">|</span> ~<span class="token builtin">float64</span> <span class="token operator">|</span> + ~<span class="token builtin">complex64</span> <span class="token operator">|</span> ~<span class="token builtin">complex128</span> + <span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> T +<span class="token punctuation">}</span> + +<span class="token comment">// AbsDifference computes the absolute value of the difference of</span> +<span class="token comment">// a and b, where the absolute value is determined by the Abs method.</span> +<span class="token keyword">func</span> AbsDifference<span class="token punctuation">[</span>T NumericAbs<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> b T<span class="token punctuation">)</span> T <span class="token punctuation">{</span> + d <span class="token operator">:=</span> a <span class="token operator">-</span> b + <span class="token keyword">return</span> d<span class="token punctuation">.</span><span class="token function">Abs</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="实现原理">实现原理</h2> <p>泛型的第一种方法是在编译这个泛型时,使用一个字典,里面包含了这个泛型函数的全部类型信息,然后当运行时,使用函数实例化的时候从这个字典中取出信息进行实例化即可,这种方法会导致执行性能下降,一个实例化类型 <code>int, x=y</code> 可能通过寄存器复制就可以了,但是泛型必须通过内存了 (因为需要字典进行运行时赋值),不过好处就是不浪费空间</p> <p>还有一种方法就是把这个泛型的所有类型全部提前生成,这种方法也有一个巨大的缺点就是代码量直线上升,如果是一个包的情况下还能根据具体的函数调用去实现该实现的类型,如果是包输出的的情况下,那么就得不得不生成所有的类型。</p> <p>所以将两者结合在一起或许是最好的选择。</p> <p>这种方法是这样的,如果类型的内存分配器/垃圾回收器呈现的方式一致的情况下,只给它生成一份代码,然后给它一个字典来区分不同的具体行为,可以最大限度的平衡速度和体积</p> <h2 id="跟其它语言的泛型进行对比">跟其它语言的泛型进行对比</h2> <ul><li>c 语言:本身不具有泛型,需要程序员去实现一个泛型,实现复杂,但是不增加语言的复杂度 (换言之只增加了程序员的)</li> <li>c++和 rust:跟 go 基本保持一种方式,就是增加编译器的工作量</li> <li>Java:将泛型装箱为 object,在装箱和拆箱擦除类型的过程中,程序执行效率会变低</li></ul> <h3 id="为什么-java-编译器不在编译期就完成泛型的装箱操作呢">为什么 Java 编译器不在编译期就完成泛型的装箱操作呢?</h3> <p>主要有以下几个原因:</p> <ol><li><p>编译期装箱需要编译器对代码细节有完整信息。但是泛型类型信息可能来自其他模块或第三方库,编译器难以完整获取。</p></li> <li><p>即使编译器可以提前装箱,也需要代码里有大量反射样板代码来还原原始泛型类型,违背泛型设计初衷。</p></li> <li><p>编译期装箱也无法很好处理运行期检查和转换的各种边界情况。</p></li></ol> <h2 id="用例子学泛型">用例子学泛型</h2> <p>理论学习完了,不使用例子进行复习的话会忘的很快的。跟着我看几个例子吧</p> <h3 id="函数泛型-map-filter-reduce">函数泛型 <code>map-filter-reduce</code></h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + vM <span class="token operator">:=</span> Map<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + + <span class="token keyword">return</span> i <span class="token operator">+</span> i + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"map的结果是:%v"</span><span class="token punctuation">,</span> vM<span class="token punctuation">)</span> + vF <span class="token operator">:=</span> Filter<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>t <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> t <span class="token operator">></span> <span class="token number">2</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">true</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">false</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"filter的结果是:%v"</span><span class="token punctuation">,</span> vF<span class="token punctuation">)</span> + vR <span class="token operator">:=</span> Reduce<span class="token punctuation">[</span>Value<span class="token punctuation">,</span> <span class="token operator">*</span>Result<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span>Value<span class="token punctuation">{</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"tt"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"bb"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"7i"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">3</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"8i"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">4</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"u4i"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">5</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"uei"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">6</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"uwi"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">7</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">{</span>name<span class="token punctuation">:</span> <span class="token string">"uti"</span><span class="token punctuation">,</span> year<span class="token punctuation">:</span> <span class="token number">8</span><span class="token punctuation">}</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token operator">&</span>Result<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>r <span class="token operator">*</span>Result<span class="token punctuation">,</span> v Value<span class="token punctuation">)</span> <span class="token operator">*</span>Result <span class="token punctuation">{</span> + r<span class="token punctuation">.</span>value <span class="token operator">=</span> r<span class="token punctuation">.</span>value <span class="token operator">+</span> v<span class="token punctuation">.</span>year + <span class="token keyword">return</span> r + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"reduce的结果是:"</span><span class="token punctuation">,</span> vR<span class="token punctuation">.</span>value<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +<span class="token comment">// Map:类似于洗菜,进去的菜和出来的菜不一样了所以需要两种种类</span> +<span class="token keyword">func</span> Map<span class="token punctuation">[</span>T1<span class="token punctuation">,</span> T2 any<span class="token punctuation">]</span><span class="token punctuation">(</span>arr <span class="token punctuation">[</span><span class="token punctuation">]</span>T1<span class="token punctuation">,</span> f <span class="token keyword">func</span><span class="token punctuation">(</span>T1<span class="token punctuation">)</span> T2<span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>T2 <span class="token punctuation">{</span> + result <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span>T2<span class="token punctuation">,</span> <span class="token function">len</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> k<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> arr <span class="token punctuation">{</span> + result<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> result +<span class="token punctuation">}</span> + +<span class="token comment">// Filter:类似于摘菜,进去的菜和出来的菜是一种,不过量减少了</span> +<span class="token keyword">func</span> Filter<span class="token punctuation">[</span>T any<span class="token punctuation">]</span><span class="token punctuation">(</span>arr <span class="token punctuation">[</span><span class="token punctuation">]</span>T<span class="token punctuation">,</span> f <span class="token keyword">func</span><span class="token punctuation">(</span>T<span class="token punctuation">)</span> <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>T <span class="token punctuation">{</span> + <span class="token keyword">var</span> result <span class="token punctuation">[</span><span class="token punctuation">]</span>T + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> arr <span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token function">f</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> <span class="token punctuation">{</span> + result <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> result +<span class="token punctuation">}</span> + +<span class="token comment">// Reduce:类似于做菜,将菜做成一道料理,所以需要两种类型</span> +<span class="token keyword">func</span> Reduce<span class="token punctuation">[</span>T1<span class="token punctuation">,</span> T2 any<span class="token punctuation">]</span><span class="token punctuation">(</span>arr <span class="token punctuation">[</span><span class="token punctuation">]</span>T1<span class="token punctuation">,</span> zero T2<span class="token punctuation">,</span> f <span class="token keyword">func</span><span class="token punctuation">(</span>T2<span class="token punctuation">,</span> T1<span class="token punctuation">)</span> T2<span class="token punctuation">)</span> T2 <span class="token punctuation">{</span> + result <span class="token operator">:=</span> zero + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> arr <span class="token punctuation">{</span> + result <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> result +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Value <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Result <span class="token keyword">struct</span> <span class="token punctuation">{</span> + value <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><p><code>map的结果是:[2 4 6 8 10] filter的结果是:[3 4 5] reduce的结果是: 36</code></p> <h3 id="例子二-方法上的泛型-sets">例子二:方法上的泛型 <code>sets</code></h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token comment">// 这里 Sets的具体类型和Make的具体类型都是int,所以可以正常赋值</span> + <span class="token keyword">var</span> s Sets<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span> <span class="token operator">=</span> Make<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">//</span> + s<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span><span class="token function">Len</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Iterate</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">Delete</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// Sets 一个key 存储对象</span> +<span class="token keyword">type</span> Sets<span class="token punctuation">[</span>T comparable<span class="token punctuation">]</span> <span class="token keyword">map</span><span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token comment">// Make 实例化一个map</span> +<span class="token keyword">func</span> Make<span class="token punctuation">[</span>D comparable<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> Sets<span class="token punctuation">[</span>D<span class="token punctuation">]</span> <span class="token punctuation">{</span> + <span class="token comment">// 泛型就像一个管道一样,只要实例化的时候管子里的东西一致,那么就是一根管子</span> + <span class="token keyword">return</span> <span class="token function">make</span><span class="token punctuation">(</span>Sets<span class="token punctuation">[</span>D<span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// Add 向这个sets添加内容</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s Sets<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Add</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + s<span class="token punctuation">[</span>t<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// delete ,从这个sets中删除内容</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s Sets<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Delete</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">delete</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span> t<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// Contains 播报t是否属于这个sets</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s Sets<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Contains</span><span class="token punctuation">(</span>t T<span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token boolean">_</span><span class="token punctuation">,</span> ok <span class="token operator">:=</span> s<span class="token punctuation">[</span>t<span class="token punctuation">]</span> + <span class="token keyword">return</span> ok +<span class="token punctuation">}</span> + +<span class="token comment">//Len sets拥有的长度</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>s Sets<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// Iterate 迭代器,并且给予每个元素功能</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>s Sets<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Iterate</span><span class="token punctuation">(</span>f <span class="token keyword">func</span><span class="token punctuation">(</span>T<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> s <span class="token punctuation">{</span> + <span class="token function">f</span><span class="token punctuation">(</span>k<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p><code>map[1:{} 2:{}] false 2 1 2 map[1:{} 2:{}] map[1:{}]</code></p> <h3 id="例子三-外部定义的约束-实现一个sort接口类型">例子三:外部定义的约束 <code>实现一个sort接口类型</code></h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Hello, 世界"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// ~ 代表只要底层满足这些类型也可以算满足约束</span> +<span class="token keyword">type</span> Ordered <span class="token keyword">interface</span> <span class="token punctuation">{</span> + ~<span class="token builtin">int</span> <span class="token operator">|</span> ~<span class="token builtin">int8</span> <span class="token operator">|</span> ~<span class="token builtin">int16</span> <span class="token operator">|</span> ~<span class="token builtin">int32</span> <span class="token operator">|</span> ~<span class="token builtin">int64</span> <span class="token operator">|</span> ~<span class="token builtin">uintptr</span> <span class="token operator">|</span> + ~<span class="token builtin">uint</span> <span class="token operator">|</span> ~<span class="token builtin">uint8</span> <span class="token operator">|</span> ~<span class="token builtin">uint16</span> <span class="token operator">|</span> ~<span class="token builtin">uint32</span> <span class="token operator">|</span> ~<span class="token builtin">uint64</span> <span class="token operator">|</span> + ~<span class="token builtin">float32</span> <span class="token operator">|</span> ~<span class="token builtin">float64</span> <span class="token operator">|</span> ~<span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> orderedSlice<span class="token punctuation">[</span>T Ordered<span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>T + +<span class="token keyword">func</span> <span class="token punctuation">(</span>s orderedSlice<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Len</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s orderedSlice<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Less</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> j <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> s<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator"><</span> s<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s orderedSlice<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Swap</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> j <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> s<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> s<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> s<span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span> s<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token punctuation">}</span> +<span class="token keyword">func</span> OrderedSlice<span class="token punctuation">[</span>T Ordered<span class="token punctuation">]</span><span class="token punctuation">(</span>s <span class="token punctuation">[</span><span class="token punctuation">]</span>T<span class="token punctuation">)</span> <span class="token punctuation">{</span> + sort<span class="token punctuation">.</span><span class="token function">Sort</span><span class="token punctuation">(</span>orderedSlice<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="issues">issues</h2> <h3 id="关于泛型中的零值">关于泛型中的零值</h3> <p>在 go 里面对泛型的零值并没有一个所谓的泛型零值可以使用,需要根据不同的实践去实现,比如</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Aget<span class="token punctuation">[</span>T any<span class="token punctuation">]</span> <span class="token keyword">struct</span> <span class="token punctuation">{</span> + t <span class="token operator">*</span>T +<span class="token punctuation">}</span> +<span class="token comment">// 根据实际判断,如果a的t不等于nil再返回,如果是nil就返回一个T类型的nil(意思就是只声明)</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>Aget<span class="token punctuation">[</span>T<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token function">Approach</span><span class="token punctuation">(</span><span class="token punctuation">)</span> T <span class="token punctuation">{</span> + <span class="token keyword">if</span> a<span class="token punctuation">.</span>t <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token operator">*</span>a<span class="token punctuation">.</span>t + <span class="token punctuation">}</span> + <span class="token keyword">var</span> r T + <span class="token keyword">return</span> r +<span class="token punctuation">}</span> + +</code></pre></div><p>实际上目前,还没一个确切的泛型的零值,那么我们要做的只能是按照实际来具体分析,按照提案,以后有可能使用 <code>return ...</code> <code>return _</code> <code>return</code> <code>return nil</code> <code>return T{}</code> 这些都是可能的结果,我个人比较喜欢 <code>return T{}</code> 来表示泛型的零值,拭目以待吧。</p> <h3 id="无法识别使用了底层数据的其它类型">无法识别使用了底层数据的其它类型</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Float <span class="token keyword">interface</span> <span class="token punctuation">{</span> + ~<span class="token builtin">float32</span> <span class="token operator">|</span> ~<span class="token builtin">float64</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> NewtonSqrt<span class="token punctuation">[</span>T Float<span class="token punctuation">]</span><span class="token punctuation">(</span>v T<span class="token punctuation">)</span> T <span class="token punctuation">{</span> + <span class="token keyword">var</span> iterations <span class="token builtin">int</span> + <span class="token keyword">switch</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token builtin">float32</span><span class="token punctuation">:</span> + iterations <span class="token operator">=</span> <span class="token number">4</span> + <span class="token keyword">case</span> <span class="token builtin">float64</span><span class="token punctuation">:</span> + iterations <span class="token operator">=</span> <span class="token number">5</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + <span class="token function">panic</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"unexpected type %T"</span><span class="token punctuation">,</span> v<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// Code omitted.</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> MyFloat <span class="token builtin">float32</span> + +<span class="token keyword">var</span> G <span class="token operator">=</span> <span class="token function">NewtonSqrt</span><span class="token punctuation">(</span><span class="token function">MyFloat</span><span class="token punctuation">(</span><span class="token number">64</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +</code></pre></div><p>这里约束 Float 拥有的约束类型是 <code>~float32</code> 和 <code>float64</code> 当在 switch 中定义了 float32 和 flaot64 时,无法识别下面的新类型 MyFloat 即使它的底层时 float32,go 的提议是以后在 switch 中使用 <code>case ~float32:</code> 来解决这个问题,目前尚未解决这个问题</p> <h3 id="即便约束一致-类型也是不同的">即便约束一致,类型也是不同的</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> Copy<span class="token punctuation">[</span>T1<span class="token punctuation">,</span> T2 any<span class="token punctuation">]</span><span class="token punctuation">(</span>dst <span class="token punctuation">[</span><span class="token punctuation">]</span>T1<span class="token punctuation">,</span> src <span class="token punctuation">[</span><span class="token punctuation">]</span>T2<span class="token punctuation">)</span> <span class="token builtin">int</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i<span class="token punctuation">,</span> x <span class="token operator">:=</span> <span class="token keyword">range</span> src <span class="token punctuation">{</span> + <span class="token keyword">if</span> i <span class="token operator">></span> <span class="token function">len</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> i + <span class="token punctuation">}</span> + dst<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">T1</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token comment">// x 是 T2类型 不能直接转化为 T1类型</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token function">len</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>T1,和 T2 虽然都是 any 的约束,但是啊,它不是一个类型啊!</p> <div class="language-go extra-class"><pre class="language-go"><code>Copy<span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 这种情况下,你能说可以直接转化吗???</span> +</code></pre></div><p>这种代码可以更改一下</p> <div class="language-go extra-class"><pre class="language-go"><code>dst<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">(</span>T1<span class="token punctuation">)</span> +</code></pre></div><p>确认是一种类型以后才能转化</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://coolshell.cn/articles/21615.html</li> <li>https://go.dev/doc/tutorial/generics</li> <li>https://colobu.com/2021/08/30/how-is-go-generic-implemented/</li> <li>https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md</li> <li>https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/generics</li> <li>https://mp.weixin.qq.com/s/zKnh_iPm8skxWv3rxaOscw</li> <li>https://mp.weixin.qq.com/s/BFsoQPvrog_sMKMTEofZyQ</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/泛型/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/30/2024, 12:34:12 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/41.73deb46e.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\347\273\223\346\236\204\344\275\223/index.html" "b/\345\237\272\347\241\200/\347\273\223\346\236\204\344\275\223/index.html" new file mode 100644 index 000000000..f292024b6 --- /dev/null +++ "b/\345\237\272\347\241\200/\347\273\223\346\236\204\344\275\223/index.html" @@ -0,0 +1,319 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/42.85cfacd9.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/#简单介绍-struct" class="sidebar-link">简单介绍 struct</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/#解耦结构体声明和调用" class="sidebar-link">解耦结构体声明和调用</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/#匿名-struct" class="sidebar-link">匿名 struct</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/#空结构体" class="sidebar-link">空结构体</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E7%BB%93%E6%9E%84%E4%BD%93/#直接嵌套还是作为字段" class="sidebar-link">直接嵌套还是作为字段</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="结构体">结构体</h1> <h2 id="简单介绍-struct">简单介绍 struct</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><ul><li>Peopel 首字母大写,根据我们所学的首字母大写可导出的知识,它是包级可导出结构</li> <li>Addr 首字母大写,所以它是可导出字段,name 和 year 都是小写,所以他们俩不可导出</li></ul> <p>下面看一下结构体的使用</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 初始化</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> p People + p<span class="token punctuation">.</span>Addr <span class="token operator">=</span> <span class="token string">"北京"</span> + p<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"小明"</span> + p<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token number">2000</span> + + <span class="token keyword">var</span> p1 <span class="token operator">=</span> People<span class="token punctuation">{</span> + Addr<span class="token punctuation">:</span> <span class="token string">"北京"</span><span class="token punctuation">,</span> + name<span class="token punctuation">:</span> <span class="token string">"小明"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span> <span class="token number">2000</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + + <span class="token keyword">var</span> p2 <span class="token operator">=</span> <span class="token operator">&</span>People<span class="token punctuation">{</span> + Addr<span class="token punctuation">:</span> <span class="token string">"北京"</span><span class="token punctuation">,</span> + name<span class="token punctuation">:</span> <span class="token string">"小明"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span> <span class="token number">2000</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 结构体的调用</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> p <span class="token operator">=</span> <span class="token operator">&</span>People<span class="token punctuation">{</span> + Addr<span class="token punctuation">:</span> <span class="token string">"北京"</span><span class="token punctuation">,</span> + name<span class="token punctuation">:</span> <span class="token string">"小明"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span> <span class="token number">2000</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + <span class="token comment">// 这里是语法糖,p虽然是people的指针,</span> + <span class="token comment">// 但是它却可以直接调用 Addr</span> + <span class="token comment">// 实际上就是 (*p).Addr 的省略</span> + p<span class="token punctuation">.</span>Addr <span class="token operator">=</span> <span class="token string">"上海"</span> + p<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"小红"</span> + p<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token number">2001</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>Addr<span class="token punctuation">,</span> p<span class="token punctuation">.</span>name<span class="token punctuation">,</span> p<span class="token punctuation">.</span>year<span class="token punctuation">)</span> + + <span class="token comment">// 我们还可以使用new来代替&</span> + <span class="token comment">// 这种写法跟上文中的 var p = &People{} </span> + <span class="token comment">// 一个意思</span> + <span class="token keyword">var</span> p1 <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>People<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>p1<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + name <span class="token builtin">string</span> + year <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="解耦结构体声明和调用">解耦结构体声明和调用</h2> <p>当我们实现结构体的时候,如果显示写出结构体的字段变量名称,就可以不按照顺序,以及可以不完全实现全部字段,这样的话,结构体的声明和实现就可以完全解耦,当然可以隐藏实现的结构体变量,那么你不得不要按照顺序,以及实现全部字段,满足这两者才可以。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 显式实现</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Addr <span class="token builtin">string</span> + name <span class="token builtin">string</span> + year <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> p <span class="token operator">=</span> People<span class="token punctuation">{</span> + Addr<span class="token punctuation">:</span> <span class="token string">"北京"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span> <span class="token keyword">func</span><span class="token punctuation">(</span>a <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">2000</span> <span class="token operator">+</span> a + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>上述代码就是显示的写出了字段的变量名称,你看,name 并没有被写上,这种情况下,name 就会被命名为一个初始值,即 “”</p> <p>这样,即使结构体本身有什么增加字段的行为,实现结构体的逻辑代码也不用改变了。</p> <p>如果是隐式的话,那么必须按照顺序,以及数量进行实现,建议在字段不变以及字段数量非常少的时候使用。</p> <h2 id="匿名-struct">匿名 struct</h2> <p>我们使用匿名 struct,可以完全将另一个结构体嵌入到这个结构体中。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + People + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>使用匿名函数,等于将这个匿名函数的字段完全给予了这个新的结构体,这跟使用这个结构体当作一个字段的类型是不同的,我们看一个例子</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + People People + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码跟上文看起来很像,但是一个是将 people 直接嵌入,一个是当成了它的一个字段类型。让我们看一下这两者使用起来的区别</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student1 <span class="token keyword">struct</span><span class="token punctuation">{</span> + People People + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + People + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student<span class="token punctuation">)</span> + <span class="token keyword">var</span> s1 <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student1<span class="token punctuation">)</span> + s<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"小明"</span> + s<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token string">"2000"</span> + s<span class="token punctuation">.</span>addr <span class="token operator">=</span> <span class="token string">"北京"</span> + s<span class="token punctuation">.</span>score <span class="token operator">=</span> <span class="token number">100</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">.</span>name<span class="token punctuation">,</span> s<span class="token punctuation">.</span>year<span class="token punctuation">,</span> s<span class="token punctuation">.</span>addr<span class="token punctuation">,</span> s<span class="token punctuation">.</span>score<span class="token punctuation">)</span> + s1<span class="token punctuation">.</span>people<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">"小红"</span> + s1<span class="token punctuation">.</span>people<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token string">"2001"</span> + s1<span class="token punctuation">.</span>people<span class="token punctuation">.</span>addr <span class="token operator">=</span> <span class="token string">"上海"</span> + s1<span class="token punctuation">.</span>score <span class="token operator">=</span> <span class="token number">200</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s1<span class="token punctuation">.</span>people<span class="token punctuation">.</span>name<span class="token punctuation">,</span> s1<span class="token punctuation">.</span>people<span class="token punctuation">.</span>year<span class="token punctuation">,</span> s1<span class="token punctuation">.</span>people<span class="token punctuation">.</span>addr<span class="token punctuation">,</span> s1<span class="token punctuation">.</span>score<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们发现匿名函数的字段直接赋予了新的结构体,它不再需要显式的调用 <code>s1.People.name</code></p> <p>实际上,不止一个 struct 可以当作匿名函数,内置类型也是可以的</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + <span class="token builtin">string</span> + People + <span class="token builtin">int</span> + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student<span class="token punctuation">)</span> + s<span class="token punctuation">.</span>People <span class="token operator">=</span> People<span class="token punctuation">{</span> + name<span class="token punctuation">:</span> <span class="token string">"小明"</span><span class="token punctuation">,</span> + year<span class="token punctuation">:</span> <span class="token string">"2000"</span><span class="token punctuation">,</span> + addr<span class="token punctuation">:</span> <span class="token string">"北京"</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + s<span class="token punctuation">.</span><span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">12</span> + s<span class="token punctuation">.</span><span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"12"</span> + s<span class="token punctuation">.</span>score <span class="token operator">=</span> <span class="token number">100</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>函数也可以将指针类型当作类型以及直接嵌入,与非指针相比,我们不能直接调用嵌入的结构体的字段,因为它目前还是 nil,这个时候我们必须先将结构体初始化,然后再进行操作,下文的代码有演示。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + Name <span class="token operator">*</span>Name + <span class="token operator">*</span>People + <span class="token builtin">int</span> + <span class="token builtin">string</span> + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Name <span class="token builtin">string</span><span class="token punctuation">{</span> + fist <span class="token builtin">string</span> + + last <span class="token builtin">string</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student<span class="token punctuation">)</span> + + s<span class="token punctuation">.</span>Name <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Name<span class="token punctuation">)</span> + s<span class="token punctuation">.</span>People <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>People<span class="token punctuation">)</span> + + s<span class="token punctuation">.</span>Name<span class="token punctuation">.</span>first <span class="token operator">=</span> <span class="token string">"小明"</span> + s<span class="token punctuation">.</span>Name<span class="token punctuation">.</span>last <span class="token operator">=</span> <span class="token string">"小红"</span> + s<span class="token punctuation">.</span>name<span class="token operator">=</span> <span class="token string">"小明"</span> + s<span class="token punctuation">.</span>year <span class="token operator">=</span> <span class="token string">"2000"</span> + s<span class="token punctuation">.</span>addr <span class="token operator">=</span> <span class="token string">"北京"</span> + s<span class="token punctuation">.</span><span class="token builtin">int</span> <span class="token operator">=</span> <span class="token number">12</span> + s<span class="token punctuation">.</span><span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">"12"</span> + s<span class="token punctuation">.</span>score <span class="token operator">=</span> <span class="token number">100</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>通过这个演示我们发现,其实嵌入更像是一种语法糖,它就跟将结构体当作类型,前面的结构体字段变量跟这个类型保持一致这种操作是同样的作用,只不过直接嵌入可以将嵌入的字段当作自己的字段,省略了中间的变量罢了,它有下面的等于关系</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Student <span class="token keyword">struct</span><span class="token punctuation">{</span> + <span class="token comment">//People *People</span> + <span class="token comment">// 等于 </span> + <span class="token comment">// *People</span> + + + <span class="token comment">// People People</span> + <span class="token comment">// 等于 </span> + <span class="token comment">// People</span> + + +<span class="token punctuation">}</span> +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当一个结构体拥有了其它嵌入的时,也一起拥有了在他们身上的方法,不过,非嵌入的那种,还是需要带上中间的字段变量名称比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">type</span> Student <span class="token keyword">struct</span> <span class="token punctuation">{</span> + Name Name + <span class="token operator">*</span>People + <span class="token builtin">int</span> + <span class="token builtin">string</span> + score <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> Name <span class="token keyword">struct</span> <span class="token punctuation">{</span> + first <span class="token builtin">string</span> + last <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> People <span class="token keyword">struct</span> <span class="token punctuation">{</span> + name <span class="token builtin">string</span> + year <span class="token builtin">string</span> + addr <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>Name<span class="token punctuation">)</span><span class="token function">S</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"stuend-s"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 如果这里不是定义在指针上的方法,这段代码将报错</span> +<span class="token comment">// 原因是 people嵌入的时候还是nil,如果这里不是指针上的方法,是值上的方法</span> +<span class="token comment">// 底层是需要 *People (取值) 操作的,但是这时候是nil,所以就会报错。</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>People<span class="token punctuation">)</span><span class="token function">SetS</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"people-setS"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span>Student<span class="token punctuation">)</span> + <span class="token comment">// 这里注意,因为不是嵌入的操作,所以它必须带上中间的 Name</span> + s<span class="token punctuation">.</span>Name<span class="token punctuation">.</span><span class="token function">S</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + s<span class="token punctuation">.</span><span class="token function">SetS</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><h2 id="空结构体">空结构体</h2> <p>通常,当我们需要一个临时的变量时,我们可以会想到设置一个 bool 类型,因为我们潜意识中感觉一个 bool 类型是比较小的,但是一个空的变量才是最小的,下面让我们看一个例子,这个例子发生在使用 channel 传递信息这个场景。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + sig <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">bool</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + sig <span class="token operator"><-</span> <span class="token boolean">true</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span> sig + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"任务已经完成"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>没错,这段代码中,使用一个 bool 类型的 channel 是没什么问题的,你甚至也可以使用 int string 都可以,因为只是传递一个信息,信息的内容不重要,但是当我们站在优化的角度来考虑,这里的 bool 就不完美了,我们改成空的结构体即可:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + sig <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + sig <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span> sig + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"任务已经完成"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>需要注意的是,一个空的结构体,表示它类型的方式是 <code>struct{}</code>,而使用这个空结构体的方式就是 <code>struct{}{}</code>,前面的大括号是跟 struct 一起的整体表示空结构体,后面的大括号表示一个空结构体类型的结构体调用</p> <h2 id="直接嵌套还是作为字段">直接嵌套还是作为字段</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Pool <span class="token keyword">struct</span> <span class="token punctuation">{</span> + wg sync<span class="token punctuation">.</span>WaitGroup + JobQueue <span class="token keyword">chan</span> Job + dispatcher <span class="token operator">*</span>dispatcher +<span class="token punctuation">}</span> +<span class="token comment">// or</span> +<span class="token keyword">type</span> Pool <span class="token keyword">struct</span> <span class="token punctuation">{</span> + sync<span class="token punctuation">.</span>WaitGroup + + JobQueue <span class="token keyword">chan</span> Job + dispatcher <span class="token operator">*</span>dispatcher +<span class="token punctuation">}</span> + +</code></pre></div><p>结构体嵌套可能带来的问题:</p> <ul><li><p>名称冲突 +如果 Pool 结构体中还定义了 Add/Done/Wait 方法,和嵌套的 WaitGroup 中的方法就会产生冲突。</p></li> <li><p>不必要的方法 +嵌套整个 WaitGroup 会让 Pool 结构体拥有 Add/Done/Wait 等方法,但 Pool 可能只需要 Wait 就够了。</p></li> <li><p>使结构体臃肿 +嵌套整个 WaitGroup 会让 Pool 结构体看起来很臃肿,包含许多其实用不到的方法。</p></li> <li><p>继承关系不清晰 +Pool 并不是 WaitGroup 的一种,嵌套整个 WaitGroup 让人可能误以为它是在继承 WaitGroup。</p></li></ul> <p>所以,作为一个字段,可以避免上述问题,又可以保持必要的功能。</p> <p>总结一下,嵌套要慎用,只有当:</p> <ul><li>被嵌套的类型方法不会与现有方法冲突</li> <li>被嵌套的所有方法都会被用到</li> <li>两者之间有逻辑上的继承关系</li></ul> <p>时,才更适合使用嵌套 (组合) 的方式。</p> <p>否则,使用字段的方式可以获得必要的功能,而不引入嵌套的潜在问题。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/结构体/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/13/2024, 2:04:03 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/42.85cfacd9.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\351\200\273\350\276\221\345\222\214\345\210\244\346\226\255\350\257\255\345\217\245/index.html" "b/\345\237\272\347\241\200/\351\200\273\350\276\221\345\222\214\345\210\244\346\226\255\350\257\255\345\217\245/index.html" new file mode 100644 index 000000000..a0f32b839 --- /dev/null +++ "b/\345\237\272\347\241\200/\351\200\273\350\276\221\345\222\214\345\210\244\346\226\255\350\257\255\345\217\245/index.html" @@ -0,0 +1,199 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/43.1b441a63.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#if" class="sidebar-link">if</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#for" class="sidebar-link">for</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#string" class="sidebar-link">string</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#map" class="sidebar-link">map</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#channel" class="sidebar-link">channel</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#switch-select" class="sidebar-link">switch && select</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%80%BB%E8%BE%91%E5%92%8C%E5%88%A4%E6%96%AD%E8%AF%AD%E5%8F%A5/#汇总一下-for-和-for-range-中最容易迷惑的几段代码" class="sidebar-link">汇总一下 for 和 for range 中最容易迷惑的几段代码</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="逻辑和判断语句">逻辑和判断语句</h1> <p>go 语言基本上继承了 c 语言的逻辑判断语句,但是仍有些不同,比如:</p> <ul><li>在循环语句中,仅保留了 <code>for</code> 语句,do-while,while 均不支持,这也是满足了 go 小而美的原则 -- 单一功能仅保留一种方式。</li> <li>break continue 后面添加 label 功能</li> <li>switch 中 case 语句不会自动执行下一个 case,需要显示的使用 <code>fallthrough</code>,当然了在 select 中的 case,并没有 fallthrough 功能</li> <li>switch 中 case 支持表达式列表</li> <li>switch 增加 type 模式,让类型也可以作为选择的条件</li> <li>跟 c 语言最大的不同,增加了 select - case 功能。</li></ul> <h2 id="if">if</h2> <p>go 语言中的控制语句基础语法:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> conditon <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> condition<span class="token punctuation">{</span> + +<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +<span class="token comment">// 比如:</span> + +<span class="token keyword">if</span> a <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"a > 0"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token keyword">if</span> a <span class="token operator"><</span> <span class="token number">12</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"a > 0 并且 < 12"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"a > 12 或者是非正数"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>go 语言推崇的控制语句是 “快乐路径”:</p> <ul><li>当出现错误时,直接返回</li> <li>成功的逻辑不要放在 if 语句中</li> <li>返回值通常在此函数的最后一行</li></ul> <div class="language-go extra-class"><pre class="language-go"><code>err<span class="token punctuation">,</span> value <span class="token operator">:=</span> <span class="token function">handle</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err +<span class="token punctuation">}</span> + +<span class="token keyword">return</span> value +</code></pre></div><h2 id="for">for</h2> <p>for 循环的基础语言和 c 类似,for range 语句中,range 后面接数组,指向数组的指针,切片,字符串,和拥有读权限的 channel</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">for</span> i<span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">for</span> k<span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> sliceValue<span class="token punctuation">{</span><span class="token punctuation">}</span> + +</code></pre></div><p>其中普通循环语句中,i 值属于整个 loop 所有,这一点需要好好注意,我们在作用域那一章节中也提到过。</p> <p>for-range 语句中,有两点需要注意,首先跟普通循环一样,变量属于整个 loop 所有。</p> <p>其次,k,v 变量是切片或者 map 的 index 和 value 复制体,当遇到比如 slice 更改数据的时候,切勿直接更改 k v,可使用 <code>arr[k] = v+1</code> 这种方式直接改变切片本身,另外,当使用 for-range 语句时,如果第二个变量没有使用的价值,可以不写,并且无需使用占位符 <code>_</code>:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> sliceValue<span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token comment">// 如果是省略第一个,那么还是需要占位符的</span> + + +<span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> sliceValue<span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>切片在运行时,len 是会变化的,因为确定切片的 len 是 runtime 的责任,而数组的 len 是在编译期确定的,for - range 后面的数组或者切片,真正处理的其实是这个数据的复制,下面看一个 bug</p> <div class="language-go extra-class"><pre class="language-go"><code> + a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> number <span class="token builtin">int</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> a <span class="token punctuation">{</span> + number<span class="token operator">++</span> + <span class="token keyword">if</span> i <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span> + a <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>a<span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token function">println</span><span class="token punctuation">(</span>number<span class="token punctuation">)</span> <span class="token comment">// 5</span> +</code></pre></div><p>这里 number 输出的是 5,因为我们 append 添加的长度是原切片的长度,但是循环体中存储的 len,还是最初的长度 5,所以只能循环 5 次。</p> <p>for-range 中还有一个容易出 bug 的事情,比如 range 后面跟一个数组,因为 range 的时候实际上是数组的复制品,看下面这段代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">}</span> + <span class="token keyword">var</span> r <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> + + <span class="token keyword">for</span> i<span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> a <span class="token punctuation">{</span> + <span class="token keyword">if</span> i <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span> + a<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">12</span> + a<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">13</span> + <span class="token punctuation">}</span> + r<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> v + <span class="token punctuation">}</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>r<span class="token punctuation">,</span> a<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>本来期望的 r 值是 1 12 13 4 5,因为在 i == 0 时就更改了数组 a 的值,但是最终输出的却是 1 2 3 4 5,原因很简单,因为 v 读取的是 a 这个数组的复制品,也就是说,实际上这个代码的隐藏含义是 <code>range a'</code> 这里的 <code>a'</code> 就是 a 的复制品,所以更改了 a,a 的复制品也不会被改变,解决方法就是取这个数组的切片就可以了,这样即便是复制了,也只是复制了一份儿指针而已。</p> <h3 id="string">string</h3> <p>如果 for-range 中后面接的是 string,每次迭代不是按照 byte 来进行的,而是按照 rune 来进行,比如 <code>"你好"</code> 每次的迭代输出的就是你和好,而不是 byte</p> <h3 id="map">map</h3> <p>for range 后面是 map 时,无法保证 map 的输出顺序,但是 map 和 slice 一样都是胖指针,所以时可以对 map 进行直接操作的。如果在循环体中新创建一个 map 项,那么这个项目在 range 时有可能会被输出,不能保证一定。</p> <h3 id="channel">channel</h3> <p>channel 的本质也是一个胖指针,所以它也可以直接被操作本体,channel 在 range 时是阻塞式的读取,如果不关闭 channel,这个 range 会一直阻塞。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> c <span class="token keyword">chan</span> <span class="token builtin">int</span> + +<span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> c <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码就会造成一直阻塞,进而触发系统的 Panic</p> <h2 id="switch-select">switch && select</h2> <p>在 go 语言的 switch 和 select 的 case 中,我们经常会使用 break 来跳出循环,默认跳出的就是最小的那个循环单位,比如下面这个例子</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span> time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token keyword">break</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码是有 bug 的,因为它无法跳出 for 这层循环,只能跳出 select 这里。那么我们该怎么做呢?这个时候应该使用 label 了,所谓 label 就是标签的意思,意思就是指定好了 break 的位置,它的作用就是这个。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + Now<span class="token punctuation">:</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span> time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token keyword">break</span> Now + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这个时候就可以 break 到 Now 指定的层级了。</p> <p>我们应避免使用 fallthrough 来执行多条件表达式,比如这样的代码</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">switch</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token builtin">int</span><span class="token punctuation">:</span> <span class="token keyword">fallthrough</span> + <span class="token keyword">case</span> <span class="token builtin">int8</span><span class="token punctuation">:</span> <span class="token keyword">fallthrough</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"yes"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这种代码也很烂,我们可以直接使用多个 case 并列的方式:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> i <span class="token builtin">int16</span> <span class="token operator">=</span> <span class="token number">12</span> + <span class="token function">a</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">a</span><span class="token punctuation">(</span>v any<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">switch</span> v<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token keyword">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">int8</span><span class="token punctuation">:</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"yes"</span><span class="token punctuation">)</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"no"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码使用的就是判断 type 的断言模式,固定用法就是 <code>value.(type)</code> 前面是要判断的 value,后面是固定用法 type,必须是这个单词才行。</p> <p>我再带你回忆一下普通的断言,<code>a.(int)</code> 除了在 switch 中的断言方式,普通的断言就跟这段代码是一致的,一个 any 类型 (interface {}) 后面跟具体的类型。</p> <p>经过上面的初步介绍,接下来,我们深入看一下 for range 的一些底层原理</p> <h2 id="汇总一下-for-和-for-range-中最容易迷惑的几段代码">汇总一下 for 和 for range 中最容易迷惑的几段代码</h2> <p>第一段代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> arr <span class="token punctuation">{</span> + arr <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码 for 循环不会一直循环,原因是,arr 会在 range 一个复制一份儿,这个复制体的 len 在最初的 range 中的开头已经确定是 3,后面继续追加的 arr,并不会改变这个最初读取的 <code>len == 3</code> 这个结果。</p> <p>不过,如果你使用的是传统的循环,那么这种写法就会出现 bug:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + n <span class="token operator">:=</span> <span class="token number">12</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + n<span class="token operator">++</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"i"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>使用这种传统的 for 循环,因为 n 在循环体和循环内部都是同一个,所以循环不会结束</p> <p>因此你应该将这种代码改写为 for - range 模式:</p> <blockquote><p>go 1.22 增加了对于整数的 for range,之前只有 chan slice map,不过整数的 for range 前面只有一个变量,并且跟其他 for range 一致,n 为复制值,并且 for i := range n,i 也是复制值。这跟其他的 for range 保持一致</p></blockquote> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + n <span class="token operator">:=</span> <span class="token number">12</span> + <span class="token keyword">for</span> <span class="token keyword">range</span> n <span class="token punctuation">{</span> + n<span class="token operator">++</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"i"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>第二段代码:</p> <div class="language-go extra-class"><pre class="language-go"><code>arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +result <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">*</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">for</span> <span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> arr <span class="token punctuation">{</span> +result <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> <span class="token operator">&</span>v<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码是存在 bug 的,&v,首先,根据作用域可知道,这个 v 是 loop 级作用域,那么这个 result 中存在的&v 就是同一个值,所以这个代码是错误的。</p> <p>改正的方式就是放入正确的切片中数据的指针即可:</p> <div class="language-go extra-class"><pre class="language-go"><code>arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> +result <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">*</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">for</span> k <span class="token operator">:=</span> <span class="token keyword">range</span> arr <span class="token punctuation">{</span> +result <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> <span class="token operator">&</span>arr<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>第三段代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">for</span> i<span class="token punctuation">,</span><span class="token boolean">_</span> <span class="token operator">:=</span> <span class="token keyword">range</span> result <span class="token punctuation">{</span> + + result<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这是一段对 int 切片进行归零的方法,很多人会觉得这要循环一次会非常浪费时间,其实不会,因为在编译器中,它不会真的循环,编译器会优化这个操作,直接给它内存清零。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/逻辑和判断语句/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/22/2024, 9:20:13 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/43.1b441a63.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\351\224\231\350\257\257\345\244\204\347\220\206/index.html" "b/\345\237\272\347\241\200/\351\224\231\350\257\257\345\244\204\347\220\206/index.html" new file mode 100644 index 000000000..7e5434fa2 --- /dev/null +++ "b/\345\237\272\347\241\200/\351\224\231\350\257\257\345\244\204\347\220\206/index.html" @@ -0,0 +1,562 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/44.5dc33e34.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#错误处理的基本认识" class="sidebar-link">错误处理的基本认识</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#error-的本质是什么" class="sidebar-link">Error 的本质是什么?</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#自定义-error" class="sidebar-link">自定义 error</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#errors-is" class="sidebar-link">errors.Is()</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#errors-as" class="sidebar-link">errors.As()</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#errors-join" class="sidebar-link">errors.Join()</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#当错误处理遇到了-defer" class="sidebar-link">当错误处理遇到了 defer</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#错误处理实战的五种方式" class="sidebar-link">错误处理实战的五种方式</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#经典的错误处理方式" class="sidebar-link">经典的错误处理方式</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#屏蔽过程中的错误处理" class="sidebar-link">屏蔽过程中的错误处理</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#分层架构中的错误处理方法" class="sidebar-link">分层架构中的错误处理方法</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#pkg-errors" class="sidebar-link">pkg/errors</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#errgroup-的使用技巧" class="sidebar-link">errgroup 的使用技巧</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#错误处理相关技巧" class="sidebar-link">错误处理相关技巧</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#使用-errors-new-时要写清楚包名" class="sidebar-link">使用 errors.New() 时要写清楚包名</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#使用-error-处理一般错误-使用-panic-处理严重错误-异常" class="sidebar-link">使用 error 处理一般错误,使用 panic 处理严重错误 (异常)</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#基础库-应该避免使用-error-types" class="sidebar-link">基础库,应该避免使用 error types</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#优化不必要的代码让程序变得更简洁" class="sidebar-link">优化不必要的代码让程序变得更简洁</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#错误应该只处理一次" class="sidebar-link">错误应该只处理一次</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#业务-code-码的设置" class="sidebar-link">业务 code 码的设置</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#一律返回-http-status-200-具体-code-码单独设置" class="sidebar-link">一律返回 http status 200,具体 code 码单独设置</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#使用合适的-http-status-code-简单的信息以及业务错误代码" class="sidebar-link">使用合适的 http status code + 简单的信息以及业务错误代码</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#使用合适的-http-status-code-非常详细的业务错误代码以及信息" class="sidebar-link">使用合适的 http status code + 非常详细的业务错误代码以及信息</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#业务-code-码的具体设计" class="sidebar-link">业务 code 码的具体设计</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#如何设置-http-status-code" class="sidebar-link">如何设置 http status code</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#设计一个生产级的错误包" class="sidebar-link">设计一个生产级的错误包</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#生产级的错误包需要的功能" class="sidebar-link">生产级的错误包需要的功能</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#具体实现" class="sidebar-link">具体实现</a></li></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="错误处理">错误处理</h1> <h2 id="错误处理的基本认识">错误处理的基本认识</h2> <p>在 go 语言中,没有传统编程语言的 <code>try - catch</code> 操作,go 语言中一切错误都需要显式处理:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">"./x"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err +<span class="token punctuation">}</span> +</code></pre></div><p>通常,我们规定函数返回的最后一个数据是错误接口:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>v <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> v <span class="token operator">></span> <span class="token number">10</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"错误x"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们直接返回一个 err 是一种简单的做法,如果错误比较初级也可以这么做,但是如果想要带有更精确的提示信息,可以在返回的时候 wrap 一层信息:</p> <p>就以上文的读取数据为例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">"./"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"在读取数据的时候发生了错误,错误信息是:%w"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>wrap 一层信息,对于错误的定位更加高效</p> <h2 id="error-的本质是什么">Error 的本质是什么?</h2> <p>错误处理的核心就是下面这一个 error 的接口</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> <span class="token builtin">error</span> <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">string</span> +<span class="token punctuation">}</span> +</code></pre></div><p>所以只要我们的自建类型实现了这个接口,就可以使用很多的错误处理的方法。</p> <h3 id="自定义-error">自定义 error</h3> <p>我们使用 errors.New() 的时候其实就是返回了一个 go 自建的,叫做 errorString 的实现了 error 接口的结构体。 +这就是自建 error 的方法</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + e <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">// (0x47fd48,0xc00003e730)</span> +</code></pre></div><p>为了防止在比较错误的时候发生错误一致的情况,所以自建 error,返回的实际上是一个指针。</p> <blockquote><p>下文会提用什么方法进行比较 err,实际上就是 “两个接口类型是否相等 --- 类型一致,值一致”,如果返回的值是指针,那么值肯定就不可能一样了。</p></blockquote> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// go 源代码</span> + +<span class="token keyword">func</span> <span class="token function">New</span><span class="token punctuation">(</span>s <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token operator">&</span>errorString<span class="token punctuation">{</span>s<span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当我们使用 fmt.Errorf() 的时候,其实也是使用的上述方法。</p> <p>不过,如果我们使用了占位符 <code>%w</code> 时,将不会使用上述方法,而是使用了 wrapError:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> wrapError <span class="token keyword">struct</span> <span class="token punctuation">{</span> + msg <span class="token builtin">string</span> + err <span class="token builtin">error</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>e <span class="token operator">*</span>wrapError<span class="token punctuation">)</span> <span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">string</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> e<span class="token punctuation">.</span>msg +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>e <span class="token operator">*</span>wrapError<span class="token punctuation">)</span> <span class="token function">Unwrap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> e<span class="token punctuation">.</span>err +<span class="token punctuation">}</span> +</code></pre></div><p>使用这种方式主要是为了错误链,那就让我们看一下如何使用错误链的相关操作。</p> <h3 id="errors-is">errors.Is()</h3> <p>上文我们说到,错误可以使用 wrap 的方式进行封装,那么如果我们想判断封装的这么多层的错误中,有没有哪一层错误等于我们要的值,可以使用这个函数进行判断:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + err <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"err is now"</span><span class="token punctuation">)</span> + err1 <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"err1:%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + err2 <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"err1:%w"</span><span class="token punctuation">,</span>err1<span class="token punctuation">)</span> + <span class="token keyword">if</span> errors<span class="token punctuation">.</span><span class="token function">Is</span><span class="token punctuation">(</span>err2<span class="token punctuation">,</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"是一个错误"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="errors-as">errors.As()</h3> <p>这个方法跟上文的 Is() 类似,只不过它判断的是类型是否一致。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> errS <span class="token keyword">struct</span> <span class="token punctuation">{</span> + a <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>t <span class="token operator">*</span>errS<span class="token punctuation">)</span> <span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> +<span class="token keyword">return</span> t<span class="token punctuation">.</span>a +<span class="token punctuation">}</span> + +err <span class="token operator">:=</span> <span class="token operator">&</span>errS<span class="token punctuation">{</span><span class="token string">"typical error"</span><span class="token punctuation">}</span> +err1 <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"wrap err: %w"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span> +err2 <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"wrap err1: %w"</span><span class="token punctuation">,</span> err1<span class="token punctuation">)</span> + +<span class="token keyword">var</span> e <span class="token operator">*</span>errS +<span class="token comment">// 这里的 target 必须使用指针</span> +<span class="token keyword">if</span> <span class="token operator">!</span>errors<span class="token punctuation">.</span><span class="token function">As</span><span class="token punctuation">(</span>err2<span class="token punctuation">,</span> <span class="token operator">&</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"TypicalErr is not on the chain of err2"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"TypicalErr is on the chain of err2"</span><span class="token punctuation">)</span> + <span class="token function">println</span><span class="token punctuation">(</span>err <span class="token operator">==</span> e<span class="token punctuation">)</span> +</code></pre></div><h3 id="errors-join">errors.Join()</h3> <p>这个方法是将几个错误结合在一起的方法:</p> <div class="language-go extra-class"><pre class="language-go"><code> err1 <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"err1:%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + err2 <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"err1:%w"</span><span class="token punctuation">,</span>err1<span class="token punctuation">)</span> + err <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">Join</span><span class="token punctuation">(</span>err1<span class="token punctuation">,</span>err2<span class="token punctuation">)</span> +</code></pre></div><h2 id="当错误处理遇到了-defer">当错误处理遇到了 defer</h2> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> xx <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">0</span> <span class="token punctuation">,</span>err + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> f<span class="token punctuation">.</span><span class="token builtin">close</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段伪代码的意思是说,当有条件之后,返回一个错误,但是 defer 的内容发生在这个 err 被固定之后,所以 defer 中如果再有错误将不会被处理。</p> <p>那么我们该怎么更改呢?</p> <p>我想你一定想到了前文我们说过,使用带有变量的返回值是可以将 defer 的值进行返回的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span> i <span class="token builtin">int</span><span class="token punctuation">,</span> e <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> xx <span class="token punctuation">{</span> + e <span class="token operator">=</span> xx + i <span class="token operator">=</span> xx + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> f<span class="token punctuation">.</span><span class="token builtin">close</span> +<span class="token punctuation">}</span> +</code></pre></div><p>那么这种写法,defer 中如果发生了错误就会覆盖掉了程序执行中的 err,所以这种方法也是不行的,即使它能照顾到了 defer 中的错误处理。</p> <p>我们可以将错误处理都放在 defer 中处理就可以了</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span> i <span class="token builtin">int</span><span class="token punctuation">,</span> e <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> xx <span class="token punctuation">{</span> + i <span class="token operator">=</span> xx + e <span class="token operator">=</span> xx + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + e1 <span class="token operator">:=</span> f<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> e <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> e1 <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">log</span><span class="token punctuation">(</span>e1<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + err <span class="token operator">=</span> e1 + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这样,两种错误都能处理到了</p> <h2 id="错误处理实战的五种方式">错误处理实战的五种方式</h2> <h3 id="经典的错误处理方式">经典的错误处理方式</h3> <p>每一个步骤分别直接处理错误</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> age <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span> + <span class="token function">putAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span> + <span class="token function">allAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">D</span><span class="token punctuation">(</span>ag age<span class="token punctuation">)</span><span class="token builtin">error</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> ag<span class="token punctuation">.</span><span class="token function">getAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> ag<span class="token punctuation">.</span><span class="token function">putAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> ag<span class="token punctuation">.</span><span class="token function">allAge</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="屏蔽过程中的错误处理">屏蔽过程中的错误处理</h3> <p>将错误放置在对象的内部进行处理:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> FileCopier <span class="token keyword">struct</span><span class="token punctuation">{</span> + w <span class="token operator">*</span>os<span class="token punctuation">.</span>File + r <span class="token operator">*</span>os<span class="token punctuation">.</span>File + err <span class="token builtin">error</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>f <span class="token operator">*</span>FileCopier<span class="token punctuation">)</span><span class="token function">open</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">(</span> <span class="token operator">*</span>os<span class="token punctuation">.</span>File<span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> f<span class="token punctuation">.</span>err + <span class="token punctuation">}</span> + + h<span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span> + <span class="token keyword">if</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + f<span class="token punctuation">.</span>err <span class="token operator">=</span> err + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> err + <span class="token punctuation">}</span> + <span class="token keyword">return</span> h<span class="token punctuation">,</span><span class="token boolean">nil</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span><span class="token punctuation">(</span>f <span class="token operator">*</span>FileCopier<span class="token punctuation">)</span><span class="token function">OpenSrc</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + f<span class="token punctuation">.</span>r<span class="token punctuation">,</span>f<span class="token punctuation">.</span>err <span class="token operator">=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span> + <span class="token keyword">return</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>f <span class="token operator">*</span>FileCopier<span class="token punctuation">)</span> <span class="token function">CopyFile</span><span class="token punctuation">(</span>src<span class="token punctuation">,</span> dst <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> f<span class="token punctuation">.</span>err + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>r <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + f<span class="token punctuation">.</span>r<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>w<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + f<span class="token punctuation">.</span>w<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> f<span class="token punctuation">.</span>w <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + os<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + + f<span class="token punctuation">.</span><span class="token function">opensrc</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span> + f<span class="token punctuation">.</span><span class="token function">createDst</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> + <span class="token keyword">return</span> f<span class="token punctuation">.</span>err + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码并不是特别完整,但是从中我们还是可以理解这种将错误放在对象中的写法的技巧。</p> <p>首先,错误直接放置在对象自身,在方法中首先去调用这个字段来看是否拥有错误,如果有,直接退出即可</p> <p>如果没有错误继续往下走,如果本次方法发生错误就继续将这个错误赋值给这个字段,</p> <p>当最后处理的方法时,这里也就是 copyfile 方法,我们在 defer 中要对于各个子方法进行判断,到底是哪个方法有错误,然后逐一进行判定。相当于处理错误的逻辑集中放置到了最后一个函数进行执行了。</p> <p>也就是说,将错误放置在对象本身的时候,通常应该为顺序调用的方法,一旦前者出现错误,后者即可退出</p> <p>如果不是顺序的执行过程,那么有些的错误就可能被湮没,导致错误无法被感知。</p> <h3 id="分层架构中的错误处理方法">分层架构中的错误处理方法</h3> <p>常见的分层架构</p> <ul><li>controller 控制层</li> <li>service 服务层</li> <li>dao 数据访问层</li></ul> <p>dao 层生产错误</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>service 追加错误</p> <div class="language-go extra-class"><pre class="language-go"><code>err <span class="token operator">:=</span> a<span class="token punctuation">.</span>Dao<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"getname err: %w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>controller 打印错误</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="pkg-errors">pkg/errors</h3> <p>如果感觉标准库提供的错误处理不够丰富,也可以使用 github.com/pkg/errors 来处理错误</p> <p>此包常用的方法有</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 生成新的错误,同样会附加堆栈信息</span> +<span class="token keyword">func</span> <span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span> +<span class="token comment">// 只附加新的消息</span> +<span class="token keyword">func</span> <span class="token function">WithMessage</span><span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">,</span>message <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> +<span class="token comment">// 只附加堆栈信息</span> +<span class="token keyword">func</span> <span class="token function">WithStack</span><span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token builtin">error</span> +<span class="token comment">// 附加信息 + 堆栈信息(就是一大堆的各种文件的堆栈调用过程的详细信息)</span> +<span class="token keyword">func</span> <span class="token function">Wrapf</span><span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">,</span>format <span class="token builtin">string</span><span class="token punctuation">,</span>args<span class="token operator">...</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token builtin">error</span> +<span class="token comment">// 获取最根本的错误(错误链的最底层)</span> +<span class="token keyword">func</span> <span class="token function">Cause</span><span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token builtin">error</span> +</code></pre></div><p>例如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + err <span class="token operator">:=</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// %+v 是 pkg/errors 包提供的格式化输出格式,输出错误堆栈</span> + fmt<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"%+v"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> errors<span class="token punctuation">.</span><span class="token function">Wrap</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span><span class="token string">"open error"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在使用这个 pkg/errors 包的时候要注意一件事,因为 wrap 可以包装堆栈向上输出,如果你调用的第三方库使用了 wrap,你再次使用 wrap,那么就会出现两堆相同的堆栈信息,这造成了极大的冗余。</p> <p>所以,</p> <ul><li>在提供多人使用的三方库的时候不要使用 wrap,只有逻辑代码的时候使用 wrap 的功能</li> <li>遇到一个错误不打算处理,那么要带上足够多的信息再向上抛出</li> <li>一旦错误处理完成之后就没有错误了,不再需要把错误继续网上抛,返回 nil 即可</li></ul> <p>所以我们使用 pkg/errors 包将上面的分层写法做一个更完善的改进:</p> <p>dao 层生产错误</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// a</span> +<span class="token keyword">func</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// 返回此处的错误堆栈</span> + <span class="token keyword">return</span> errors<span class="token punctuation">.</span><span class="token function">Wrap</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span><span class="token string">"error:"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>service 追加错误</p> <div class="language-go extra-class"><pre class="language-go"><code>err <span class="token operator">:=</span> a<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// 不返回堆栈了,仅仅添加错误</span> + <span class="token keyword">return</span> errors<span class="token punctuation">.</span><span class="token function">WithMessage</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span><span class="token string">"getName error"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>controller 打印错误</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// 添加日志</span> + <span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="errgroup-的使用技巧">errgroup 的使用技巧</h3> <p>errgroup 的使用方法是 golang.org/x/sync/errgroup</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"fmt"</span> + <span class="token string">"golang.org/x/sync/errgroup"</span> +<span class="token punctuation">)</span> + + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + g<span class="token punctuation">,</span> ctx <span class="token operator">:=</span> errgroup<span class="token punctuation">.</span><span class="token function">WithContext</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token comment">// 启动一个 goroutine去处理错误</span> + g<span class="token punctuation">.</span><span class="token function">Go</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"error1"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + g<span class="token punctuation">.</span><span class="token function">Go</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"error2"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token comment">// 类似 waitgroup 的 wait 方法</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> g<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="错误处理相关技巧">错误处理相关技巧</h2> <p>这里会介绍在实战过程中用到的诸多技巧</p> <h3 id="使用-errors-new-时要写清楚包名">使用 errors.New() 时要写清楚包名</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> age + +ErrMyAge <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"age: ErrMyAge is error"</span><span class="token punctuation">)</span> +ErrMyAddress <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"age: ErrMyAddress is error"</span><span class="token punctuation">)</span> +</code></pre></div><h3 id="使用-error-处理一般错误-使用-panic-处理严重错误-异常">使用 error 处理一般错误,使用 panic 处理严重错误 (异常)</h3> <p>使用这种模型就避免了类似 Java 那种所有错误都一样的行为,Java 的使用 try-catch 的方式导致任何错误都是一个方式去处理,非常有可能让程序员忽略错误的处理</p> <p>然而 go 不同,<strong>错误</strong>使用 error,<strong>异常</strong>使用 panic 的方式去处理。</p> <ul><li>错误:error</li> <li>异常:panic</li></ul> <p>假设我们在代码中使用了 panic,通常来说,为了代码的健壮性还是会使用 defer 函数去运行一个 recover() 的,程序的存活比啥都重要。</p> <h3 id="基础库-应该避免使用-error-types">基础库,应该避免使用 error types</h3> <p>因为这种写法容易造成代码的耦合,尤其是在我们写的基础库中,非常容易造成改动代码来引入的不健壮性。</p> <p>使用自定义的 error type</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token comment">// 为了额外增加更多的错误信息,字段需大写</span> +<span class="token keyword">type</span> ErrMyAge <span class="token keyword">struct</span> <span class="token punctuation">{</span> + EV <span class="token builtin">string</span> + MErr <span class="token builtin">int</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>e <span class="token operator">*</span>ErrMyAge<span class="token punctuation">)</span> <span class="token function">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"age: %s"</span><span class="token punctuation">,</span> e<span class="token punctuation">.</span>EV<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + err <span class="token operator">:=</span> <span class="token operator">&</span>ErrMyAge<span class="token punctuation">{</span><span class="token string">"err age is hi"</span><span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>使用 errors.New() 哨兵错误模式:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 我方代码</span> +ErrAge <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"age: ErrAge is error"</span><span class="token punctuation">)</span> +ErrAddress <span class="token operator">:=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"age: ErrAddress is error"</span><span class="token punctuation">)</span> + +<span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">--</span><span class="token operator">-</span> +<span class="token comment">// 使用者</span> + +<span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"github.com/shgopher/age"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 带来了耦合</span> + <span class="token keyword">if</span> errors<span class="token punctuation">.</span><span class="token function">Is</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span> age<span class="token punctuation">.</span>ErrAge<span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 处理</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>实际上他们都是 error types,只不过前者比后者增加了很多额外的信息,但是相同点是,他们都造成了耦合</p> <p>如果别人使用了这个基础库,那么势必这些错误就会跟使用者的代码耦合,我们改动了代码,第三方的代码就会因此受到影响。</p> <p>因此,在对外暴露的基础包中,我们应尽量减少定义哨兵错误 (上述定义方法被称之为哨兵模式的错误)</p> <p>上述提供的哨兵模式是透明的错误导出机制,所以容易造成耦合</p> <p>我们可以提供不透明的机制,不导出透明的错误类型,仅仅让用户判断是否等于 nil,就可以防止耦合的存在</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span><span class="token string">"github.com/shgopher/age"</span><span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + + <span class="token keyword">if</span> err<span class="token operator">:=</span> age<span class="token punctuation">.</span><span class="token function">Bar</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>这也是大多数程序应该提供的模式,不对外暴露,避免了耦合</p> <p>那么这种方法的缺陷也很明显了,就是无法获取更多的错误信息,理论上来说,我们也没必要获取那么多错误信息,但是如果真的要获取错误信息了,该如何去做呢?</p> <p>我们可以向外暴露一些动作,只暴露行为:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> mage <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 通过一个对外暴露的函数可以对外输出行为</span> +<span class="token comment">// 并且还不用暴露出具体的对象</span> +<span class="token keyword">func</span> <span class="token function">IsMage</span><span class="token punctuation">(</span>err <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token builtin">bool</span> <span class="token punctuation">{</span> + a<span class="token punctuation">,</span> ok <span class="token operator">:=</span> err<span class="token punctuation">.</span><span class="token punctuation">(</span>mage<span class="token punctuation">)</span> + <span class="token keyword">return</span> ok <span class="token operator">&&</span> a<span class="token punctuation">.</span><span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="优化不必要的代码让程序变得更简洁">优化不必要的代码让程序变得更简洁</h3> <p>方法一将大函数变小函数,通过封装函数的方法从视觉上降低 if err 的影响。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 改造之前</span> + +<span class="token keyword">func</span> <span class="token function">OpenFile</span><span class="token punctuation">(</span>src <span class="token punctuation">,</span>dst <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> r<span class="token punctuation">,</span>err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">if</span> w<span class="token punctuation">,</span>err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + r<span class="token punctuation">.</span><span class="token function">Cloase</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span>err <span class="token operator">:=</span> io<span class="token punctuation">.</span><span class="token function">Copy</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span>r<span class="token punctuation">)</span><span class="token punctuation">;</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 将前面两个操作封装成一个函数</span> + +<span class="token keyword">func</span> <span class="token function">OpenD</span><span class="token punctuation">(</span>src dst <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>os<span class="token punctuation">.</span>File<span class="token punctuation">,</span><span class="token operator">*</span>os<span class="token punctuation">.</span>File<span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> r <span class="token punctuation">,</span>w <span class="token operator">*</span>os<span class="token punctuation">.</span>File + <span class="token keyword">var</span> err <span class="token builtin">error</span> + + <span class="token keyword">if</span> r<span class="token punctuation">,</span>err <span class="token operator">=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">;</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span><span class="token boolean">nil</span><span class="token punctuation">,</span>err + <span class="token punctuation">}</span> + <span class="token keyword">if</span> w<span class="token punctuation">,</span>err <span class="token operator">=</span> os<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span><span class="token punctuation">;</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + r<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span><span class="token boolean">nil</span><span class="token punctuation">,</span>err + <span class="token punctuation">}</span> + + <span class="token keyword">return</span> r<span class="token punctuation">,</span>w<span class="token punctuation">,</span>err +<span class="token punctuation">}</span> +<span class="token comment">// 主函数就只有一个 if err 了</span> +<span class="token keyword">func</span> <span class="token function">OpenFile</span><span class="token punctuation">(</span>src<span class="token punctuation">,</span>dst <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token builtin">error</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> err <span class="token builtin">error</span> + <span class="token keyword">var</span> r<span class="token punctuation">,</span> w <span class="token operator">*</span>os<span class="token punctuation">.</span>File + <span class="token keyword">if</span> r<span class="token punctuation">,</span>w<span class="token punctuation">,</span>err <span class="token operator">=</span> <span class="token function">OpenD</span><span class="token punctuation">(</span>src<span class="token punctuation">,</span>dst<span class="token punctuation">)</span><span class="token punctuation">;</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + r<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + w<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span>err <span class="token operator">=</span> io<span class="token punctuation">.</span><span class="token function">Copy</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span>r<span class="token punctuation">)</span><span class="token punctuation">;</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +</code></pre></div><p>方法二将代码中不必要的成分删除,来保证代码的简洁</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 改造前</span> +<span class="token keyword">func</span> <span class="token function">AuthticateRequest</span><span class="token punctuation">(</span>r <span class="token operator">*</span>Request<span class="token punctuation">)</span><span class="token builtin">error</span><span class="token punctuation">{</span> + err <span class="token operator">:=</span> <span class="token function">authticate</span><span class="token punctuation">(</span>r<span class="token punctuation">.</span>User<span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> +<span class="token punctuation">}</span> +<span class="token comment">// 实际上 authticate 只返回一个 error 类型的接口,根本不需要判断</span> +<span class="token keyword">func</span> <span class="token function">AuthticateRequest</span><span class="token punctuation">(</span>r <span class="token operator">*</span>Request<span class="token punctuation">)</span><span class="token builtin">error</span><span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">authticate</span><span class="token punctuation">(</span>r<span class="token punctuation">.</span>User<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>方法三使用更加合适的方法</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 我们要逐行去读取数据</span> + +<span class="token comment">// 改造前</span> +<span class="token keyword">func</span> <span class="token function">Countlines</span><span class="token punctuation">(</span>r io<span class="token punctuation">.</span>Reader<span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span><span class="token punctuation">(</span> + br <span class="token operator">=</span> bufio<span class="token punctuation">.</span><span class="token function">NewReader</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> + line <span class="token builtin">int</span> + err <span class="token builtin">error</span> + <span class="token punctuation">)</span> + + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token boolean">_</span><span class="token punctuation">,</span>err <span class="token operator">=</span> br<span class="token punctuation">.</span><span class="token function">readline</span><span class="token punctuation">(</span><span class="token char">'\n'</span><span class="token punctuation">)</span> + line <span class="token operator">++</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">break</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> io<span class="token punctuation">.</span>EOF <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">,</span>err + <span class="token punctuation">}</span> + <span class="token keyword">return</span> lines<span class="token punctuation">,</span><span class="token boolean">nil</span> + +<span class="token punctuation">}</span> + +<span class="token comment">// 代码看起来也是很合理的样子,也很简洁,但是,我们其实用的函数不是特别的合适</span> + +<span class="token comment">//其实这里使用 scan 更加合适,代码量更加精简,并且结构异常舒服</span> +<span class="token keyword">func</span> <span class="token function">Countlines</span><span class="token punctuation">(</span>r io<span class="token punctuation">.</span>Reader<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + sc <span class="token operator">:=</span> bufio<span class="token punctuation">.</span><span class="token function">NewScanner</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> + lines <span class="token operator">:=</span> <span class="token number">0</span> + + <span class="token keyword">for</span> sc<span class="token punctuation">.</span><span class="token function">Scan</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + lines<span class="token operator">++</span> + <span class="token punctuation">}</span> + + <span class="token keyword">return</span> lines<span class="token punctuation">,</span> sc<span class="token punctuation">.</span><span class="token function">Err</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><h3 id="错误应该只处理一次">错误应该只处理一次</h3> <p>我们有日志系统,有些时候我们发现一个错误,然后打了一个日志,然后又把错误给 return 了,实际上这与 go 语言哲学中说的错误只处理一次相违背</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌</span> +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span><span class="token punctuation">{</span> + <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"./a"</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + log<span class="token punctuation">.</span><span class="token function">Prinln</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ✅</span> +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token builtin">error</span><span class="token punctuation">{</span> + <span class="token boolean">_</span><span class="token punctuation">,</span> err <span class="token operator">:=</span> os<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token string">"./a"</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err<span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> errors<span class="token punctuation">.</span><span class="token function">Wrap</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span><span class="token string">"open error"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>正确的处理方法是错误只处理一次,那么在什么时候处理呢?</p> <p>上文提到了多层的架构设计,我们在底层 (带有堆栈的错误向上抛出) 和中层 (仅仅附加信息再次向上抛出) 仅仅是向上抛出,并不需要将错误记录在日志中,在应用层才需要去使用日志记录错误,日志记录完错误以后,也不需要再向上抛出错误了 (最顶端了) 完全满足 “只处理一次错误” 的要求。</p> <h2 id="业务-code-码的设置">业务 code 码的设置</h2> <p>常见的 http 错误码数量较少,比如常见的只有例如 404 301 302 200 503 等,绝对数量还是较少,无法去表达业务上的错误,因此我们需要设置一套能表达具体生产业务的 code 码。</p> <p>为了保证服务端的安全,我们设置的 code 码应该设置两套数据,一套显示给客户端,一套自用,以此来保证服务端的绝对安全。</p> <p>有三种设计业务 code 码的方式:</p> <h3 id="一律返回-http-status-200-具体-code-码单独设置">一律返回 http status 200,具体 code 码单独设置</h3> <p>例如</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> + <span class="token property">"error"</span><span class="token operator">:</span> <span class="token punctuation">{</span> + <span class="token property">"message"</span><span class="token operator">:</span> <span class="token string">"Syntax error \"Field picture specified more than once. This is only possible before version 2.1\" at character 23: id,name,picture,picture"</span><span class="token punctuation">,</span> + <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"OAuthException"</span><span class="token punctuation">,</span> + <span class="token property">"code"</span><span class="token operator">:</span> <span class="token number">2500</span><span class="token punctuation">,</span> + <span class="token property">"fbtrace_id"</span><span class="token operator">:</span> <span class="token string">"xxxxxxxxxxx"</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><ul><li>http status code 通通 200</li> <li>code 2500,才是真实的面向客户端的 code 码</li></ul> <p>使用这种方法的一大缺陷就是必须解析 body 内容才能发现具体的错误业务码,很多场景我们仅仅需要知道返回的是成功或者错误,并不需要知晓具体的业务码,这是这种方式的一大弊端。</p> <h3 id="使用合适的-http-status-code-简单的信息以及业务错误代码">使用合适的 http status code + 简单的信息以及业务错误代码</h3> <div class="language-bash extra-class"><pre class="language-bash"><code>HTTP/1.1 <span class="token number">400</span> Bad Request +x-connection-hash: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +set-cookie: <span class="token assign-left variable">guest_id</span><span class="token operator">=</span>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +Date: Thu, 01 Jun <span class="token number">2017</span> 03:04:23 GMT +Content-Length: <span class="token number">62</span> +x-response-time: <span class="token number">5</span> +strict-transport-security: max-age<span class="token operator">=</span><span class="token number">631138519</span> +Connection: keep-alive +Content-Type: application/json<span class="token punctuation">;</span> <span class="token assign-left variable">charset</span><span class="token operator">=</span>utf-8 +Server: tsa_b + +<span class="token comment"># 注意这里:仅仅返回简单的错误信息</span> +<span class="token punctuation">{</span><span class="token string">"errors"</span>:<span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string">"code"</span>:215,<span class="token string">"message"</span><span class="token builtin class-name">:</span><span class="token string">"Bad Authentication data."</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">}</span> +</code></pre></div><p>这种方案也是大多数公司采纳的方案,使用具体的 http status code 可以知晓大概的业务类型,是错误还是正常运行,然后使用简单的错误信息和业务错误代码去定位具体的错误</p> <p>如果业务不是特别复杂,使用这种方式即可</p> <h3 id="使用合适的-http-status-code-非常详细的业务错误代码以及信息">使用合适的 http status code + 非常详细的业务错误代码以及信息</h3> <div class="language-bash extra-class"><pre class="language-bash"><code>HTTP/1.1 <span class="token number">400</span> +Date: Thu, 01 Jun <span class="token number">2017</span> 03:40:55 GMT +Content-Length: <span class="token number">276</span> +Connection: keep-alive +Content-Type: application/json<span class="token punctuation">;</span> <span class="token assign-left variable">charset</span><span class="token operator">=</span>utf-8 +Server: Microsoft-IIS/10.0 +X-Content-Type-Options: nosniff + +<span class="token punctuation">{</span><span class="token string">"SearchResponse"</span>:<span class="token punctuation">{</span><span class="token string">"Version"</span><span class="token builtin class-name">:</span><span class="token string">"2.2"</span>,<span class="token string">"Query"</span>:<span class="token punctuation">{</span><span class="token string">"SearchTerms"</span><span class="token builtin class-name">:</span><span class="token string">"api error codes"</span><span class="token punctuation">}</span>,<span class="token string">"Errors"</span>:<span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string">"Code"</span>:1001,<span class="token string">"Message"</span><span class="token builtin class-name">:</span><span class="token string">"Required parameter is missing."</span>,<span class="token string">"Parameter"</span><span class="token builtin class-name">:</span><span class="token string">"SearchRequest.AppId"</span>,<span class="token string">"HelpUrl"</span><span class="token builtin class-name">:</span><span class="token string">"http<span class="token entity" title="\u003a">\u003a</span><span class="token entity" title="\u002f">\u002f</span><span class="token entity" title="\u002f">\u002f</span>msdn.microsoft.com<span class="token entity" title="\u002f">\u002f</span>en-us<span class="token entity" title="\u002f">\u002f</span>library<span class="token entity" title="\u002f">\u002f</span>dd251042.aspx"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">}</span> +</code></pre></div><p>当业务逻辑稍微复杂一些,并且需要极其精准和快速的定位错误时,就需要在返回的 body 中去设置非常详细的错误信息</p> <p><strong>综上所述:</strong></p> <ul><li>使用正确的 http status code 让业务的第一步变得更加直观</li> <li>区别于 http status code,具体业务的 code 码会更加丰富</li> <li>返回尽可能详细的错误,有助于复杂逻辑的快速错误定位</li> <li>直接返回给客户的错误代码不应该包括敏感信息,敏感信息的 code 码仅供内部使用</li> <li>错误信息要求规范,简洁以及有用</li></ul> <h3 id="业务-code-码的具体设计">业务 code 码的具体设计</h3> <p>引入业务 code 码的核心原因就是 http status code 太少,以及他们并不能跟具体业务挂钩。</p> <p>当我们设置好良好又详细的 code 码时,我们就可以快速定位业务代码,以及可以快速知晓发生错误的等级模块,具体信息等</p> <p>下面给出具体的设计思路:<strong>纯数字表达,不同的数字段表达不同的模块不同的业务</strong></p> <p>例如 100101</p> <ul><li>10:表示某个服务</li> <li>01:表示某个服务下的模块</li> <li>01:模块下的错误码</li></ul> <p>10 服务 01 模块 01 错误,--- 服务 10 数据库模块未找到记录错误</p> <p>一共最多有 100 个服务,每个服务最多有 100 个模块,每个模块最多有 100 个错误,如果某些模块 100 个都不够用,那怎么这个模块有必要去拆分一下了。</p> <h3 id="如何设置-http-status-code">如何设置 http status code</h3> <ul><li><code>1xx</code>:请求已接收,继续处理</li> <li><code>2xx</code>:成功处理了请求</li> <li><code>3xx</code>:请求被重定向</li> <li><code>4xx</code>:请求错误</li> <li><code>5xx</code>:服务器错误</li></ul> <p>由于 http status code 相对数量也不算太少,如果每一个都利用上,难免会增加复杂度,建议仅使用基本的几个即可</p> <ul><li>200 - 表示请求成功执行。</li> <li>400 - 表示客户端出问题。</li> <li>500 - 表示服务端出问题。</li></ul> <p>如果上述的感觉太少,再增加下面几个也可以</p> <ul><li>401 - 表示认证失败。</li> <li>403 - 表示授权失败。</li> <li>404 - 表示资源找不到,这里的资源可以是 URL 或者 RESTful 资源。</li></ul> <p>将 http status code 控制在<strong>个位数</strong>,有利于后端的逻辑代码简洁性,比如 301 302 确实是代表不同的含义,<strong>前端或许可以设置丰富的 http status code,因为浏览器会进行相关的具体操作,但是后端返回给前端的 http status code 并没有任何的操作,使用过多只会增加复杂度。</strong></p> <h2 id="设计一个生产级的错误包">设计一个生产级的错误包</h2> <h3 id="生产级的错误包需要的功能">生产级的错误包需要的功能</h3> <ol><li>支持错误堆栈</li></ol> <div class="language-go extra-class"><pre class="language-go"><code><span class="token number">2021</span><span class="token operator">/</span><span class="token number">07</span><span class="token operator">/</span><span class="token number">02</span> <span class="token number">14</span><span class="token punctuation">:</span><span class="token number">17</span><span class="token punctuation">:</span><span class="token number">03</span> call <span class="token keyword">func</span> got failed<span class="token punctuation">:</span> <span class="token keyword">func</span> called <span class="token builtin">error</span> + +main<span class="token punctuation">.</span>funcB <span class="token operator">/</span>home<span class="token operator">/</span>colin<span class="token operator">/</span>workspace<span class="token operator">/</span>golang<span class="token operator">/</span>src<span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>marmotedu<span class="token operator">/</span>gopractise<span class="token operator">-</span>demo<span class="token operator">/</span>errors<span class="token operator">/</span>good<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">27</span> +main<span class="token punctuation">.</span>funcA <span class="token operator">/</span>home<span class="token operator">/</span>colin<span class="token operator">/</span>workspace<span class="token operator">/</span>golang<span class="token operator">/</span>src<span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>marmotedu<span class="token operator">/</span>gopractise<span class="token operator">-</span>demo<span class="token operator">/</span>errors<span class="token operator">/</span>good<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">19</span> +main<span class="token punctuation">.</span>main <span class="token operator">/</span>home<span class="token operator">/</span>colin<span class="token operator">/</span>workspace<span class="token operator">/</span>golang<span class="token operator">/</span>src<span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>marmotedu<span class="token operator">/</span>gopractise<span class="token operator">-</span>demo<span class="token operator">/</span>errors<span class="token operator">/</span>good<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">10</span> +runtime<span class="token punctuation">.</span>main <span class="token operator">/</span>home<span class="token operator">/</span>colin<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">/</span>go1<span class="token punctuation">.</span><span class="token number">16.2</span><span class="token operator">/</span>src<span class="token operator">/</span>runtime<span class="token operator">/</span>proc<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span>225runtime<span class="token punctuation">.</span>goexit <span class="token operator">/</span>home<span class="token operator">/</span>colin<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">/</span>go1<span class="token punctuation">.</span><span class="token number">16.2</span><span class="token operator">/</span>src<span class="token operator">/</span>runtime<span class="token operator">/</span>asm_amd64<span class="token punctuation">.</span>s<span class="token punctuation">:</span><span class="token number">1371</span> +exit status <span class="token number">1</span> +</code></pre></div><p>拥有错误的堆栈,我们才能定位错误的根源。</p> <ol start="2"><li><p>支持打印不同的格式比如 %s %w %d</p></li> <li><p>支持 Wrap() Unwrap() 的功能,就是错误的嵌套和反嵌套</p></li> <li><p>错误包要支持 Is() 和 As() 方法,这主要是因为有错误的嵌套,所以无法再使用接口相比较的方式进行判断接口类型是否相等 (类型相同,值相同)</p></li> <li><p>要支持格式化和非格式化的创建方式</p></li></ol> <div class="language-go extra-class"><pre class="language-go"><code>errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"err"</span><span class="token punctuation">)</span> +fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"%w"</span><span class="token punctuation">,</span>err<span class="token punctuation">)</span> +</code></pre></div><h3 id="具体实现">具体实现</h3> <p>从 github.com/pkg/errors 包中改造即可。</p> <p>增加以下字段的结构体就可以满足上面的需求</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> withCode <span class="token keyword">struct</span> <span class="token punctuation">{</span> + err <span class="token builtin">error</span> + code <span class="token builtin">int</span> + cause <span class="token builtin">error</span> + <span class="token operator">*</span>stack +<span class="token punctuation">}</span> +</code></pre></div><h2 id="issues">issues</h2> <p><code>问题一:</code> <strong>请说出下列代码的执行输出</strong>*</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"3"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"2"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"1"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi1"</span><span class="token punctuation">)</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"oops"</span><span class="token punctuation">)</span> + <span class="token comment">// 这里的defer将不会进栈,所以也就不会执行了。</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"x"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi2"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>答案是</p> <div class="language-go extra-class"><pre class="language-go"><code>hi1 +<span class="token number">1</span> +<span class="token number">2</span> +<span class="token number">3</span> +oops +<span class="token builtin">panic</span><span class="token punctuation">:</span> oops + +goroutine <span class="token number">1</span> <span class="token punctuation">[</span>running<span class="token punctuation">]</span><span class="token punctuation">:</span> +main<span class="token punctuation">.</span><span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator">/</span>tmp<span class="token operator">/</span>sandbox1932632082<span class="token operator">/</span>prog<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">18</span> <span class="token operator">+</span><span class="token number">0xa7</span> + +Program exited<span class="token punctuation">.</span> +</code></pre></div><p>解释:Panic,意味着恐慌,意思等于 return,所以 panic 下面的数据是无法执行的,defer 不同,他们是顺序的将这些 defer 函数装入函数内置的 defer 栈的,所以在 return 之后,defer 栈会执行,所以这里的 defer 1 2 3 可以执行,Panic 前面的 hi1 可以执行,但是 Panic 之后,相当于 return 后面的 hi2 就无法执行了。</p> <p><code>问题二:</code> <strong>看一段代码,分析答案</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> r <span class="token operator">:=</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> r <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Recovered in f"</span><span class="token punctuation">,</span> r<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"starting f"</span><span class="token punctuation">)</span> + <span class="token function">g</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"behind g"</span><span class="token punctuation">)</span> <span class="token comment">//会终止执行</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">g</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Defer in g"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Panicking!"</span><span class="token punctuation">)</span> + <span class="token function">panic</span><span class="token punctuation">(</span>fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%v"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Printing in g"</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span> <span class="token comment">//终止执行</span> +<span class="token punctuation">}</span> +</code></pre></div><p>答案是</p> <div class="language-js extra-class"><pre class="language-js"><code>starting f +panicking +Defer <span class="token keyword">in</span> g <span class="token number">2</span> +recoverd <span class="token keyword">in</span> f +</code></pre></div><p>解释一下,首先执行的是 f 函数的代码,然后开始执行 g,在 g 中遇到了 Panic,所以 panic 后面的 parinting in g 就无法执行了,所以执行了 defer in g +这个时候 f 中的 g(2) 后面的数据也无法执行了,因为整个 f 也陷入了恐慌,所以它只能 return 进入 defer 了,defer 中刚好有 recover,所以执行了 recover 信息后,就退出了函数。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/EvkMQCPwg-B0ffZonpwXodg</li> <li>https://mp.weixin.qq.com/s/D_CVrPzjP3O81EpFqLoynQ</li> <li>https://time.geekbang.org/column/article/391895</li> <li>极客时间《go 进阶训练营》</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/错误处理/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/5/2024, 2:50:37 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/44.5dc33e34.js" defer></script> + </body> +</html> diff --git "a/\345\237\272\347\241\200/\351\233\266\345\200\274/index.html" "b/\345\237\272\347\241\200/\351\233\266\345\200\274/index.html" new file mode 100644 index 000000000..3370c1052 --- /dev/null +++ "b/\345\237\272\347\241\200/\351\233\266\345\200\274/index.html" @@ -0,0 +1,117 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 语言零值 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/45.b2f02d30.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 语言零值</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/#零值可用" class="sidebar-link">零值可用</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/#零值不可用" class="sidebar-link">零值不可用</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%9F%BA%E7%A1%80/%E9%9B%B6%E5%80%BC/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-语言零值">go 语言零值</h1> <p>go 在声明时期就会为变量提供默认值。</p> <p>下面是所有的原生 go 类型的零值:</p> <ul><li>整数类型:0</li> <li>浮点数:0.0</li> <li>布尔类型:false</li> <li>字符串类型:“”</li> <li>指针,接口,切片,channel,map,function:nil</li></ul> <p>至于复合类型,比如数组,和结构体的声明过程,就是 <code>递归的,针对于它所有的子元素的初始化</code></p> <h2 id="零值可用">零值可用</h2> <p>go 奉行零值可用,最经典的案例是切片的 append 过程,即是你最初的切片变量只是声明,并未 make 赋予底层数组,那么 go 系统仍然处理的结果是可用,并非 Panic</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> +s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> +fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +</code></pre></div><p>下吗再看一个例子</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> b <span class="token operator">*</span>bytes<span class="token punctuation">.</span>Buffer + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p><code>fmt.Println(b)</code> 是调用的 <code>b.String()</code>,那么为什么这里输出的是 <code><nil></code> 不是 Panic 呢?</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>b <span class="token operator">*</span>Buffer<span class="token punctuation">)</span> <span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> b <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// Special case, useful in debugging.</span> + <span class="token keyword">return</span> <span class="token string">"<nil>"</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token function">string</span><span class="token punctuation">(</span>b<span class="token punctuation">.</span>buf<span class="token punctuation">[</span>b<span class="token punctuation">.</span>off<span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这就是答案,它在实现的 String 中实现了零值可用,<code>原因一:</code> <strong>nil 的对象是完全可以调用属于它身上的方法的</strong>,<code>原因二:</code> 这个方法内部实现的时候又是直接 return 一个 <code><nil></code> 避免了取 nil 索引值的情况。所以说基于这两点,它零值可用。</p> <p>再看一个经典的 buffer 例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"bytes"</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a bytes<span class="token punctuation">.</span>Buffer + a<span class="token punctuation">.</span><span class="token function">Write</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span><span class="token string">"12"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>为什么只是声明了 buffer 就可以直接往里面写值呢?</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 结构体</span> +<span class="token keyword">type</span> Buffer <span class="token keyword">struct</span> <span class="token punctuation">{</span> + buf <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span> <span class="token comment">// contents are the bytes buf[off : len(buf)]</span> + off <span class="token builtin">int</span> <span class="token comment">// read at &buf[off], write at &buf[len(buf)]</span> + lastRead readOp <span class="token comment">// last read operation, so that Unread* can work correctly.</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 取自 Write() 相关的代码 这段代码保证了即便是初始化的buf是nil也可以零值可用。</span> +<span class="token keyword">if</span> b<span class="token punctuation">.</span>buf <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token operator">&&</span> n <span class="token operator"><=</span> smallBufferSize <span class="token punctuation">{</span> + b<span class="token punctuation">.</span>buf <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">,</span> n<span class="token punctuation">,</span> smallBufferSize<span class="token punctuation">)</span> + <span class="token keyword">return</span> <span class="token number">0</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>另外,当切片是 nil 的时候,也是完全可以取它的 <code>[:]</code> 切片的,只要不超过 index 都没问题,这也是满足零值可用的一个小 tips</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> +s <span class="token operator">=</span> s<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span> <span class="token comment">// 或者 s = s[:0] or s = s[0:] or s= s[0:0]</span> +</code></pre></div><h2 id="零值不可用">零值不可用</h2> <ul><li>slice 零值赋值</li> <li>map 零值赋值</li> <li>互斥锁的值复制</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> s slice +s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">// 错误 ❌</span> + +<span class="token keyword">var</span> m <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span> +m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">12</span> <span class="token comment">// 错误 ❌</span> +</code></pre></div><p>再看互斥锁的案例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex +mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +</code></pre></div><p>这段代码是可以正常使用的</p> <p>但是,如果队 mu 进行值的复制就不能使用了</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"sync"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">foo</span><span class="token punctuation">(</span>mu<span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">foo</span><span class="token punctuation">(</span>mu sync<span class="token punctuation">.</span>Mutex<span class="token punctuation">)</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>这个问题的解释是这样的:互斥锁是带有状态的,就是说,当你复制的时候本来是 a 的状态,然后复制过去还是 a 的状态,但是这是一个新的对象了按道理应该是初始状态,所以就会出现错误,这也是传说中的重入锁 (go 不支持),因为 go 的互斥锁是带有状态的,所以这种复制的方法就会出现错误。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://github.com/golang/go/blob/037b209ae3e0453004a4d57e152aa522c56f79e4/src/bytes/buffer.go#L117</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/基础/零值/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/45.b2f02d30.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/cgo/index.html" "b/\345\267\245\347\250\213/cgo/index.html" new file mode 100644 index 000000000..351c3a49c --- /dev/null +++ "b/\345\267\245\347\250\213/cgo/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>cgo | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/47.6dd9b6a9.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>cgo</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/cgo/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="cgo">cgo</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/Xs5Ngi9444z6SyVVu0byUg</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/cgo/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">6/10/2022, 12:03:01 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/47.6dd9b6a9.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/copilot/index.html" "b/\345\267\245\347\250\213/copilot/index.html" new file mode 100644 index 000000000..3bb42ae36 --- /dev/null +++ "b/\345\267\245\347\250\213/copilot/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>Github Copilot | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/48.e525f69a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Github Copilot</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="github-copilot">Github Copilot</h1> <p>自动补全代码</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/copilot/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">6/29/2022, 3:31:28 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/48.e525f69a.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/goweb\347\274\226\347\250\213/index.html" "b/\345\267\245\347\250\213/goweb\347\274\226\347\250\213/index.html" new file mode 100644 index 000000000..d2f197578 --- /dev/null +++ "b/\345\267\245\347\250\213/goweb\347\274\226\347\250\213/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/49.565c30a8.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/goweb%E7%BC%96%E7%A8%8B/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="web-开发">web 开发</h1> <p>这里主要讲述 go 的 web 开发的用法。基本涉及到的包有 <code>net</code>,<code>net/http</code></p> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/NQSgECerdR2rM06ugp4qjQ</li> <li>https://mp.weixin.qq.com/s/jGrPM0UgqjZ10cXafoC0wQ</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/goweb编程/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/49.565c30a8.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\345\221\275\345\220\215\346\203\257\344\276\213/index.html" "b/\345\267\245\347\250\213/go\345\221\275\345\220\215\346\203\257\344\276\213/index.html" new file mode 100644 index 000000000..5b2ffeeb0 --- /dev/null +++ "b/\345\267\245\347\250\213/go\345\221\275\345\220\215\346\203\257\344\276\213/index.html" @@ -0,0 +1,121 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 命名惯例 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/50.249734db.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 命名惯例</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/#包" class="sidebar-link">包</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/#变量-类型-函数-方法" class="sidebar-link">变量,类型,函数,方法</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/#常量" class="sidebar-link">常量</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/#接口" class="sidebar-link">接口</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/#两种命名的对比" class="sidebar-link">两种命名的对比</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-命名惯例">go 命名惯例</h1> <p>go 语言的命名哲学就是<strong>尽可能的简单化</strong>。</p> <p>go 要求的简单,不仅仅是简单化,还要关注上下文的连贯性,go 喜欢一个简洁明了的命名+对字段的注释</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// userTypeInfo stores the information associated with a type the user has handed</span> +<span class="token comment">// to the package. It's computed once and stored in a map keyed by reflection</span> +<span class="token comment">// type.</span> +<span class="token keyword">type</span> userTypeInfo <span class="token keyword">struct</span> <span class="token punctuation">{</span> + user reflect<span class="token punctuation">.</span>Type <span class="token comment">// the type the user handed us</span> + base reflect<span class="token punctuation">.</span>Type <span class="token comment">// the base type after all indirections</span> + indir <span class="token builtin">int</span> <span class="token comment">// number of indirections to reach the base type</span> + externalEnc <span class="token builtin">int</span> <span class="token comment">// xGob, xBinary, or xText</span> + externalDec <span class="token builtin">int</span> <span class="token comment">// xGob, xBinary or xText</span> + encIndir <span class="token builtin">int8</span> <span class="token comment">// number of indirections to reach the receiver type; may be negative</span> + decIndir <span class="token builtin">int8</span> <span class="token comment">// number of indirections to reach the receiver type; may be negative</span> +<span class="token punctuation">}</span> +</code></pre></div><p>比如这段代码,对于字段和结构体都进行了注释,但是结构体内部的字段都相对简洁</p> <h2 id="包">包</h2> <p>包名称一般使用小写单词进行命名,例如说:<code>context</code>,<code>http</code>,<code>net</code>,无需考虑包名称的重复化,因为在 go 引入包的过程中,实际上是引入的路径,并且 go 的包在引入过程中还可以进行包的重命名</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span> + + <span class="token string">"example.com/hey/log"</span> + + blog <span class="token string">"example.net/bob/log"</span> +<span class="token punctuation">)</span> +</code></pre></div><p>包的路径名称最后一位尽量和包的名称保持一致性,不过不一致也是有不少情况的,比如说,现在有一个适应不同语言的 log,那么命名的时候就变成了 <code>github.com/shgopher/golog</code>,<code>github.com/shgopher/javalog</code>,但是他们实际上的包都叫 log,并不是 golog 和 javalog,那么使用的时候就需要对其中一个包进行重命名了。</p> <h2 id="变量-类型-函数-方法">变量,类型,函数,方法</h2> <p>因为 go 语言使用导出的变量时需要带上包的名称 (除了。省略包名称的方式,一般不提倡),所以命名的时候变量不需要再加上包的称呼,比如说 string 包的 Reader 就不需要写成 <code>string.StringReader</code>,写成 <code>string.Reader</code> 即可</p> <p>go 变量的命名使用驼峰的命名方式,go 的文件名称使用下划线连接的方式,比如说 <code>UpperName</code>,<code>lowName</code> 区别就是前者是大驼峰,导出的变量,后者是小驼峰,不可导出变量,缩略词如果首字母大写那么全部大写,比如 <code>HTTP</code>,不能写成 <code>Http</code></p> <p>go 代码里使用了大量单字母或者短字母的命名方式。</p> <p>for 循环中以及 if 条件语句中使用单字母</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">for</span> k<span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> users<span class="token punctuation">{</span> + +<span class="token punctuation">}</span> + +<span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">method1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>函数和方法的参数或者返回值,常见单字母或单个单词的方式出现。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">method1</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>方法调用的时候会绑定类型信息,可以尽量使用单个单词的命名方法</p> <p>函数和类型多以多单词驼峰的方法组合,比如 <code>func MakeFile(){}</code>,<code>type gobEncoderType struct {}</code></p> <p>在命名变量的时候,不要带上类型信息,比如说 <code>names</code> 比 <code>nameSlice</code> 要好,因为 go 强调命名和使用越近越好,没必要在字段上加上类型的名称。</p> <p>go 使用一致性来强调单字母或者单个单词的意义,意思就是说使用的单个字母在任何地方表示的意思都是一样的。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">for</span> k<span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> names<span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">for</span> i<span class="token punctuation">,</span>v <span class="token operator">:=</span> <span class="token keyword">range</span> users<span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>从 k v i 这三个字母就可以观察到,绝大多数情况下,在 go 语言中 kv 就是表示的 key 和 value,i 表示的就是 index,那么即便是单个字母也不会造成识别障碍</p> <p>另外 <code>t</code> <code>b</code> <code>n</code> 也很常见,他们通常表示 time 和 byte 以及数量</p> <h2 id="常量">常量</h2> <ul><li>go 语言的常量并不要求全大写,通常只有本身是全大写的常量才是全大写,比如 <code>PI</code></li> <li>常量不需要赋予类型,系统会根据根据使用时期左变量的类型,以及运算操作进行自动推断</li></ul> <p>一般常量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span><span class="token punctuation">(</span> + keepHostHeader <span class="token operator">=</span> <span class="token boolean">false</span> +<span class="token punctuation">)</span> +</code></pre></div><p>全大写常量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span> PI <span class="token operator">=</span> <span class="token number">3.14</span> + +<span class="token keyword">const</span> SIGABRT <span class="token operator">=</span> <span class="token function">Signal</span><span class="token punctuation">(</span><span class="token number">0x6</span><span class="token punctuation">)</span> +</code></pre></div><h2 id="接口">接口</h2> <p>拥有唯一方法的接口,或者内嵌多个拥有唯一方法的接口一律使用 <code>单词+er</code> 结尾,比如 <code>Reader</code> 或者 <code>WriteReadCloser</code></p> <p>go 语言推崇简单接口,和内嵌多个简单接口的接口,所以你会看到 go 语言标准库很多带有 er 结尾的接口</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Reader <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">Reade</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> Writer <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">Write</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">type</span> WriteReadeCloser <span class="token keyword">interface</span><span class="token punctuation">{</span> + Writer + Reader + Closer +<span class="token punctuation">}</span> +</code></pre></div><h2 id="两种命名的对比">两种命名的对比</h2> <p>简洁的并且考虑上下文一致性的代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">RuneCount</span><span class="token punctuation">(</span>b <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span> + count <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">for</span> i<span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span> <span class="token function">len</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> b<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator"><</span> RuneSelf <span class="token punctuation">{</span> + i<span class="token operator">++</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span><span class="token punctuation">{</span> + <span class="token boolean">_</span><span class="token punctuation">,</span>n <span class="token operator">:=</span> <span class="token function">DecodeRune</span><span class="token punctuation">(</span>b<span class="token punctuation">[</span>i<span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> + i<span class="token operator">+=</span>n + <span class="token punctuation">}</span> + count<span class="token operator">++</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> count +<span class="token punctuation">}</span> +</code></pre></div><p>见名知意的 java 式的代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">RuneCount</span><span class="token punctuation">(</span>buffer <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span><span class="token builtin">int</span><span class="token punctuation">{</span> + runeCount <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">for</span> index <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span>index <span class="token operator"><</span> <span class="token function">len</span><span class="token punctuation">(</span>buffer<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">{</span> + <span class="token keyword">if</span> buffer<span class="token punctuation">[</span>index<span class="token punctuation">]</span> <span class="token operator"><</span> runeSelf <span class="token punctuation">{</span> + index<span class="token operator">++</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + <span class="token boolean">_</span><span class="token punctuation">,</span> size <span class="token operator">:=</span> <span class="token function">DecodeRune</span><span class="token punctuation">(</span>buffer<span class="token punctuation">[</span>index<span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> + index <span class="token operator">+=</span> size + <span class="token punctuation">}</span> + runeCount<span class="token operator">++</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> runeCount +<span class="token punctuation">}</span> +</code></pre></div><h2 id="参考资料">参考资料</h2> <ul><li>图书:go 语言精进之路</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go命名惯例/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/50.249734db.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/encoding-hex.html" "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/encoding-hex.html" new file mode 100644 index 000000000..eee071603 --- /dev/null +++ "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/encoding-hex.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>encoding/hex | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/52.9dfffd13.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>encoding/hex</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/encoding-hex.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="encoding-hex">encoding/hex</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://pkg.go.dev/encoding/hex@go1.17.8#DecodeString</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go标准库/encoding-hex.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/52.9dfffd13.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/fmt.html" "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/fmt.html" new file mode 100644 index 000000000..bb36f1eca --- /dev/null +++ "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/fmt.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>fmt | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/53.c98436b4.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>fmt</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/fmt.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="fmt">fmt</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://studygolang.com/topics/2594/comment/7252</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go标准库/fmt.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/53.c98436b4.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/index.html" "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/index.html" new file mode 100644 index 000000000..6dffa8e2b --- /dev/null +++ "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/index.html" @@ -0,0 +1,158 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 标准库的简单介绍 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/51.9dd5ff4a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 标准库的简单介绍</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#archive" class="sidebar-link">archive</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#archive-tar" class="sidebar-link">archive/tar</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#archive-zip" class="sidebar-link">archive/zip</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#bufio" class="sidebar-link">bufio</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#builtin" class="sidebar-link">builtin</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#bytes" class="sidebar-link">bytes</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#cmp" class="sidebar-link">cmp</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#compress" class="sidebar-link">compress</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#compress-bzip2" class="sidebar-link">compress/bzip2</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#compress-flate" class="sidebar-link">compress/flate</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#compress-gzip" class="sidebar-link">compress/gzip</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#compress-lzw" class="sidebar-link">compress/lzw</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#compress-zlib" class="sidebar-link">compress/zlib</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#container" class="sidebar-link">container</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#container-heap" class="sidebar-link">container/heap</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#container-list" class="sidebar-link">container/list</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#container-ring" class="sidebar-link">container/ring</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#context" class="sidebar-link">context</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto" class="sidebar-link">crypto</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-aes" class="sidebar-link">crypto/aes</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-cipher" class="sidebar-link">crypto/cipher</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-des" class="sidebar-link">crypto/des</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-dsa" class="sidebar-link">crypto/dsa</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-ecdh" class="sidebar-link">crypto/ecdh</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-ecdsa" class="sidebar-link">crypto/ecdsa</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-ed25519" class="sidebar-link">crypto/ed25519</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-elliptic" class="sidebar-link">crypto/elliptic</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-hmac" class="sidebar-link">crypto/hmac</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-md5" class="sidebar-link">crypto/md5</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-rand" class="sidebar-link">crypto/rand</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-rc4" class="sidebar-link">crypto/rc4</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-rsa" class="sidebar-link">crypto/rsa</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-sha1" class="sidebar-link">crypto/sha1</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-sha256" class="sidebar-link">crypto/sha256</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-sha512" class="sidebar-link">crypto/sha512</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-subtle" class="sidebar-link">crypto/subtle</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-tls" class="sidebar-link">crypto/tls</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#crypto-x509" class="sidebar-link">crypto/x509</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#database" class="sidebar-link">database</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#database-sql" class="sidebar-link">database/sql</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#database-sql-driver" class="sidebar-link">database/sql/driver</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug" class="sidebar-link">debug</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-buildinfo" class="sidebar-link">debug/buildinfo</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-dwarf" class="sidebar-link">debug/dwarf</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-elf" class="sidebar-link">debug/elf</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-gosym" class="sidebar-link">debug/gosym</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-macho" class="sidebar-link">debug/macho</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-pe" class="sidebar-link">debug/pe</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#debug-plan9obj" class="sidebar-link">debug/plan9obj</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#embed" class="sidebar-link">embed</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding" class="sidebar-link">encoding</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-ascii85" class="sidebar-link">encoding/ascii85</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-asn1" class="sidebar-link">encoding/asn1</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-base32" class="sidebar-link">encoding/base32</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-base64" class="sidebar-link">encoding/base64</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-binary" class="sidebar-link">encoding/binary</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-csv" class="sidebar-link">encoding/csv</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-gob" class="sidebar-link">encoding/gob</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-hex" class="sidebar-link">encoding/hex</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-json" class="sidebar-link">encoding/json</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-pem" class="sidebar-link">encoding/pem</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#encoding-xml" class="sidebar-link">encoding/xml</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#errors" class="sidebar-link">errors</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#expvar" class="sidebar-link">expvar</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#flag" class="sidebar-link">flag</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#fmt" class="sidebar-link">fmt</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go" class="sidebar-link">go</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-ast" class="sidebar-link">go/ast</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-build" class="sidebar-link">go/build</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-constant" class="sidebar-link">go/constant</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-doc" class="sidebar-link">go/doc</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-format" class="sidebar-link">go/format</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-importer" class="sidebar-link">go/importer</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-parser" class="sidebar-link">go/parser</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-printer" class="sidebar-link">go/printer</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-scanner" class="sidebar-link">go/scanner</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-token" class="sidebar-link">go/token</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#go-types" class="sidebar-link">go/types</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#hash" class="sidebar-link">hash</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#hash-adler32" class="sidebar-link">hash/adler32</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#hash-crc32" class="sidebar-link">hash/crc32</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#hash-crc64" class="sidebar-link">hash/crc64</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#hash-fnv" class="sidebar-link">hash/fnv</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#hash-maphash" class="sidebar-link">hash/maphash</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#html" class="sidebar-link">html</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#html-template" class="sidebar-link">html/template</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#image" class="sidebar-link">image</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#image-color" class="sidebar-link">image/color</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#image-draw" class="sidebar-link">image/draw</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#image-gif" class="sidebar-link">image/gif</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#image-jpeg" class="sidebar-link">image/jpeg</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#png" class="sidebar-link">png</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#index" class="sidebar-link">index</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#index-suffixarray" class="sidebar-link">index/suffixarray</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#io" class="sidebar-link">io</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#io-fs" class="sidebar-link">io/fs</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#io-ioutil" class="sidebar-link">io/ioutil</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#log" class="sidebar-link">log</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#log-slog" class="sidebar-link">log/slog</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#log-syslog" class="sidebar-link">log/syslog</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#maps" class="sidebar-link">maps</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#math" class="sidebar-link">math</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#math-big" class="sidebar-link">math/big</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#math-bits" class="sidebar-link">math/bits</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#math-cmplx" class="sidebar-link">math/cmplx</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#math-rand" class="sidebar-link">math/rand</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#mime" class="sidebar-link">mime</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#mime-multipart" class="sidebar-link">mime/multipart</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#mime-quotedprintable" class="sidebar-link">mime/quotedprintable</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net" class="sidebar-link">net</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-http" class="sidebar-link">net/http</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-mail" class="sidebar-link">net/mail</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-netip" class="sidebar-link">net/netip</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-rpc" class="sidebar-link">net/rpc</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-smtp" class="sidebar-link">net/smtp</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-textproto" class="sidebar-link">net/textproto</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#net-url" class="sidebar-link">net/url</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#os" class="sidebar-link">os</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#os-exec" class="sidebar-link">os/exec</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#os-signal" class="sidebar-link">os/signal</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#os-user" class="sidebar-link">os/user</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#path" class="sidebar-link">path</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#path-filepath" class="sidebar-link">path/filepath</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#plugin" class="sidebar-link">plugin</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#reflect" class="sidebar-link">reflect</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#regexp" class="sidebar-link">regexp</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#regexp-syntax" class="sidebar-link">regexp/syntax</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime" class="sidebar-link">runtime</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-cgo" class="sidebar-link">runtime/cgo</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-coverage" class="sidebar-link">runtime/coverage</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-debug" class="sidebar-link">runtime/debug</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-metrics" class="sidebar-link">runtime/metrics</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-pprof" class="sidebar-link">runtime/pprof</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-race" class="sidebar-link">runtime/race</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#runtime-trace" class="sidebar-link">runtime/trace</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#slices" class="sidebar-link">slices</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#sort" class="sidebar-link">sort</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#strconv" class="sidebar-link">strconv</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#strings" class="sidebar-link">strings</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#sync" class="sidebar-link">sync</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#sync-atomic" class="sidebar-link">sync/atomic</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#syscall" class="sidebar-link">syscall</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#sync-js" class="sidebar-link">sync/js</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#testing" class="sidebar-link">testing</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#testing-fstest" class="sidebar-link">testing/fstest</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#testing-iotest" class="sidebar-link">testing/iotest</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#testing-quick" class="sidebar-link">testing/quick</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#testing-slogtest" class="sidebar-link">testing/slogtest</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#text" class="sidebar-link">text</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#text-scanner" class="sidebar-link">text/scanner</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#text-tabwriter" class="sidebar-link">text/tabwriter</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#text-template" class="sidebar-link">text/template</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#time" class="sidebar-link">time</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#time-tzdata" class="sidebar-link">time/tzdata</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#unicode" class="sidebar-link">unicode</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#unicode-utf16" class="sidebar-link">unicode/utf16</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#unicode-utf8" class="sidebar-link">unicode/utf8</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/#unsafe" class="sidebar-link">unsafe</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-标准库的简单介绍">go 标准库的简单介绍</h1> <p>https://pkg.go.dev/std</p> <h2 id="archive">archive</h2> <p>https://pkg.go.dev/archive</p> <p>目前不存在 archive 包本身,存在其子包,这个包,包含的内容是对于档案文件的处理,比如 tar,zip 这种文档文件。</p> <h3 id="archive-tar">archive/tar</h3> <p>https://pkg.go.dev/archive/tar</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"archive/tar"</span> +</code></pre></div><p><code>archive/tar</code> 包,实现了对 tar 文件的处理</p> <ul><li>tar 文件头的设置</li> <li>tar 文件的读写</li></ul> <h3 id="archive-zip">archive/zip</h3> <p>https://pkg.go.dev/archive/zip</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"archive/zip"</span> +</code></pre></div><p><code>archive/zip</code> 包,实现了对 zip 文件的处理</p> <ul><li>zip 文件头的设置</li> <li>zip 文件的读写</li></ul> <h2 id="bufio">bufio</h2> <p>https://pkg.go.dev/bufio</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"bufio"</span> +</code></pre></div><p><code>bufio</code> 包,提供了有缓冲的 i/o,比 io 包封装程度更高。使用缓冲区来一次读取多个字节,从而减少系统调用的次数。</p> <ul><li>提供了基本的读写功能</li> <li>提供了逐行读取的功能</li></ul> <h2 id="builtin">builtin</h2> <p>https://pkg.go.dev/builtin</p> <p>注意,此包无法使用 import 的方式引入,因为它只是内部包和内部类型的一个存放位置而已</p> <p>比如有 append() clear() max() min() int float64 等等</p> <h2 id="bytes">bytes</h2> <p>https://pkg.go.dev/bytes</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"bytes"</span> +</code></pre></div><p>bytes 包,包含了很多处理 bytes 类型的操作。</p> <p>跟字符串的基本操作类型</p> <h2 id="cmp">cmp</h2> <p>https://pkg.go.dev/cmp</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"cmp"</span> +</code></pre></div><p>cmp 包提供了有关比较的相关内容。</p> <ul><li>cmp.Ordered 表示可比较的类型约束</li> <li>提供了比较函数</li></ul> <h2 id="compress">compress</h2> <p>https://pkg.go.dev/compress</p> <p>不直接提供 compress 包,提供了众多子包,所有的内容都是关于压缩算法</p> <h3 id="compress-bzip2">compress/bzip2</h3> <p>https://pkg.go.dev/compress/bzip2</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"compress/bzip2"</span> +</code></pre></div><p>提供了 bzip2 的解压功能,然而并没有提供压缩的功能</p> <h3 id="compress-flate">compress/flate</h3> <p>https://pkg.go.dev/compress/flate</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"compress/flate"</span> +</code></pre></div><p>flate 实现了 RFC1951 中描述的 DEFLATE 压缩数据格式。</p> <h3 id="compress-gzip">compress/gzip</h3> <p>https://pkg.go.dev/compress/gzip</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"compress/gzip"</span> +</code></pre></div><p>gzip 实现了对 gzip 格式压缩文件的解压 (读取) 和压缩 (写入)</p> <h3 id="compress-lzw">compress/lzw</h3> <p>https://pkg.go.dev/compress/lzw</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"compress/lzw"</span> +</code></pre></div><p>lzw 实现了 lzw 文件 (Lempel-Ziv-Welch) 的解压缩操作。</p> <h3 id="compress-zlib">compress/zlib</h3> <p>https://pkg.go.dev/compress/zlib</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"compress/zlib"</span> +</code></pre></div><p>zlib 实现了对 zlib 格式文件的解压和压缩操作。</p> <h2 id="container">container</h2> <p>https://pkg.go.dev/container</p> <p>container 没有提供本包,提供了众多子包,这个目录下的内容都是关于容器的,这也是 go 提供的内置容器</p> <h3 id="container-heap">container/heap</h3> <p>https://pkg.go.dev/container/heap</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"container/heap"</span> +</code></pre></div><p>go 内置的堆,值得注意的是,go 语言仅提供了接口以及接口的相关函数,并没有具体的实现,使用时还需要自行实现接口。</p> <h3 id="container-list">container/list</h3> <p>https://pkg.go.dev/container/list</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> "container<span class="token operator">/</span>list +</code></pre></div><p>go 内置的双向链表,这里不是接口了,是已经实现好了的双向链表</p> <h3 id="container-ring">container/ring</h3> <p>https://pkg.go.dev/container/ring</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"container/ring"</span> +</code></pre></div><p>go 内置的循环链表,非接口,已经实现好了</p> <h2 id="context"><a href="../%E5%B9%B6%E5%8F%91/context">context</a></h2> <p>https://pkg.go.dev/context</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"context"</span> +</code></pre></div><p>context 提供了在 “多线程” 的场景下的线程控制功能,简单的说就是 context 这个上下文可以统一取消所有的上下文环境中的 goroutine</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// cal的调用,以及计时器的到达均可调用 ctx.Done() 的发生。</span> + ctx<span class="token punctuation">,</span> cal <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithTimeout</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token function">cal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ctx<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">3</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="crypto">crypto</h2> <p>https://pkg.go.dev/crypto</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto"</span> +</code></pre></div><p>crypto 包,包含了很多加密算法</p> <h3 id="crypto-aes">crypto/aes</h3> <p>https://pkg.go.dev/crypto/aes</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/aes"</span> +</code></pre></div><p>提供了 aes 加密算法的加密过程。此算法为对称加密算法</p> <ul><li>创建一个密钥</li></ul> <h3 id="crypto-cipher">crypto/cipher</h3> <p>https://pkg.go.dev/crypto/cipher</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/cipher"</span> +</code></pre></div><h3 id="crypto-des">crypto/des</h3> <p>https://pkg.go.dev/crypto/des</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/des"</span> +</code></pre></div><h3 id="crypto-dsa">crypto/dsa</h3> <p>https://pkg.go.dev/crypto/dsa</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/dsa"</span> +</code></pre></div><h3 id="crypto-ecdh">crypto/ecdh</h3> <p>https://pkg.go.dev/crypto/ecdh</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/ecdh"</span> +</code></pre></div><h3 id="crypto-ecdsa">crypto/ecdsa</h3> <p>https://pkg.go.dev/crypto/ecdsa</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/ecdsa"</span> +</code></pre></div><h3 id="crypto-ed25519">crypto/ed25519</h3> <p>https://pkg.go.dev/crypto/ed25519</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/ed25519"</span> +</code></pre></div><h3 id="crypto-elliptic">crypto/elliptic</h3> <p>https://pkg.go.dev/crypto/elliptic</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/elliptic"</span> +</code></pre></div><h3 id="crypto-hmac">crypto/hmac</h3> <p>https://pkg.go.dev/crypto/hmac</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/hmac"</span> +</code></pre></div><h3 id="crypto-md5">crypto/md5</h3> <p>https://pkg.go.dev/crypto/md5</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/md5"</span> +</code></pre></div><h3 id="crypto-rand">crypto/rand</h3> <p>https://pkg.go.dev/crypto/rand</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/rand"</span> +</code></pre></div><h3 id="crypto-rc4">crypto/rc4</h3> <p>https://pkg.go.dev/crypto/rc4</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/rc4"</span> +</code></pre></div><h3 id="crypto-rsa">crypto/rsa</h3> <p>https://pkg.go.dev/crypto/rsa</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/rsa"</span> +</code></pre></div><h3 id="crypto-sha1">crypto/sha1</h3> <p>https://pkg.go.dev/crypto/sha1</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/sha1"</span> +</code></pre></div><h3 id="crypto-sha256">crypto/sha256</h3> <p>https://pkg.go.dev/crypto/sha256</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/sha256"</span> +</code></pre></div><h3 id="crypto-sha512">crypto/sha512</h3> <p>https://pkg.go.dev/crypto/sha512</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/sha512"</span> +</code></pre></div><h3 id="crypto-subtle">crypto/subtle</h3> <p>https://pkg.go.dev/crypto/subtle</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/subtle"</span> +</code></pre></div><h3 id="crypto-tls">crypto/tls</h3> <p>https://pkg.go.dev/crypto/tls</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/tls"</span> +</code></pre></div><h3 id="crypto-x509">crypto/x509</h3> <p>https://pkg.go.dev/crypto/x509</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/x509"</span> +</code></pre></div><h4 id="crypto-x509-pkix">crypto/x509/pkix</h4> <p>https://pkg.go.dev/crypto/x509/pkix</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"crypto/x509/pkix"</span> +</code></pre></div><h2 id="database">database</h2> <p>https://pkg.go.dev/database +此包不可直接使用,它包含了子包,这个子包是处理 sql 的统一接口,并不提供实际的实现</p> <h3 id="database-sql">database/sql</h3> <p>https://pkg.go.dev/database/sql</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token boolean">_</span> <span class="token string">"database/sql"</span> +</code></pre></div><p>当我们使用 MySQL,Redis 等数据库的时候,通常要使用上述的方式引入这个包,此包提供了 SQL 操作的接口。</p> <p>使用此包必须跟第三方的数据库驱动结合,比如下面这种操作:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span><span class="token punctuation">(</span> +<span class="token boolean">_</span> <span class="token string">"database/sql"</span> + <span class="token string">"xx/mysql"</span> +<span class="token punctuation">)</span> +</code></pre></div><h3 id="database-sql-driver">database/sql/driver</h3> <p>https://pkg.go.dev/database/sql/driver</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"database/sql/driver"</span> +</code></pre></div><p>driver 包,包含了数据库 driver 的接口,要想实现某个数据库的驱动 (driver) 就必须引入此包,实现此包定义接口的具体内容。</p> <p>在被用户使用的时候,引入第三方数据库驱动,加上引入 database/sql 这个 SQL 操作包,就可以实现正常的 SQL 操作。</p> <h2 id="debug">debug</h2> <p>https://pkg.go.dev/debug</p> <p>不提供 debug 包本身,debug 包含了众多子包,都是跟调试相关。</p> <h3 id="debug-buildinfo">debug/buildinfo</h3> <p>https://pkg.go.dev/debug/buildinfo +不直接使用此包,此包提供二进制的功能,由 runtime/debug 来调用。</p> <h3 id="debug-dwarf">debug/dwarf</h3> <p>https://pkg.go.dev/debug/dwarf</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"debug/dwarf"</span> +</code></pre></div><p>用于解析 DWARF 调试信息,DWARF 调试信息包含了程序的源代码、变量、函数、类型等相关信息,可以帮助调试器进行源代码级别的调试。</p> <h3 id="debug-elf">debug/elf</h3> <p>https://pkg.go.dev/debug/elf</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"debug/elf"</span> +</code></pre></div><p>用于解析 ELF 可执行文件格式,</p> <h3 id="debug-gosym">debug/gosym</h3> <p>https://pkg.go.dev/debug/gosym</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"debug/gosym"</span> +</code></pre></div><p>debug/gosym 用于解析 Go 语言程序的符号表信息。</p> <h3 id="debug-macho">debug/macho</h3> <p>https://pkg.go.dev/debug/macho</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"debug/macho"</span> +</code></pre></div><p>debug/macho 用于解析 Mach-O 格式的可执行文件</p> <h3 id="debug-pe">debug/pe</h3> <p>https://pkg.go.dev/debug/pe</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"debug/pe"</span> +</code></pre></div><p>debug/pe 用于解析 PE 格式的可执行文件</p> <h3 id="debug-plan9obj">debug/plan9obj</h3> <p>https://pkg.go.dev/debug/plan9obj</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"debug/plan9obj"</span> +</code></pre></div><p>debug/plan9obj 用于解析 Plan 9 object 文件格式。</p> <h2 id="embed">embed</h2> <p>https://pkg.go.dev/embed</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token boolean">_</span> <span class="token string">"embed"</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//go:embed hello.text</span> +</code></pre></div><p>mbed 是 Go 语言自 1.16 版本引入的一个标准库,用于将静态文件嵌入到 Go 代码中。</p> <p>通过 embed 包,我们可以将静态文件 (如文本文件、JSON 文件、HTML 文件、图像文件等) 直接嵌入到 Go 代码中,而无需将文件作为独立的资源文件放在磁盘上。这样做的好处是,可以将所有的资源文件打包到可执行文件中,方便分发和部署。</p> <p>将一个文件嵌入到一个 string 中</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token boolean">_</span> <span class="token string">"embed"</span> + +<span class="token comment">// 这里的注释开头没有空格,这是 go 的自有命令注释;//go:xx </span> +<span class="token comment">//</span> +<span class="token comment">//go:embed hello.txt</span> +<span class="token keyword">var</span> s <span class="token builtin">string</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">print</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>将一个文件嵌入到文件系统中</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"embed"</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token comment">//go:embed hello.txt</span> +<span class="token keyword">var</span> helloFile embed<span class="token punctuation">.</span>FS + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + content<span class="token punctuation">,</span> err <span class="token operator">:=</span> helloFile<span class="token punctuation">.</span><span class="token function">ReadFile</span><span class="token punctuation">(</span><span class="token string">"hello.txt"</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"无法读取文件:"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">string</span><span class="token punctuation">(</span>content<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="encoding">encoding</h2> <p>https://pkg.go.dev/encoding +使用时,不直接使用 encoding,除非你想亲自实现某个编码的加解码</p> <p>encoding 是 Go 语言标准库中的一个包,用于处理数据的编码和解码。</p> <p>encoding 包提供了许多子包,每个子包都专门用于处理特定的数据编码格式</p> <ul><li>encoding/json:用于处理 JSON 数据的编码和解码。</li> <li>encoding/xml:用于处理 XML 数据的编码和解码。</li> <li>encoding/csv:用于处理 CSV (逗号分隔值) 数据的编码和解码。</li> <li>encoding/base64:用于进行 base64 编码和解码。</li> <li>encoding/hex:用于进行十六进制编码和解码。</li> <li>encoding/gob:用于进行 Go 对象的编码和解码。</li></ul> <h3 id="encoding-ascii85">encoding/ascii85</h3> <p>https://pkg.go.dev/encoding/ascii85</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/ascii85"</span> +</code></pre></div><p>encoding/ascii85 用于进行 ASCII85 编码和解码</p> <h3 id="encoding-asn1">encoding/asn1</h3> <p>https://pkg.go.dev/encoding/asn1</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/asn1"</span> +</code></pre></div><p>encoding/asn1 用于进行 ASN.1 (Abstract Syntax Notation One) 编码和解码。</p> <h3 id="encoding-base32">encoding/base32</h3> <p>https://pkg.go.dev/encoding/base32</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/base32"</span> +</code></pre></div><h3 id="encoding-base64">encoding/base64</h3> <p>https://pkg.go.dev/encoding/base64</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/base64"</span> +</code></pre></div><p>encoding/base32 用于进行 Base32 编码和解码</p> <h3 id="encoding-binary">encoding/binary</h3> <p>https://pkg.go.dev/encoding/binary</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/binary"</span> +</code></pre></div><p>encoding/base64 用于进行 Base64 编码和解码。</p> <h3 id="encoding-csv">encoding/csv</h3> <p>https://pkg.go.dev/encoding/csv</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/csv"</span> +</code></pre></div><p>encoding/csv 用于处理 CSV (逗号分隔值) 格式的数据。</p> <h3 id="encoding-gob">encoding/gob</h3> <p>https://pkg.go.dev/encoding/gob</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/gob"</span> +</code></pre></div><p>encoding/gob 用于将 Go 的值编码为二进制格式,并进行序列化和反序列化。</p> <h3 id="encoding-hex">encoding/hex</h3> <p>https://pkg.go.dev/encoding/hex</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/hex"</span> +</code></pre></div><p>十六进制编码将二进制数据编码为十六进制字符串,每个字节对应两个十六进制字符。十六进制编码通常用于将二进制数据转换为可打印的 ASCII 字符串,例如在 URL 参数中传递二进制数据或在文本文件中嵌入二进制数据。</p> <p>encoding/hex 包提供了一组函数和类型,用于进行十六进制编码和解码。主要有两个函数:EncodeToString 和 DecodeString。</p> <h3 id="encoding-json">encoding/json</h3> <p>https://pkg.go.dev/encoding/json</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/json"</span> +</code></pre></div><p>encoding/json 用于对 JSON (JavaScript Object Notation) 格式的数据进行编码和解码操作。</p> <p>JSON 是一种常用的数据交换格式,用于在不同平台和编程语言之间传输和存储数据。JSON 数据由键值对组成,可以表示复杂的数据结构和层次关系。</p> <h3 id="encoding-pem">encoding/pem</h3> <p>https://pkg.go.dev/encoding/pem</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/pem"</span> +</code></pre></div><p>encoding/pem 用于对 PEM (Privacy-Enhanced Mail) 格式的数据进行编码和解码操作。</p> <p>PEM 是一种常用的文本格式,用于在非文本环境中传输和存储密钥、证书等数据。PEM 格式使用 ASCII 字符表示二进制数据,通常以 “-----BEGIN…” 和 “-----END…” 标记来标识不同类型的数据。</p> <h3 id="encoding-xml">encoding/xml</h3> <p>https://pkg.go.dev/encoding/xml</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token string">"encoding/xml"</span> +</code></pre></div><p>encoding/xml 用于对 XML (eXtensible Markup Language) 格式的数据进行编码和解码操作。</p> <p>XML 是一种常用的文本格式,用于存储和传输结构化的数据。XML 数据由标签、属性和文本内容组成,可以表示复杂的数据结构和层次关系。</p> <h2 id="errors">errors</h2> <h2 id="expvar">expvar</h2> <h2 id="flag">flag</h2> <h2 id="fmt">fmt</h2> <h2 id="go">go</h2> <h3 id="go-ast">go/ast</h3> <h3 id="go-build">go/build</h3> <h4 id="go-build-constraint">go/build/constraint</h4> <h3 id="go-constant">go/constant</h3> <h3 id="go-doc">go/doc</h3> <h4 id="go-doc-comment">go/doc/comment</h4> <h3 id="go-format">go/format</h3> <h3 id="go-importer">go/importer</h3> <h3 id="go-parser">go/parser</h3> <h3 id="go-printer">go/printer</h3> <h3 id="go-scanner">go/scanner</h3> <h3 id="go-token">go/token</h3> <h3 id="go-types">go/types</h3> <h2 id="hash">hash</h2> <h3 id="hash-adler32">hash/adler32</h3> <h3 id="hash-crc32">hash/crc32</h3> <h3 id="hash-crc64">hash/crc64</h3> <h3 id="hash-fnv">hash/fnv</h3> <h3 id="hash-maphash">hash/maphash</h3> <h2 id="html">html</h2> <h3 id="html-template">html/template</h3> <h2 id="image">image</h2> <h3 id="image-color">image/color</h3> <h4 id="image-color-palette">image/color/palette</h4> <h3 id="image-draw">image/draw</h3> <h3 id="image-gif">image/gif</h3> <h3 id="image-jpeg">image/jpeg</h3> <h3 id="png">png</h3> <h2 id="index">index</h2> <h3 id="index-suffixarray">index/suffixarray</h3> <h2 id="io">io</h2> <h3 id="io-fs">io/fs</h3> <h3 id="io-ioutil">io/ioutil</h3> <h2 id="log">log</h2> <h3 id="log-slog">log/slog</h3> <h3 id="log-syslog">log/syslog</h3> <h2 id="maps">maps</h2> <h2 id="math">math</h2> <h3 id="math-big">math/big</h3> <h3 id="math-bits">math/bits</h3> <h3 id="math-cmplx">math/cmplx</h3> <h3 id="math-rand">math/rand</h3> <h2 id="mime">mime</h2> <h3 id="mime-multipart">mime/multipart</h3> <h3 id="mime-quotedprintable">mime/quotedprintable</h3> <h2 id="net">net</h2> <h3 id="net-http">net/http</h3> <h4 id="net-http-cgi">net/http/cgi</h4> <h4 id="net-http-cookiejar">net/http/cookiejar</h4> <h4 id="net-http-fcgi">net/http/fcgi</h4> <h4 id="net-http-httptest">net/http/httptest</h4> <h4 id="net-http-httptrace">net/http/httptrace</h4> <h4 id="net-http-httputil">net/http/httputil</h4> <h4 id="net-http-pprof">net/http/pprof</h4> <h3 id="net-mail">net/mail</h3> <h3 id="net-netip">net/netip</h3> <h3 id="net-rpc">net/rpc</h3> <h4 id="net-rpc-jsonrpc">net/rpc/jsonrpc</h4> <h3 id="net-smtp">net/smtp</h3> <h3 id="net-textproto">net/textproto</h3> <h3 id="net-url">net/url</h3> <h2 id="os">os</h2> <h3 id="os-exec">os/exec</h3> <h3 id="os-signal">os/signal</h3> <h3 id="os-user">os/user</h3> <h2 id="path">path</h2> <h3 id="path-filepath">path/filepath</h3> <h2 id="plugin">plugin</h2> <h2 id="reflect">reflect</h2> <h2 id="regexp">regexp</h2> <h3 id="regexp-syntax">regexp/syntax</h3> <h2 id="runtime">runtime</h2> <h3 id="runtime-cgo">runtime/cgo</h3> <h3 id="runtime-coverage">runtime/coverage</h3> <h3 id="runtime-debug">runtime/debug</h3> <h3 id="runtime-metrics">runtime/metrics</h3> <h3 id="runtime-pprof">runtime/pprof</h3> <h3 id="runtime-race">runtime/race</h3> <h3 id="runtime-trace">runtime/trace</h3> <h2 id="slices">slices</h2> <h2 id="sort">sort</h2> <h2 id="strconv">strconv</h2> <h2 id="strings">strings</h2> <h2 id="sync">sync</h2> <h3 id="sync-atomic">sync/atomic</h3> <h2 id="syscall">syscall</h2> <h3 id="sync-js">sync/js</h3> <h2 id="testing">testing</h2> <h3 id="testing-fstest">testing/fstest</h3> <h3 id="testing-iotest">testing/iotest</h3> <h3 id="testing-quick">testing/quick</h3> <h3 id="testing-slogtest">testing/slogtest</h3> <h2 id="text">text</h2> <h3 id="text-scanner">text/scanner</h3> <h3 id="text-tabwriter">text/tabwriter</h3> <h3 id="text-template">text/template</h3> <h4 id="template-parse">template/parse</h4> <h2 id="time">time</h2> <h3 id="time-tzdata">time/tzdata</h3> <h2 id="unicode">unicode</h2> <h3 id="unicode-utf16">unicode/utf16</h3> <h3 id="unicode-utf8">unicode/utf8</h3> <h2 id="unsafe">unsafe</h2></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go标准库/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/51.9dd5ff4a.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/sync.html" "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/sync.html" new file mode 100644 index 000000000..d58392125 --- /dev/null +++ "b/\345\267\245\347\250\213/go\346\240\207\345\207\206\345\272\223/sync.html" @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>sync | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/54.ee26f0f5.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>sync</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html#sync-map" class="sidebar-link">sync.Map</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html#sync-map-的底层数据" class="sidebar-link">sync.Map 的底层数据</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E6%A0%87%E5%87%86%E5%BA%93/sync.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="sync">sync</h1> <h2 id="sync-map">sync.Map</h2> <h3 id="sync-map-的底层数据">sync.Map 的底层数据</h3> <p>sync.Map 适合在读多写少的场景下使用,sync.Map 的核心思想是读写分离,以及用空间换时间。</p> <p>有两个数据结构:</p> <p><code>dirty</code> 数据结构</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Map <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token comment">// 互斥锁</span> + mu Mutex + <span class="token comment">// 原子操作</span> + read atomic<span class="token punctuation">.</span>Value + <span class="token comment">// dirty数据 </span> + dirty <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token operator">*</span>entry + <span class="token comment">// 标记tag 表示数据每次从diry中往read中迁移一个就+1</span> + misses <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><p><code>read</code> 数据结构</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> readOnly <span class="token keyword">struct</span> <span class="token punctuation">{</span> + m <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token operator">*</span>entry + <span class="token comment">// 标记:false 证明数据不只是read中有,dirty也有</span> + amended <span class="token builtin">bool</span> +</code></pre></div><p>读数据是优先从 read 中读 (注意,read 是只读的数据结构,所以不加锁),如果 read 不包含这个数据,会从 dirty 中读取 (注意,从 dirty 查找的时候会加锁),并 misses+1,直到 misses 大于 dirty,开始迁移数据,数据一次性从 dirty 传到 read 中。</p> <p>因为 read 没有锁,所以才说,sync.Map 读的时候效率高。</p> <p>当新增的时候,从 read 和 dirty 中查找是否用数据,在 read 有数据且没有被标记为清除就无锁覆盖原来的值。这个时候开始加锁了,如果在 read 中虽然有数据,但是被标记为清除了,并且 dirty 没有数据,就加入到 diry 中,如果这个时候 read 有数据,虽然被被标记为删除了,dirty 也有数据,那么直接原子更新数据即可。如果数据不在 read,在 dirty 中,直接在 dirty 中更新即可,如果数据不在 read 中也不再 dirty 中,如果这个时候 read.amended 是 false (意思就是 dirty 空了),<strong>那么就必须将数据一点一点从 read 中复制到 dirty 中</strong>,如果是 true 就不用复制了,在完成这个工序后,再把数据放置在 dirty 中。</p> <p>删除的时候,就先从 read 中查找,有了就原子性质的将其标记为 nil,并不是真的删,没有就加锁从 dirty 中找,有了就删。这个时候是真删,如果都没有就返回。</p> <p>在写多读少的时候,涉及到 read 中无数据就会频繁的加锁去 dirty 中查找、read 和 dirty 交换等开销,比常规的 map 加锁性能更差。因为普通的只是加锁,sync.Map 不仅仅是加锁,还得复制数据,这花销就更大了。</p> <p>总结:<strong>高并发,读多写少可以使用 sync.Map,如果读少写多,不要使用 sync.Map,比常规锁+map 更慢</strong></p> <h2 id="参考资料">参考资料</h2> <ul><li>https://zhuanlan.zhihu.com/p/353440086</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go标准库/sync.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/54.ee26f0f5.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/index.html" new file mode 100644 index 000000000..f7a3b772d --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/55.7b5dc58d.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#创建模式" class="sidebar-link">创建模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#结构模式" class="sidebar-link">结构模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#行为模式" class="sidebar-link">行为模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#同步模式" class="sidebar-link">同步模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#并发模式" class="sidebar-link">并发模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#消息传递模式" class="sidebar-link">消息传递模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#稳定性模式" class="sidebar-link">稳定性模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#分析模式" class="sidebar-link">分析模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#函数式编程模式" class="sidebar-link">函数式编程模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-编程范式">go 编程范式</h1> <h2 id="创建模式">创建模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/创建者/">创建者</a></li> <li><a href="/GOFamily/工程/go编程范式/工厂方法/">工厂方法</a></li> <li><a href="/GOFamily/工程/go编程范式/对象池/">对象池</a></li> <li><a href="/GOFamily/工程/go编程范式/单例/">单例</a></li> <li><a href="/GOFamily/工程/go编程范式/原型/">原型</a></li></ul> <h2 id="结构模式">结构模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/装饰器/">装饰器</a></li> <li><a href="/GOFamily/工程/go编程范式/代理/">代理</a></li></ul> <h2 id="行为模式">行为模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/观察者/">观察者</a></li> <li><a href="/GOFamily/工程/go编程范式/策略/">策略</a></li></ul> <h2 id="同步模式">同步模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/信号量/">信号量</a></li></ul> <h2 id="并发模式">并发模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/有界并行/">有界并行</a></li> <li><a href="/GOFamily/工程/go编程范式/生成器/">生成器</a></li> <li><a href="/GOFamily/工程/go编程范式/并行/">并行</a></li></ul> <h2 id="消息传递模式">消息传递模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/扇入/">扇入</a></li> <li><a href="/GOFamily/工程/go编程范式/扇出/">扇出</a></li> <li><a href="/GOFamily/工程/go编程范式/发布者订阅者/">发布者订阅者</a></li></ul> <h2 id="稳定性模式">稳定性模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/断路器/">断路器</a></li></ul> <h2 id="分析模式">分析模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/定时函数/">定时函数</a></li></ul> <h2 id="函数式编程模式">函数式编程模式</h2> <ul><li><a href="/GOFamily/工程/go编程范式/功能选项/">功能选项</a></li> <li><a href="/GOFamily/工程/go编程范式/k8s_visitor/">k8s visitor</a></li> <li><a href="/GOFamily/工程/go编程范式/pipeline/">pipeline</a></li></ul> <h2 id="参考资料">参考资料</h2> <ul><li>https://github.com/shgopher/go-patterns</li> <li>https://time.geekbang.org/column/article/386238</li> <li>https://mp.weixin.qq.com/s/Sv-SXDYxea_K_TtiI_CjTw</li> <li>https://mp.weixin.qq.com/s/KRgNwJt1C7q2ckeqCu9pCQ</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/26/2023, 3:56:49 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/55.7b5dc58d.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/k8s_visitor/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/k8s_visitor/index.html" new file mode 100644 index 000000000..4063c232c --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/k8s_visitor/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>k8s visitor | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/56.e3024720.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>k8s visitor</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="k8s-visitor">k8s visitor</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/k8s_visitor/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/9/2023, 6:17:22 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/56.e3024720.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/pipeline/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/pipeline/index.html" new file mode 100644 index 000000000..29ad92cd8 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/pipeline/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>pipeline | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/57.ba1b4c58.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>pipeline</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="pipeline">pipeline</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/pipeline/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/9/2023, 6:17:22 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/57.ba1b4c58.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\273\243\347\220\206/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\273\243\347\220\206/index.html" new file mode 100644 index 000000000..dd151164c --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\273\243\347\220\206/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/58.d6c32d73.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/代理/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/58.d6c32d73.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\277\241\345\217\267\351\207\217/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\277\241\345\217\267\351\207\217/index.html" new file mode 100644 index 000000000..457d82558 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\344\277\241\345\217\267\351\207\217/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/59.a733d97b.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/信号量/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/59.a733d97b.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\210\233\345\273\272\350\200\205/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\210\233\345\273\272\350\200\205/index.html" new file mode 100644 index 000000000..2bd47e790 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\210\233\345\273\272\350\200\205/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>创建者模式 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/60.f162e276.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>创建者模式</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="创建者模式">创建者模式</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/创建者/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/9/2023, 11:27:50 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/60.f162e276.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\212\237\350\203\275\351\200\211\351\241\271/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\212\237\350\203\275\351\200\211\351\241\271/index.html" new file mode 100644 index 000000000..f21259f51 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\212\237\350\203\275\351\200\211\351\241\271/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/61.155a3987.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/功能选项/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/61.155a3987.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\215\225\344\276\213/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\215\225\344\276\213/index.html" new file mode 100644 index 000000000..9e69b2a99 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\215\225\344\276\213/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/62.ad6d715b.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/单例/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/62.ad6d715b.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\216\237\345\236\213/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\216\237\345\236\213/index.html" new file mode 100644 index 000000000..a7cc81f53 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\216\237\345\236\213/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/63.088bb315.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="原型模式">原型模式</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/原型/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/9/2023, 11:27:50 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/63.088bb315.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\217\221\345\270\203\350\200\205\350\256\242\351\230\205\350\200\205/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\217\221\345\270\203\350\200\205\350\256\242\351\230\205\350\200\205/index.html" new file mode 100644 index 000000000..33f25423e --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\217\221\345\270\203\350\200\205\350\256\242\351\230\205\350\200\205/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/64.58e4a79c.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/发布者订阅者/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/64.58e4a79c.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\256\232\346\227\266\345\207\275\346\225\260/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\256\232\346\227\266\345\207\275\346\225\260/index.html" new file mode 100644 index 000000000..babf7acf4 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\256\232\346\227\266\345\207\275\346\225\260/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/65.9e82002d.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/定时函数/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/65.9e82002d.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\257\271\350\261\241\346\261\240/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\257\271\350\261\241\346\261\240/index.html" new file mode 100644 index 000000000..d40e9d553 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\257\271\350\261\241\346\261\240/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/66.949483d3.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/对象池/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/66.949483d3.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\267\245\345\216\202\346\226\271\346\263\225/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\267\245\345\216\202\346\226\271\346\263\225/index.html" new file mode 100644 index 000000000..0ff535efb --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\267\245\345\216\202\346\226\271\346\263\225/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/67.613f77e3.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/工厂方法/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/67.613f77e3.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\271\266\350\241\214/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\271\266\350\241\214/index.html" new file mode 100644 index 000000000..253b2cb87 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\345\271\266\350\241\214/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/68.f73d44cf.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/并行/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/68.f73d44cf.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\205\245/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\205\245/index.html" new file mode 100644 index 000000000..cf375f39b --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\205\245/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/69.a717baf8.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/扇入/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/69.a717baf8.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\207\272/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\207\272/index.html" new file mode 100644 index 000000000..29e8fe011 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\211\207\345\207\272/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/70.b3476fa3.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/扇出/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/70.b3476fa3.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\226\255\350\267\257\345\231\250/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\226\255\350\267\257\345\231\250/index.html" new file mode 100644 index 000000000..54d2502bb --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\226\255\350\267\257\345\231\250/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/71.57746954.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/断路器/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/71.57746954.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\234\211\347\225\214\345\271\266\350\241\214/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\234\211\347\225\214\345\271\266\350\241\214/index.html" new file mode 100644 index 000000000..34138d26a --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\346\234\211\347\225\214\345\271\266\350\241\214/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/72.4cc3186e.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/有界并行/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/72.4cc3186e.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\224\237\346\210\220\345\231\250/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\224\237\346\210\220\345\231\250/index.html" new file mode 100644 index 000000000..80b76f4e1 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\224\237\346\210\220\345\231\250/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/73.03d8974c.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/生成器/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/73.03d8974c.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\255\226\347\225\245/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\255\226\347\225\245/index.html" new file mode 100644 index 000000000..6dfea1e90 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\347\255\226\347\225\245/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/74.4f1eeb3c.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/策略/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/74.4f1eeb3c.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\243\205\351\245\260\345\231\250/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\243\205\351\245\260\345\231\250/index.html" new file mode 100644 index 000000000..87ee3e882 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\243\205\351\245\260\345\231\250/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/75.d44fc2e7.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/装饰器/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/75.d44fc2e7.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\247\202\345\257\237\350\200\205/index.html" "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\247\202\345\257\237\350\200\205/index.html" new file mode 100644 index 000000000..74fc1a987 --- /dev/null +++ "b/\345\267\245\347\250\213/go\347\274\226\347\250\213\350\214\203\345\274\217/\350\247\202\345\257\237\350\200\205/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/76.f53bf284.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go编程范式/观察者/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">8/7/2023, 3:58:56 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/76.f53bf284.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\350\257\255\350\250\200\350\247\204\350\214\203/index.html" "b/\345\267\245\347\250\213/go\350\257\255\350\250\200\350\247\204\350\214\203/index.html" new file mode 100644 index 000000000..5c1d2af95 --- /dev/null +++ "b/\345\267\245\347\250\213/go\350\257\255\350\250\200\350\247\204\350\214\203/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/77.bad2588a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-语言规范">go 语言规范</h1> <p>总结了 go,google 官方以及腾讯的 go 语言规范。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/ref/spec</li> <li>https://github.com/Tencent/secguide/blob/main/Go%E5%AE%89%E5%85%A8%E6%8C%87%E5%8D%97.md</li> <li>https://google.github.io/styleguide/go/best-practices</li> <li>https://colobu.com/2023/11/17/golang-quick-reference-top-20-best-coding-practices/</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go语言规范/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">12/6/2023, 8:24:47 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/77.bad2588a.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/architect.html" "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/architect.html" new file mode 100644 index 000000000..1db56b52a --- /dev/null +++ "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/architect.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/79.f5c3f20d.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go面试题/architect.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/29/2023, 2:17:57 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/79.f5c3f20d.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/index.html" "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/index.html" new file mode 100644 index 000000000..b23c9d6e0 --- /dev/null +++ "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 面试题 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/78.2ee31447.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 面试题</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/#按照公司排序" class="sidebar-link">按照公司排序</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/go%E9%9D%A2%E8%AF%95%E9%A2%98/#最终总结出的面试题" class="sidebar-link">最终总结出的面试题</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-面试题">go 面试题</h1> <ul><li><a href="/GOFamily/工程/go面试题/中高级go面试题一.html">中高级 go 面试题一</a></li></ul> <h2 id="按照公司排序">按照公司排序</h2> <h2 id="最终总结出的面试题">最终总结出的面试题</h2> <ul><li><a href="/GOFamily/工程/go面试题/primary.html">初级</a></li> <li><a href="/GOFamily/工程/go面试题/intermediate.html">中级</a></li> <li><a href="/GOFamily/工程/go面试题/senior.html">高级</a></li> <li><a href="/GOFamily/工程/go面试题/architect.html">架构师</a></li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go面试题/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/29/2023, 2:17:57 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/78.2ee31447.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/intermediate.html" "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/intermediate.html" new file mode 100644 index 000000000..357cece2d --- /dev/null +++ "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/intermediate.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/80.5aa44af4.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go面试题/intermediate.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/29/2023, 2:17:57 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/80.5aa44af4.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/primary.html" "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/primary.html" new file mode 100644 index 000000000..c73ab3873 --- /dev/null +++ "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/primary.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/81.33455a03.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go面试题/primary.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/29/2023, 2:17:57 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/81.33455a03.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/senior.html" "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/senior.html" new file mode 100644 index 000000000..473b2d7c6 --- /dev/null +++ "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/senior.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/82.9f2284bd.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go面试题/senior.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">10/29/2023, 2:17:57 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/82.9f2284bd.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/\344\270\255\351\253\230\347\272\247go\351\235\242\350\257\225\351\242\230\344\270\200.html" "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/\344\270\255\351\253\230\347\272\247go\351\235\242\350\257\225\351\242\230\344\270\200.html" new file mode 100644 index 000000000..6af09c7fd --- /dev/null +++ "b/\345\267\245\347\250\213/go\351\235\242\350\257\225\351\242\230/\344\270\255\351\253\230\347\272\247go\351\235\242\350\257\225\351\242\230\344\270\200.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/83.5e222179.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><ol><li>自我介绍</li> <li>代码效率分析,考察局部性原理</li> <li>多核 CPU 场景下,cache 如何保持一致、不冲突?</li> <li>uint 类型溢出</li> <li>介绍 rune 类型</li> <li>编程题:3 个函数分别打印 cat、dog、fish,要求每个函数都要起一个 goroutine,按照 cat、dog、fish 顺序打印在屏幕上 100 次。</li> <li>介绍一下 channel,无缓冲和有缓冲区别</li> <li>是否了解 channel 底层实现,比如实现 channel 的数据结构是什么?</li> <li>channel 是否线程安全?</li> <li>Mutex 是悲观锁还是乐观锁?悲观锁、乐观锁是什么?</li> <li>Mutex 几种模式?</li> <li>Mutex 可以做自旋锁吗?</li> <li>介绍一下 RWMutex</li> <li>项目中用过的锁?</li> <li>介绍一下线程安全的共享内存方式</li> <li>介绍一下 goroutine</li> <li>goroutine 自旋占用 cpu 如何解决 (go 调用、gmp)</li> <li>介绍 linux 系统信号</li> <li>goroutine 抢占时机 (gc 栈扫描)</li> <li>Gc 触发时机</li> <li>是否了解其他 gc 机制</li> <li>Go 内存管理方式</li> <li>Channel 分配在栈上还是堆上?哪些对象分配在堆上,哪些对象分配在栈上?</li> <li>介绍一下大对象小对象,为什么小对象多了会造成 gc 压力?</li> <li>项目中遇到的 oom 情况?</li> <li>项目中使用 go 遇到的坑?</li> <li>工作遇到的难题、有挑战的事情,如何解决?</li> <li>如何指定指令执行顺序?</li></ol></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/go面试题/中高级go面试题一.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/83.5e222179.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/index.html" "b/\345\267\245\347\250\213/index.html" new file mode 100644 index 000000000..3d391a85b --- /dev/null +++ "b/\345\267\245\347\250\213/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>工程 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/46.7fef4e9d.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>工程</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="工程">工程</h1> <ul><li><a href="./log">log 包</a></li> <li><a href="./%E6%B5%8B%E8%AF%95">测试</a></li> <li><a href="./%E6%80%A7%E8%83%BD%E5%89%96%E6%9E%90">性能剖析</a></li> <li><a href="./%E5%8C%85%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7">包管理工具</a></li> <li><a href="./%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95">动态调试</a></li> <li><a href="./%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86">错误处理</a></li> <li><a href="./cgo">cgo</a></li> <li><a href="./golint">go lint</a></li> <li><a href="./%E5%8F%8D%E5%B0%84">反射</a></li> <li><a href="./web">web</a></li> <li><a href="./wasm">wasm</a></li> <li><a href="./%E5%91%BD%E4%BB%A4">命令</a></li> <li><a href="./%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85">优秀第三方包</a></li> <li><a href="./go%E6%A0%87%E5%87%86%E5%BA%93">go 标准库</a></li> <li><a href="./%E9%A1%B9%E7%9B%AE%E7%BB%84%E7%BB%87%E5%BD%A2%E5%BC%8F">go 项目组织形式</a></li> <li><a href="./go%E5%91%BD%E5%90%8D%E6%83%AF%E4%BE%8B">go 命名惯例</a></li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/46.7fef4e9d.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/ioc/index.html" "b/\345\267\245\347\250\213/ioc/index.html" new file mode 100644 index 000000000..2bf401dca --- /dev/null +++ "b/\345\267\245\347\250\213/ioc/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>IOC | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/84.b93653e7.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>IOC</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/ioc/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="ioc">IOC</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/Ar-JdkrQ5NnCWcGOoCuVgg</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/ioc/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">6/29/2022, 3:31:28 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/84.b93653e7.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/log/index.html" "b/\345\267\245\347\250\213/log/index.html" new file mode 100644 index 000000000..03261e619 --- /dev/null +++ "b/\345\267\245\347\250\213/log/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>log 包 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/85.aff346f9.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>log 包</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/log/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="log-包">log 包</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://github.com/uber-go/zap</li> <li>https://pkg.go.dev/golang.org/x/exp/slog</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/log/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/8/2022, 4:03:36 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/85.aff346f9.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/wasm/index.html" "b/\345\267\245\347\250\213/wasm/index.html" new file mode 100644 index 000000000..bb55fea3d --- /dev/null +++ "b/\345\267\245\347\250\213/wasm/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>wasm 在 go 中的实践 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/86.ca707802.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>wasm 在 go 中的实践</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/wasm/#参考文章" class="sidebar-link">参考文章</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="wasm-在-go-中的实践">wasm 在 go 中的实践</h1> <h2 id="参考文章">参考文章</h2> <ul><li>https://github.com/golang/go/wiki/WebAssembly</li> <li>https://blog.csdn.net/jojo1001/article/details/130611146</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/wasm/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">12/6/2023, 8:24:47 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/86.ca707802.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\344\273\243\347\240\201\346\243\200\346\237\245/index.html" "b/\345\267\245\347\250\213/\344\273\243\347\240\201\346\243\200\346\237\245/index.html" new file mode 100644 index 000000000..dbbe7a8fa --- /dev/null +++ "b/\345\267\245\347\250\213/\344\273\243\347\240\201\346\243\200\346\237\245/index.html" @@ -0,0 +1,133 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>代码检查工具 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/87.d9bc2332.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>代码检查工具</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/#go-vet-go-tool-vet" class="sidebar-link">go vet / go tool vet</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/#golangci-lint" class="sidebar-link">golangci-lint</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/#govulncheck" class="sidebar-link">govulncheck</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/#x-tools-工具系列" class="sidebar-link">x/tools 工具系列</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E4%BB%A3%E7%A0%81%E6%A3%80%E6%9F%A5/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="代码检查工具">代码检查工具</h1> <p>代码检查通常会被配置再 CI 中,用于自动检查代码的质量,本次我们介绍三个用于代码检查的工具</p> <ul><li>go vet / go tool vet</li> <li>golangci-lint</li> <li>govulncheck</li></ul> <h2 id="go-vet-go-tool-vet">go vet / go tool vet</h2> <p>go vet 命令是 go tool vet 的简单封装,go vet 实际上还是需要调用 go tool vet 才能完成工作,这俩命令的主要目的就是为了基础的代码检查。不过这个命令只能做简单的检查,下面我们介绍一下更常用的工具。</p> <h2 id="golangci-lint">golangci-lint</h2> <p>首先在介绍 golangci-lint 之前我们先下载它,它是一个 go 语言写的可执行文件,使用</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span> install github<span class="token punctuation">.</span>com<span class="token operator">/</span>golangci<span class="token operator">/</span>golangci<span class="token operator">-</span>lint<span class="token operator">/</span>cmd<span class="token operator">/</span>golangci<span class="token operator">-</span>lint@latest +</code></pre></div><p>即可下载到本地的~/go/bin/ 目录,这里专门存储使用 go install 下载的使用 go 写的可执行文件,记得将这个路径加入 PATH。</p> <p>通过在要检查的项目中设置配置文件,用来配置 lint 工具的选项,使用 <code>.golangci.yaml</code> 即可</p> <p>例如:</p> <div class="language-bash extra-class"><pre class="language-bash"><code> +run: + skip-dirs: <span class="token comment"># 设置要忽略的目录</span> + - util + - .*~ + - api/swagger/docs + skip-files: <span class="token comment"># 设置不需要检查的go源码文件,支持正则匹配,这里建议包括:_test.go</span> + - <span class="token string">".*<span class="token entity" title="\\">\\</span>.my<span class="token entity" title="\\">\\</span>.go$"</span> + - _test.go +linters-settings: + errcheck: + check-type-assertions: <span class="token boolean">true</span> <span class="token comment"># 这里建议设置为true,如果确实不需要检查,可以写成`num, _ := strconv.Atoi(numStr)`</span> + check-blank: <span class="token boolean">false</span> + gci: + <span class="token comment"># 将以`github.com/marmotedu/iam`开头的包放在第三方包后面</span> + local-prefixes: github.com/marmotedu/iam + godox: + keywords: <span class="token comment"># 建议设置为BUG、FIXME、OPTIMIZE、HACK</span> + - BUG + - FIXME + - OPTIMIZE + - HACK + goimports: + <span class="token comment"># 设置哪些包放在第三方包后面,可以设置多个包,逗号隔开</span> + local-prefixes: github.com/marmotedu/iam + gomoddirectives: <span class="token comment"># 设置允许在go.mod中replace的包</span> + replace-local: <span class="token boolean">true</span> + replace-allow-list: + - github.com/coreos/etcd + - google.golang.org/grpc + - github.com/marmotedu/api + - github.com/marmotedu/component-base + - github.com/marmotedu/marmotedu-sdk-go + gomodguard: <span class="token comment"># 下面是根据需要选择可以使用的包和版本,建议设置</span> + allowed: + modules: + - gorm.io/gorm + - gorm.io/driver/mysql + - k8s.io/klog + domains: <span class="token comment"># List of allowed module domains</span> + - google.golang.org + - gopkg.in + - golang.org + - github.com + - go.uber.org + blocked: + modules: + - github.com/pkg/errors: + recommendations: + - github.com/marmotedu/errors + reason: <span class="token string">"<span class="token variable"><span class="token variable">`</span>github.com/marmotedu/errors<span class="token variable">`</span></span> is the log package used by marmotedu projects."</span> + versions: + - github.com/MakeNowJust/heredoc: + version: <span class="token string">"> 2.0.9"</span> + reason: <span class="token string">"use the latest version"</span> + local_replace_directives: <span class="token boolean">false</span> + lll: + line-length: <span class="token number">240</span> <span class="token comment"># 这里可以设置为240,240一般是够用的</span> + importas: <span class="token comment"># 设置包的alias,根据需要设置</span> + jwt: github.com/appleboy/gin-jwt/v2 + metav1: github.com/marmotedu/component-base/pkg/meta/v1 + +</code></pre></div><p>使用 golangci-lint run (等于 golangci-lint run ./... 意思就是把所有的包,子包,遍历完全) 你会得到一个类似:</p> <div class="language-bash extra-class"><pre class="language-bash"><code> +collie.go:171:41: composites: image/jpeg.Options struct literal uses unkeyed fields <span class="token punctuation">(</span>govet<span class="token punctuation">)</span> + <span class="token keyword">if</span> err :<span class="token operator">=</span> jpeg.Encode<span class="token punctuation">(</span>file, i.img, <span class="token operator">&</span>jpeg.Options<span class="token punctuation">{</span>q<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> nil <span class="token punctuation">{</span> + ^ +collie.go:241:2: printf: <span class="token variable"><span class="token variable">`</span>fmt.Println<span class="token variable">`</span></span> arg list ends with redundant newline <span class="token punctuation">(</span>govet<span class="token punctuation">)</span> + fmt.Println<span class="token punctuation">(</span><span class="token string">"声明:本程序来自GitHub:shgopher,欢迎关注公众号:科科人神;<span class="token entity" title="\n">\n</span>免费软件,如果使用期间出现任何后果,本软件不承担任何责任谢谢<span class="token entity" title="\n">\n</span>"</span><span class="token punctuation">)</span> + ^ +collie.go:244:2: printf: <span class="token variable"><span class="token variable">`</span>fmt.Println<span class="token variable">`</span></span> arg list ends with redundant newline <span class="token punctuation">(</span>govet<span class="token punctuation">)</span> + fmt.Println<span class="token punctuation">(</span><span class="token string">"运行结束 ☕️ ☕ ☕<span class="token entity" title="\n">\n</span>"</span><span class="token punctuation">)</span> + ^ +collie.go:162:5: SA9001: defers <span class="token keyword">in</span> this range loop won't run unless the channel gets closed <span class="token punctuation">(</span>staticcheck<span class="token punctuation">)</span> + defer file.Close<span class="token punctuation">(</span><span class="token punctuation">)</span> + ^ +</code></pre></div><p>这样的结果,这样你就会发现是哪个配置的 linter 发出的警告,以及是什么样子的警告。</p> <h2 id="govulncheck">govulncheck</h2> <p>go 官方维护了一个 https://vuln.go.dev/ 的漏洞库,我们可以使用 <code>go install golang.org/x/vuln/cmd/govulncheck@latest</code> 的方式,下载目前 (go 1.19) 还在测试阶段的这一功能,<code>govulncheck</code> 将会是一个独立的工具,并且 go 在 https://pkg.go.dev/golang.org/x/vuln/vulncheck 还提供了相关功能的 API,可以更灵活的去使用这个功能,目前已知的即将推出的功能分别是提供 vscode 插件,以及将此功能集成在 pkg.go.dev 这个 go 包的集合地,也就是说只要被收录在这个网站的 go 包都将自动接受漏洞检查,另外,go 以后可能还会将这个功能直接集成在例如 <code>go build</code> 这种常用命令上。</p> <ul><li>下载 govulncheck <code>go install golang.org/x/vuln/cmd/govulncheck@latest</code></li> <li>在一个拥有 go.mod 的目录下,使用 govulncheck 跟上一个有 go 文件的路径,例如:<code>govulncheck ./pkg/watcher</code></li></ul> <p>只需要这样简单的设置就可以去检查代码中存在的风险和漏洞,govulncheck 就会打印出这样的信息:</p> <div class="language-go extra-class"><pre class="language-go"><code>Vulnerability #<span class="token number">2</span><span class="token punctuation">:</span> GO<span class="token operator">-</span><span class="token number">2022</span><span class="token operator">-</span><span class="token number">0493</span> + When called with a non<span class="token operator">-</span>zero flags parameter<span class="token punctuation">,</span> the Faccessat + function can incorrectly report that a file is accessible<span class="token punctuation">.</span> + Found in<span class="token punctuation">:</span> golang<span class="token punctuation">.</span>org<span class="token operator">/</span>x<span class="token operator">/</span>sys<span class="token operator">/</span>unix@v0<span class="token punctuation">.</span><span class="token number">0.0</span><span class="token operator">-</span><span class="token number">20211020064051</span><span class="token operator">-</span>0ec99a608a1b + Fixed in<span class="token punctuation">:</span> golang<span class="token punctuation">.</span>org<span class="token operator">/</span>x<span class="token operator">/</span>sys<span class="token operator">/</span>unix@v0<span class="token punctuation">.</span><span class="token number">0.0</span><span class="token operator">-</span><span class="token number">20220412211240</span><span class="token operator">-</span>33da011f77ad + More info<span class="token punctuation">:</span> https<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span>pkg<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">.</span>dev<span class="token operator">/</span>vuln<span class="token operator">/</span>GO<span class="token operator">-</span><span class="token number">2022</span><span class="token operator">-</span><span class="token number">0493</span> +</code></pre></div><p>信息中包括了你引用的某些包出现的一些漏洞,在 fix 中有修复的信息,可以把你引用的包进行一个升级。</p> <h2 id="x-tools-工具系列">x/tools 工具系列</h2> <blockquote><p>https://pkg.go.dev/golang.org/x/tools#section-readme</p></blockquote> <p>比如检测变量 shadow 的工具</p> <div class="language-bash extra-class"><pre class="language-bash"><code>go <span class="token function">install</span> golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow +</code></pre></div><h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/blog/vuln</li> <li>https://time.geekbang.org/column/article/390401</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/代码检查/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/87.d9bc2332.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/gin/index.html" "b/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/gin/index.html" new file mode 100644 index 000000000..458db136b --- /dev/null +++ "b/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/gin/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>gin | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/89.37b7fea9.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>gin</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E4%BC%98%E7%A7%80%E7%AC%AC%E4%B8%89%E6%96%B9%E5%8C%85/gin/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="gin">gin</h1> <blockquote><p>https://github.com/gin-gonic/gin</p></blockquote> <h2 id="参考资料">参考资料</h2> <ul><li>https://betterprogramming.pub/a-do-it-yourself-implementation-of-the-golang-middleware-6f02f155ed17</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/优秀第三方包/gin/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/89.37b7fea9.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/index.html" "b/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/index.html" new file mode 100644 index 000000000..11d0a1ad3 --- /dev/null +++ "b/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>优秀第三方包 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/88.87973a44.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>优秀第三方包</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="优秀第三方包">优秀第三方包</h1> <ul><li><a href="./gin">gin</a> 优秀的 web 框架</li> <li><a href="./sonic">sonic</a> 字节跳动出品的 json 引擎</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/优秀第三方包/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/88.87973a44.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/sonic/index.html" "b/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/sonic/index.html" new file mode 100644 index 000000000..bd241ab96 --- /dev/null +++ "b/\345\267\245\347\250\213/\344\274\230\347\247\200\347\254\254\344\270\211\346\226\271\345\214\205/sonic/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>sonic | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/90.dedfc540.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>sonic</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="sonic">sonic</h1> <blockquote><p>https://github.com/bytedance/sonic</p></blockquote></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/优秀第三方包/sonic/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/90.dedfc540.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\345\212\250\346\200\201\350\260\203\350\257\225/index.html" "b/\345\267\245\347\250\213/\345\212\250\346\200\201\350\260\203\350\257\225/index.html" new file mode 100644 index 000000000..c0b84cab6 --- /dev/null +++ "b/\345\267\245\347\250\213/\345\212\250\346\200\201\350\260\203\350\257\225/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>动态调试 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/91.dbd4ca9b.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>动态调试</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8A%A8%E6%80%81%E8%B0%83%E8%AF%95/#资料" class="sidebar-link">资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="动态调试">动态调试</h1> <h2 id="资料">资料</h2> <ul><li>https://mp.weixin.qq.com/s/qfukFmJRcBAjn-e2K73VLQ</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/动态调试/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">6/29/2022, 3:31:28 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/91.dbd4ca9b.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\345\214\205\345\217\212\345\205\266\346\236\204\345\273\272\345\267\245\345\205\267/index.html" "b/\345\267\245\347\250\213/\345\214\205\345\217\212\345\205\266\346\236\204\345\273\272\345\267\245\345\205\267/index.html" new file mode 100644 index 000000000..d2e386853 --- /dev/null +++ "b/\345\267\245\347\250\213/\345\214\205\345\217\212\345\205\266\346\236\204\345\273\272\345\267\245\345\205\267/index.html" @@ -0,0 +1,275 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 包管理工具 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/92.61c0947f.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 包管理工具</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#go-语言的包导入过程" class="sidebar-link">go 语言的包导入过程</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#go-程序的构建过程。" class="sidebar-link">go 程序的构建过程。</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#go-module-构建工具" class="sidebar-link">go module 构建工具</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#如何控制-go-引入的包的版本号。" class="sidebar-link">如何控制 go 引入的包的版本号。</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#如何优雅的升级和降级引入的包版本" class="sidebar-link">如何优雅的升级和降级引入的包版本?</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#引入的-go-包-git-更改名称了怎么办" class="sidebar-link">引入的 go 包 git 更改名称了怎么办?</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#go-包代理" class="sidebar-link">go 包代理</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#如何使用一个私有包" class="sidebar-link">如何使用一个私有包</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#本地开发使用的配置文件-go-work" class="sidebar-link">本地开发使用的配置文件 go.work</a></li></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%8C%85%E5%8F%8A%E5%85%B6%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-包管理工具">go 包管理工具</h1> <ul><li>go 导包的过程</li> <li>go 包的版本管理</li> <li>go 包的最小版本原则</li> <li>go module 命令的使用 +<ul><li>go get / go install</li> <li>GOPROXY</li> <li>GOSUMDB</li> <li>go 使用私有服务器</li> <li>workspace</li></ul></li></ul> <h2 id="go-语言的包导入过程">go 语言的包导入过程</h2> <ul><li>go 编译快的原因</li> <li>go 程序的构建过程</li></ul> <p>go 程序编译快的原因。1 是因为 go 要求每一个包都必须显式的标记处引入的包。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> hi + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"io"</span> + + <span class="token string">"github.com/shgopher/hui"</span> +<span class="token punctuation">)</span> +</code></pre></div><p>所以编译器无需去查找这个文件中具体引入了哪些包就可以在头部检索出全部的导包名单</p> <p>2 是因为 go 语言不允许循环引用,比如说 a 引用了 b,b 又引入了 a,所以每一个包都是独立的存在,处于 “有向无环图 “这种格式下,进而可以并行去编译不同的包,提高编译效率。</p> <p>3 包编译的结果里 (<code>xx.o</code>,<code>xx.a</code>) 中不仅存储了此包的导出信息,还存储了它引入的包的导出信息,这样编译器只需要读取一个目标文件就可以获取全部的包信息,不需要读取全部的文件。比如 p 包要引入 q 包,那么 q 包的。a 文件已经包括了它引入的全部包的导出信息,这样编译器可以快速统计某一个包被引用的情况,比如包引用了 a b,a b 分别引用了 c 但是版本不同,那么这种情况下因为主包已经了解了他们的情况,所以就可以用最小版本原则去选择一个版本的包进行编译即可。有点类似分封制,我帝王 p 包,我的直接负责人是诸侯 q,q 掌握了它下级 s 的所有数据,假设 s 还有下级,s 掌握了 w 的所有数据,然后层层回报,当帝王 p 最终编译的时候,它已经完全拥有了所有的数据,可以精准调控。再结合每一个包都可以独立的并行编译</p> <p>所以这一整套下来 go 的编译速度就会很快。并且在 go.mod 文件中也会详细记录使用过的包及其版本,那么并行下载,快速编译就不是梦了。</p> <h2 id="go-程序的构建过程。">go 程序的构建过程。</h2> <p>go 程序的建立是由编译和链接两个阶段组成的,举个例子 +有一个项目拥有一个 main 包,一个 lib 包,lib 包会被引入到 main 包中,那么编译的过程是这样的,首先创建一个临时工作区域,编译 lib 包为 lib.a,编译 main 包为 main.a,链接器将 lib.a 和 main.a 链接成 name.out,然后改名为 name (unix-like),<strong>使用第三方包的意思就是链接了该包的源代码编译的最新的。a 文件而已</strong>,并且<strong>每次编译</strong>都会重新编译最新的。a 文件 (所以只保留。a 文件,删除源码是不可行的),但是标准库除外,并不会每次编译都会重新编译标准库,所以说如果你修改了源码一定得把标准库。a 文件删除,并且 build 的时候使用 <code>build -a</code> 的方式才可以使用自己更新的标准库。</p> <p>一个小 tip:go 导包的时候引入的是路径名称,路径名称<strong>通常</strong>最后一位路径名称跟包名保持一致,当然也可以不一致。例如 <code>github.com/shgopher/go-hui</code> 但是实际上包名称是这个 <code>package hui</code>,所以导入的时候按照 <code>github.com/shgopher/go-hui</code>,使用的时候用 <code>hui.xxx()</code>。</p> <p>因为包的名称很容易发生冲突,所以 go 接受包名称的重命名</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">import</span> <span class="token punctuation">(</span> + + app <span class="token string">"github.com/shgopher/app"</span> + app1 <span class="token string">"github.com/googege/app"</span> +<span class="token punctuation">)</span> +</code></pre></div><p>除此之外还有 <code>_</code> 方式,它会<strong>计算包级变量的初始化表达式</strong>和<strong>执行导入包的 init 初始化函数</strong>,意思就是跟 init 函数有关的内容都会被计算,并且导入进去。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"image"</span> + <span class="token string">"image/jpeg"</span> + <span class="token boolean">_</span> <span class="token string">"image/png"</span> + <span class="token string">"io"</span> + <span class="token string">"os"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> <span class="token function">toJPEG</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span>Stdin<span class="token punctuation">,</span> os<span class="token punctuation">.</span>Stdout<span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Fprintf</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span>Stderr<span class="token punctuation">,</span> <span class="token string">"jpeg: %v\n"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span> + os<span class="token punctuation">.</span><span class="token function">Exit</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">toJPEG</span><span class="token punctuation">(</span>in io<span class="token punctuation">.</span>Reader<span class="token punctuation">,</span> out io<span class="token punctuation">.</span>Writer<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> + img<span class="token punctuation">,</span> kind<span class="token punctuation">,</span> err <span class="token operator">:=</span> image<span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span>in<span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> err + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Fprintln</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span>Stderr<span class="token punctuation">,</span> <span class="token string">"Input format ="</span><span class="token punctuation">,</span> kind<span class="token punctuation">)</span> + <span class="token keyword">return</span> jpeg<span class="token punctuation">.</span><span class="token function">Encode</span><span class="token punctuation">(</span>out<span class="token punctuation">,</span> img<span class="token punctuation">,</span> <span class="token operator">&</span>jpeg<span class="token punctuation">.</span>Options<span class="token punctuation">{</span>Quality<span class="token punctuation">:</span> <span class="token number">95</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>比如这个例子,image.Decode 会查询注册表,看看注册表里都有谁,这个时候我们引入的 _ iumage/png 的 init 函数就是将 png 中实现了接口的具体数据导入到了注册表中,所以说这里只需要导入这个 init 函数即可。</p> <p>这种用法还是比较重要的,我们来自己编写一段代码,来看看实现这种注册器的基本原理:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 这里是实现这个注册器</span> +<span class="token keyword">package</span> go2 +<span class="token comment">// 在某个包实现go2的时候,这里是go3,这个drivers就被初始化了。</span> +<span class="token keyword">var</span> drivers <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span>Driver<span class="token punctuation">)</span> + +<span class="token keyword">type</span> Driver <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">Open</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">Register</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">,</span> driver Driver<span class="token punctuation">)</span> <span class="token punctuation">{</span> + drivers<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">=</span> driver +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">DDD</span><span class="token punctuation">(</span>name <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> d Driver + <span class="token keyword">if</span> d1<span class="token punctuation">,</span> ok <span class="token operator">:=</span> drivers<span class="token punctuation">[</span>name<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"no real driver registered"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + d <span class="token operator">=</span> d1 + <span class="token punctuation">}</span> + d<span class="token punctuation">.</span><span class="token function">Open</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 这里是实际的实现我们注册器那个包实现的抽象方法</span> +<span class="token keyword">package</span> go3 + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + + <span class="token string">"shgopher.com/go2"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">type</span> ddd <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>d <span class="token operator">*</span>ddd<span class="token punctuation">)</span> <span class="token function">Open</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"this is go3"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + go2<span class="token punctuation">.</span><span class="token function">Register</span><span class="token punctuation">(</span><span class="token string">"go3"</span><span class="token punctuation">,</span> <span class="token operator">&</span>ddd<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code> +<span class="token comment">// 最后我们来使用一下:</span> + +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"shgopher.com/go2"</span> + <span class="token boolean">_</span> <span class="token string">"shgopher.com/go3"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + go2<span class="token punctuation">.</span><span class="token function">DDD</span><span class="token punctuation">(</span><span class="token string">"go3"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>另外还有一种导入包的奇妙用法,就是</p> <div class="language-go extra-class"><pre class="language-go"><code> <span class="token punctuation">.</span> <span class="token string">"fmt"</span> + + <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"hi"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +</code></pre></div><p>它的意思是省略包名,no!,请不要这么用。</p> <h2 id="go-module-构建工具">go module 构建工具</h2> <ul><li>go111MODULE</li> <li>GOPROXY</li> <li>GOSUMDB</li> <li>module 版本的升级</li> <li>workspace</li></ul> <p>go 自带包管理工具 go module,本文章写作时 go 的版本是 1.19,所以过去的 go path,go vendor,go dep 均不再提及,读者也不用去 care,鉴于干谈 go module 非常的枯燥,我设立一个例子来讲述 go module。</p> <p>在桌面,我们使用 go module 的创建命令</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token builtin class-name">cd</span> ~/Desktop + +<span class="token function">mkdir</span> hello + +go mod init github.com/shgopher/hello + +</code></pre></div><p>创立了一个以 hello 作为包名称的包。这里我们使用 <code>github.com/shgopher/hello</code> 是证明这个包使用 GitHub 进行存储,因为 go 使用 git 来管理版本,在项目内部,这个项目的包名称就是最后一个名称,hello 才是这个包的正式名称,此处是惯用,实际上真实管理包正式名称的是每一个文件上的 package xx 管理的,整个就是路径而已,不过习惯于最后一个路径名称为包的名称,即:最后一个名称 == package 后面的 xxx。</p> <p>然后我们在这个项目的 root 路径下会发现 go 帮我们创建了一个 go.mod 的文件,它就是 go module 的版本文件,我们拿一个 go.mod 来作为举例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 一个 go.mod 目录:</span> + +module github<span class="token punctuation">.</span>com<span class="token operator">/</span>shgopher<span class="token operator">/</span>hello + +<span class="token keyword">go</span> <span class="token number">1.19</span> + + +require <span class="token punctuation">(</span> + github<span class="token punctuation">.</span>com<span class="token operator">/</span>apache<span class="token operator">/</span>thrift v0<span class="token punctuation">.</span><span class="token number">13.0</span> + github<span class="token punctuation">.</span>com<span class="token operator">/</span>bytedance<span class="token operator">/</span>gopkg v0<span class="token punctuation">.</span><span class="token number">0.0</span><span class="token operator">-</span><span class="token number">20220531084716</span><span class="token operator">-</span>665b4f21126f + github<span class="token punctuation">.</span>com<span class="token operator">/</span>appleboy<span class="token operator">/</span>gin<span class="token operator">-</span>jwt<span class="token operator">/</span>v2 v2<span class="token punctuation">.</span><span class="token number">6.4</span> + gopkg<span class="token punctuation">.</span>in<span class="token operator">/</span>yaml<span class="token punctuation">.</span>v3 v3<span class="token punctuation">.</span><span class="token number">0.1</span> +<span class="token punctuation">)</span> + +require <span class="token punctuation">(</span> + + github<span class="token punctuation">.</span>com<span class="token operator">/</span>beorn7<span class="token operator">/</span>perks v1<span class="token punctuation">.</span><span class="token number">0.1</span> <span class="token comment">// indirect</span> +<span class="token punctuation">)</span> + +replace <span class="token punctuation">(</span> + <span class="token comment">// 后面指向的要么是相对路径例如 ../shgopher/.com/net</span> + <span class="token comment">// 要么一定要在后面加上版本,并且是可以获取到的包</span> + golang<span class="token punctuation">.</span>org<span class="token operator">/</span>x<span class="token operator">/</span>net v1<span class="token punctuation">.</span><span class="token number">1.2</span> <span class="token operator">=</span><span class="token operator">></span> shgopher<span class="token punctuation">.</span>com<span class="token operator">/</span>net v1<span class="token punctuation">.</span><span class="token number">4.5</span> +<span class="token punctuation">)</span> + +</code></pre></div><p>我们一个一个解释,首先最开头的是这个包的路径名称,实际上 go 会使用 <code>git clone https://github.com/shgopher/hello.git</code> 的方式下载包,当然,假设你不使用 GitHub 的 git 作为项目的存储位置,使用自建的也是 OK 的,比如 <code>module shgopher.com/hello</code> 只要同样配置了 git 服务器都可以,因为底层都是使用的 <code>git clone https://xxx.com/xx.git</code> 模式。</p> <p>接下来的 <code>go 1.19</code> 是这个项目使用的 go 的大版本,比如你使用的是 <code>1.19.1</code>,<code>1.19.2</code>,上面写的都是 <code>go 1.19</code>,比如你使用 <code>go mod edit -go=1.19</code> 来更新此项目使用的 go 版本的时候,只能写到 minor,而不能加上 patch (minor 和 patch 下文有说)。</p> <p>接下里有两个 require,其中第一个 require 指的是直接引入的包,后面的 require 是间接引用的包。意思就是你引用的包,它引入的包。</p> <p>第一个 require 中,我给出了四种常见的版本用法</p> <ol><li>使用 git version 命名的版本 <code>v0.13.0</code></li> <li>项目没有使用 version 命名,go 官方使用最新的文件,并且给予了它一个临时的版本号 <code>v0.0.0-20220531084716-665b4f21126f</code></li> <li>当项目的版本超过 1.x 的时候,go 推荐使用再加上一个/v2 的方式进行命名,但是实际上它的包名称仍然是 gin-jwt,并且 1.x 和 2.x 的包可以同时引入项目中,因为他们算两个包,只需要重命名即可。版本 2 和版本 1 的 module 后面写的也不一样,比如一个是 <code>module github.com/shgopher/collie</code> 版本 2 就是 <code>module github.com/shgopher/collie/v2</code> 不过虽然最后结尾的是 v2 但是 package 后面写的仍然是 collie</li> <li>也可以使用 yaml.v3 的方式进行命名,因为路径名称并不是包的名称,所以这种方式也有不少项目使用</li></ol> <p>第二个 require,全部都是间接引用的包名称,go 也会一并下载到本地缓存,go 会使用 <code>~/go/pkg/mod/包名称@版本号</code> 的地方去保存下载下来的包。</p> <p>使用 <code>go list -m -json all</code> 命令可以查看当前项目的所有依赖的包名称,例如</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> + <span class="token property">"Path"</span><span class="token operator">:</span> <span class="token string">"github.com/marmotedu/iam"</span><span class="token punctuation">,</span> + <span class="token property">"Main"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> + <span class="token property">"Dir"</span><span class="token operator">:</span> <span class="token string">"/Users/shgopher/Desktop/github-projects/iam"</span><span class="token punctuation">,</span> + <span class="token property">"GoMod"</span><span class="token operator">:</span> <span class="token string">"/Users/shgopher/Desktop/github-projects/iam/go.mod"</span><span class="token punctuation">,</span> + <span class="token property">"GoVersion"</span><span class="token operator">:</span> <span class="token string">"1.18"</span> +<span class="token punctuation">}</span> +<span class="token punctuation">{</span> + <span class="token property">"Path"</span><span class="token operator">:</span> <span class="token string">"cloud.google.com/go"</span><span class="token punctuation">,</span> + <span class="token property">"Version"</span><span class="token operator">:</span> <span class="token string">"v0.93.3"</span><span class="token punctuation">,</span> + <span class="token property">"Time"</span><span class="token operator">:</span> <span class="token string">"2021-08-17T22:38:11Z"</span><span class="token punctuation">,</span> + <span class="token property">"Indirect"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> + <span class="token property">"GoMod"</span><span class="token operator">:</span> <span class="token string">"/Users/shgopher/go/pkg/mod/cache/download/cloud.google.com/go/@v/v0.93.3.mod"</span><span class="token punctuation">,</span> + <span class="token property">"GoVersion"</span><span class="token operator">:</span> <span class="token string">"1.11"</span> +<span class="token punctuation">}</span> +<span class="token punctuation">{</span> + <span class="token property">"Path"</span><span class="token operator">:</span> <span class="token string">"github.com/marmotedu/component-base"</span><span class="token punctuation">,</span> + <span class="token property">"Version"</span><span class="token operator">:</span> <span class="token string">"v1.6.2"</span><span class="token punctuation">,</span> + <span class="token property">"Time"</span><span class="token operator">:</span> <span class="token string">"2021-12-21T06:47:41Z"</span><span class="token punctuation">,</span> + <span class="token property">"GoMod"</span><span class="token operator">:</span> <span class="token string">"/Users/shgopher/go/pkg/mod/cache/download/github.com/marmotedu/component-base/@v/v1.6.2.mod"</span><span class="token punctuation">,</span> + <span class="token property">"GoVersion"</span><span class="token operator">:</span> <span class="token string">"1.17"</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们重点关注几个字段,首先第一个对象中,<code>"Main":true</code>,表示这个对象描述的包属于主包,即,这个项目的 root 路径下的 <code>go.mod</code>;第二个对象中,我们看到 <code>"Indirect": true,</code> 意思就是指这个包是间接引入的包,第三个对象里,并没有出现 indirect 的字段,就证明这个包是直接引入的。因为这个列举的主要是 go.mod 的目录,又因为拥有一个 go.mod 的包拥有同样的版本号,所以包和包的子包是公用一个 go.mod 的,只会出现一次。</p> <h3 id="如何控制-go-引入的包的版本号。">如何控制 go 引入的包的版本号。</h3> <p>当我们更新一个旧的项目中的依赖时,我们可以使用 <code>go clean -modcache</code> 的命令去删除 go 缓存的 go 包。然后显式的为包设置版本,第一种方法是直接在 go.mod 写入要引入的包的版本,第二种方法是使用 <code>go mod -require=github.com/shgopher/hello@v0.1.1</code> 的方式写入你想要的包的版本,除了第二种这种比较精确的方式,go mod 还支持 query 的方式去指定范围,例如说 <code>go mod -require=github.com/shgopher/hello@>=v0.1.1</code>。</p> <p>go 包采用 “最小版本” 选择的理念。举个例子,我的项目 hello,直接引入了 c 包和 d 包,然后 c 和 d 又分别引入了 e 包,那么最后本项目使用的 c,d,e 包采用的是哪个版本呢?</p> <p>我们详细说明一下,假设我们使用的 cde 都是@latest,那么每次 build 的时候,都会去下载最新的包;如果我们使用了具体的版本,假设我们在 go.mod 中给定的 c d 分别是 v0.1.0 v1.0.1 但是呢,c 存在多个版本,比如现在有 v0.1.1 v0.2.1 那么根据最小版本的选择问题,go 会选择一个符合 v0.1.0 的最小版本,即:>=v0.1.0,所以此处会选用 v0.1.1,也就是说 go 的版本的隐藏含义是大于等于选最小,很多别的语言都是大于等于选最大,例如 rust,但是强调一下,<strong>这个大于等于选最大或者最小说的是一个版本的情况下,超过版本号的时候,算俩包 (例如 v1.1.0 和 v2.1.0 就算俩大版本了,所以说他们是俩包都不为过)</strong>,而且我们在改变版本的时候应该先把缓存给清除了 <code>go clean -modcache</code>,接下来我们的 cd 包分别引入了 e 包,假如 e 存在 v1.1.0 v1.2.0 v1.3.0 v1.4.0,c d 分别引入的是 v1.1.0 v1.3.0 那么 go 会<strong>合并需求 (只引入包众多版本的一个版本)</strong>,并且依然采用最小版本的方式即:最终只选用 e 包的 v1.3.0 这一个版本的包引入,总结一下:单个包,使用 >= 的最小值引入,多个包引入同一个包的情况,使用满足他们共同条件下的最小值。</p> <p>使用 go mod tidy 可以对这个项目的包进行梳理,比如使用 latest 的包会重新比对,然后下载最新版本的包,比如在 require 中明确引入的包,但是在实际上线前发现没有继续使用这个包了,那么使用 go mod tidy 也可以删除这个包,这个命令类似于 “刷新” 这个概念。</p> <h3 id="如何优雅的升级和降级引入的包版本">如何优雅的升级和降级引入的包版本?</h3> <p>我们会用到下面两个命令</p> <ul><li>go list</li> <li>go get</li></ul> <p>首先,我们使用 <code>go list -m -versions github.com/shgopher/hello</code> 的命令查找这个包的众多版本 (没有使用 git 给定版本的就没办法了,给定@latest,直接用最新的了),例如说会有 v1.1.0 v1.2.0,假设我们本来用的是 v1.1.0 想升级一下,我们使用 <code>go get github.com/shgopher/hello@v1.2.0</code> 即可优雅的升级这个包的版本,当然降级也是一样的,反正指定一个包即可,要注意的是,go 在升级或者降级的时候,会自动将间接使用的包也做出相应的版本调整。假如我们现在想把所有的依赖包升级为这个版本下的最新包,使用 <code>go get -u</code> 就可以更新所有的直接依赖和间接依赖的包为最新包。如果只想升级 patch 而不是 minor (v1.2.0;1 是 version,2 是 minor,3 是 patch) 使用 <code>go get -u=patch</code>,如果只想升级某一个包 (及其依赖包) 到最新版本,在后面指出来具体的包名称即可,<code>go get -u github.com/shgopher/hello</code>。</p> <p>go install 和 go get 是两个比较像的命令,其中 go get 仅仅用在 go module 中调整版本的时候,比如升级,降级,go install 用于下载包,两者都是一样的,如果包的后面带上版本那么就是指定版本,如果不带就是最新版本。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span> install github<span class="token punctuation">.</span>com<span class="token operator">/</span>shgopher<span class="token operator">/</span>hello + +<span class="token keyword">go</span> install github<span class="token punctuation">.</span>com<span class="token operator">/</span>shgopher<span class="token operator">/</span>hello@v1<span class="token punctuation">.</span><span class="token number">1.2</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span> get <span class="token operator">-</span>u github<span class="token punctuation">.</span>com<span class="token operator">/</span>shgopher<span class="token operator">/</span>hello +<span class="token keyword">go</span> get github<span class="token punctuation">.</span>com<span class="token operator">/</span>shgopher<span class="token operator">/</span>hello@v1<span class="token punctuation">.</span><span class="token number">3.4</span> +</code></pre></div><p>在使用 go install 的时候其实是忽略 go.mod 的,所以 go install 跟 go.mod 没有任何关系,也不会记录 go.mod 中,它的作用就是下载包,go get 跟 go.mod 紧密相关,它需要 go.mod,并且每次更改都会记录在 go.mod 中,当你在一个没有 go.mod 的路径下 (指的是此路径,此路径的父路径也没有) 使用 go get 会提示如下错误</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span><span class="token punctuation">:</span> <span class="token keyword">go</span><span class="token punctuation">.</span>mod file not found in current directory or any parent directory<span class="token punctuation">.</span> + <span class="token char">'go get'</span> is no longer supported outside a module<span class="token punctuation">.</span> + To build and install a command<span class="token punctuation">,</span> use <span class="token char">'go install'</span> with a version<span class="token punctuation">,</span> + like '<span class="token keyword">go</span> install example<span class="token punctuation">.</span>com<span class="token operator">/</span>cmd@latest' + For more information<span class="token punctuation">,</span> see https<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span>golang<span class="token punctuation">.</span>org<span class="token operator">/</span>doc<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>get<span class="token operator">-</span>install<span class="token operator">-</span>deprecation + or run '<span class="token keyword">go</span> help get<span class="token char">' or '</span><span class="token keyword">go</span> help install'<span class="token punctuation">.</span> +</code></pre></div><p>所以这个时候应该使用的是 go install。</p> <h3 id="引入的-go-包-git-更改名称了怎么办">引入的 go 包 git 更改名称了怎么办?</h3> <p>Go 语言提出了一个模块代号 (Module Path) 的概念来解决这个问题。</p> <p>简单来说,模块代号就是一个模块的唯一标识,即使模块仓库的路径名改变了,但其模块代号不变。</p> <p>例如一个模块:</p> <p>模块路径:<code>github.com/user/project</code> +模块代号:<code>github.com/user/project</code> +如果模块 rename 后路径变成了 <code>github.com/newUser/newProj</code>,但模块代号不变:</p> <p>模块新路径:<code>github.com/newUser/newProj</code> +模块代号:<code>github.com/user/project</code> +这样通过模块代号,其他依赖它的模块导入语句就不用修改了,还是导入老的模块代号,但实际上会去新路径下找。</p> <p>在发布新版本代码时,只需要在 go.mod 文件中声明:</p> <p><code>module github.com/user/project</code></p> <p>就可以确保模块代号不变,其他依赖不受影响。</p> <p>所以 Go 语言通过模块代号很好地解决了模块路径变更的问题,最大程度保证了导入的稳定性。</p> <h3 id="go-包代理">go 包代理</h3> <p>GOPROXY 是 go 的代理服务器。go 之前使用 GitHub,gitlab 等托管平台,goproxy 命令可以设置一个集中式的代理服务,比如</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token builtin class-name">export</span> GOPROXY <span class="token operator">=</span> https://goproxy.cn,direct + +<span class="token builtin class-name">export</span> GOPROXY <span class="token operator">=</span> https://proxy.golang.org,direct + +</code></pre></div><p>其中前者是国内常用的代理服务器,后者是 go 官方的代理服务器;<code>direct</code> 的意思是,<strong>直接</strong>使用代理服务器的内容,<code>,</code> 的意思是前面的服务器<strong>只有</strong>出现 404 和 410 错误的时候才会去选择逗号后面的服务,如果想设置只要发生错误就使用后者的命令,那么可以使用 <code>|</code>,例如使用</p> <div class="language-bash extra-class"><pre class="language-bash"><code>go <span class="token function">env</span> -w <span class="token assign-left variable">GOPROXY</span><span class="token operator">=</span>https://proxy.golang.org<span class="token operator">|</span>https://goproxy.cn<span class="token operator">|</span>direct` +</code></pre></div><p>这里有个小知识,因为 <code>|</code> 在 unix-like 操作系统中通常还表示通道的含义,就是前面的输出等于后面的输入,所以我们需要将这个符号进行转义才能正常使用:</p> <div class="language-bash extra-class"><pre class="language-bash"><code>go <span class="token function">env</span> -w <span class="token assign-left variable">GOPROXY</span><span class="token operator">=</span>https://proxy.golang.org<span class="token punctuation">\</span><span class="token operator">|</span>https://goproxy.cn<span class="token punctuation">\</span><span class="token operator">|</span>direct + +</code></pre></div><p>go module 还有 go.sum 这个文件,它存储的是包的一些基础信息,最重要的是对于一个包求 hash 值,记录这个 hash,在每次 build 的时候对于缓存的包和 go.sum 中的 hash 值做对比,来规避恶意更改,go.sum 会在项目的更新换代过程中保存多个版本的包信息。</p> <p>GOSUMDB 命令指向的服务就是保存公有包的校验和的数据库。一个新的包,在一切运行正确的情况下,go 会通过 GOSUMDB 配置的数据库去查询这个包的校验和,查询出结果后和下载的包进行比对,正确的情况下存入 go.sum;如果一个已经缓存的包,每次 run build 的时候都会将缓存的包文件校验跟 go.sum 进行比对来保证正确性。</p> <p>当然,如果你不想使用 GOSUMDB,使用 <code>go env -w GOSUMDB=off</code> 即可。这样就无法对比包和数据库中的校验和,只能做本地校验了。</p> <h3 id="如何使用一个私有包">如何使用一个私有包</h3> <p>我们讲解了如果配置公有的代理服务器 GOPROXY,文件校验和数据库 GOSUMDB,接下来我们谈一下如果我们想使用一个私有的包,比如一个 GitHub 上的私有包,一个本地 git 服务器上的包,我们使用 GOPRIVATE,它的目的就是绕过 GOPROXY 和 GOSUMDB,因为是私有的所以在代理服务器和文件校验和数据库都不会有它的记录,我们可以这么设置</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># 意思是这个路径下的所有包都不会经过代理服务器了。</span> +<span class="token comment"># 这个命令支持多个路径使用逗号分隔</span> +<span class="token builtin class-name">export</span> GOPRIVATE <span class="token operator">=</span> shgopher.com,shgopher.io,*.api.shgopher.com +</code></pre></div><p>除了设置这个命令之外,还需要设置一个密钥用来 ssh 的方式去访问 GitHub 上的私有仓库,或者是 GitHub --- personal access tokens</p> <p>使用 ssh,将主机公钥 (~/.ssh/id_rsa.pub) 添加到 github.com 的 ssh keys 中。</p> <div class="language-bash extra-class"><pre class="language-bash"><code> <span class="token comment">#我们谈一下如果生成公钥:</span> + <span class="token comment">## 在~/.ssh/ 路径下</span> + ssh-keygen -t rsa -C <span class="token string">"个人邮箱"</span> + <span class="token comment">## 将这个id_rsa.pub中的公钥 添加到GitHub中的ssh keys 中</span> +</code></pre></div><p>如果使用 ssh 的方式获取代码,那么在~/.gitconfig 中添加 (这一步其实就是一个映射:保持你的日常习惯的情况下,使用了 ssh)</p> <div class="language-bash extra-class"><pre class="language-bash"><code> +<span class="token punctuation">[</span>url <span class="token string">"ssh://git@github.com"</span><span class="token punctuation">]</span> + insteadOf <span class="token operator">=</span> https://github.com +</code></pre></div><p>如果是本地服务器那么就是</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token punctuation">[</span>url <span class="token string">"ssh://git@local.com"</span><span class="token punctuation">]</span> + insteadOf <span class="token operator">=</span> https://git.local.com +</code></pre></div><p>不过要注意一下,如果使用 ssh 那么远程的服务就得变更名称,因为通常我们的 GitHub 给我们的都是 https 的方式,使用 ssh 的话就是:</p> <div class="language-bash extra-class"><pre class="language-bash"><code> <span class="token function">git</span> remote set-url origin git@github.com:USERNAME/REPOSITORY.git +</code></pre></div><p>从 ssh 更改为 https 就是</p> <div class="language-go extra-class"><pre class="language-go"><code>git remote set<span class="token operator">-</span>url origin https<span class="token punctuation">:</span><span class="token operator">/</span><span class="token operator">/</span>github<span class="token punctuation">.</span>com<span class="token operator">/</span>USERNAME<span class="token operator">/</span>REPOSITORY<span class="token punctuation">.</span>git +</code></pre></div><p>使用 GitHub personal access token 的方式</p> <div class="language-bash extra-class"><pre class="language-bash"><code><span class="token comment"># 在GitHub personal access tokens中申请即可,然后配置在~/.netrc</span> + +machine github.com login shgopher password 你的 personal access tokens +</code></pre></div><p>在 Linux 中要配置~/.netrc,但在 macOS 中,git 输入的 username 和令牌会自动的缓存,不用设置这个配置文件。</p> <p>更多关于 GitHub 访问的信息可以访问<a href="https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories#switching-remote-urls-from-ssh-to-https" target="_blank" rel="noopener noreferrer">这里<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>我个人建议直接使用 GitHub 的 personal access tokens (仅支持 https) 这种令牌的方式代替密码,并且使用 https 即可,简单,安全,好用, +另外如果你的令牌更新了,假设是 Macos 的情况下,可以去钥匙串访问的互联网密码种类中去更新令牌</p> <p>如果我们引入的包是不支持 https 协议的,那么我们可以设置 <code>GOINSECURE = private.res.com</code> 来使用这种私有库。</p> <p>go 仅仅支持 https 和 http 标准端口的带有域名的包,比如我们使用 ip,或者端口不是 80 和 443,那么设置 GOPROXY 和 GOPRIVATE GOINSECURE 都没用了。</p> <p>比如类似这种:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 这种无法使用</span> +<span class="token keyword">import</span> <span class="token number">192.168</span><span class="token number">.1</span><span class="token number">.1</span><span class="token punctuation">:</span><span class="token number">9090</span><span class="token operator">/</span>test<span class="token operator">/</span>t +</code></pre></div><p>这种直接使用 ip 的方式不能写到 go 的代码中,所以我们可以使用 git 的 insteadof 功能来改变一下,使用一个正常的 url 去改变掉这个 ip</p> <div class="language-go extra-class"><pre class="language-go"><code># ~<span class="token operator">/</span><span class="token punctuation">.</span>gitconfig +<span class="token punctuation">[</span>url <span class="token string">"132.148.1.1:9090/test/t"</span><span class="token punctuation">]</span> + insteadof<span class="token operator">=</span><span class="token string">"shgopher.com/test/t"</span> +</code></pre></div><p>这个时候你引入的时候写 shgopher.com/test/t 就可以了,它会自己找 192.168.1.1:9090/test/t 真实值去代理,并且 shgopher.com/test/t 也要加入到 GOPRIVATE 中才可以。</p> <p>这个时候有个问题,就是如果 shgopher.com 没有配置版本管理软件,例如 git 这种,go 是无法获取数据的,go 一般会存储一些网站,例如 GitHub,gitlab,所以它看到类似 github.com/xxx/的地址就去找使用 git,或者你手动写上 git,比如 shgopher/d/x.git go 也会明白你使用的 git,go 还能发送请求的方式去获取你使用的版本软件,比如 golang.org/x/net go 就会请求 https://golang.org/x/net?go-get=1 这个服务提供了一个 html:</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> +<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>go-import<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>golang/x/net git https://go.googlesource.com/net<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> +<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>go-source<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>golang.org/x/net https://github.com/golang/net<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> +<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> +</code></pre></div><p>这表示这个 golang.org/x/net 的包实际是通过 git 的方式从 https://go.googlesource.com/net 获取的。</p> <p>我们可以让 <code>GET shgopher.com?go-get=1</code> 返回一个 html,在里面设置为 content=“shgopher.com/test/t git 132.148.1.1:9090/test/t”。</p> <p>其实,老老实实的使用 go 推荐的导包方式挺好的,即便是私有包也好好的安排一个 git 版本服务器,仅限内部使用的话,配置好 GOPRIVATE 并且使用 ssh 公钥和私钥或者 GPG 的方式加密获取包,这种才是王道。</p> <p>配置私有的 GOPROXY,你不能总想着靠别人,如果想搭建一个属于自己的 goproxy 服务器,那么可以使用 https://github.com/goproxy/goproxy 这个项目</p> <h3 id="本地开发使用的配置文件-go-work">本地开发使用的配置文件 go.work</h3> <p>go 推出了仅用于本地开发的 workspace,我们来介绍一下这个功能,比如说我们要在一个项目中你引入一个还未公开到公共仓库的包 github.com/shgopher/hui,那么在这个时候就需要 workspace 了。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"github.com/shgopher/hui"</span> +<span class="token punctuation">)</span> +</code></pre></div><p>很显然这个包还未发布,所以不可能引入,在之前通常使用 replace 的方式,但是有了 workspace 以后,不到特定的场景就不需要使用 replace,比如尚未发布的包这种场景用 workspace 最好用 (包的子包不需要任何设置,就可以主包直接引入这个子包了,这一点要搞清楚)。</p> <p>使用 go work init 来创建一个工作区,go.work 形如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//go.work</span> +go1<span class="token punctuation">.</span><span class="token number">19</span> + +<span class="token function">use</span><span class="token punctuation">(</span> + <span class="token punctuation">.</span> <span class="token comment">//go.work当前路径是可以省略的</span> + <span class="token operator">/</span>Users<span class="token operator">/</span>ddd<span class="token operator">/</span>src<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">/</span>hui +<span class="token punctuation">)</span> + +</code></pre></div><p>go.work 可以设置在需要工作区的路径的父路径 (如果父路径没有就会一直忘外寻找直到根路径),工作区中的命令会向外部去寻找 go.work,所以我们通常可以在需要 workspace 的地方的父路行下设置 go.work,并且设置为绝对路径这样简单高效,记住,路径是不包含子路径的,比如本来是/workspace/go1 但是你设置的是/workspace 那么就是错的,它会寻找/workspace 中有没有 go.mod 它以 go.mod 作为寻找对象。当然了一个包的子包 (例如/workspace/go1/a) 无需再写进去 go.work 中,它跟外部的包是一个包。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token function">use</span><span class="token punctuation">(</span> + <span class="token operator">/</span>workspace<span class="token operator">/</span>a + <span class="token operator">/</span>workspace<span class="token operator">/</span>b + <span class="token operator">/</span>workspace<span class="token operator">/</span>c +<span class="token punctuation">)</span> +</code></pre></div><p>在工作区同样可以设置 replace,但是级别没有 go.mod 中的高,会被 go.mod 覆盖。</p> <p>go 的包和包的管理工具 go module 基本上已经讲解完毕了,以后有了新的见解再更新这篇文章。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/blog/get-familiar-with-workspaces</li> <li>https://book.douban.com/subject/35720728/ 图书下册 321 页 - 349 页;图书上册 120 页 - 131 页</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/包及其构建工具/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">12/8/2023, 6:39:03 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/92.61c0947f.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\345\217\215\345\260\204/index.html" "b/\345\267\245\347\250\213/\345\217\215\345\260\204/index.html" new file mode 100644 index 000000000..bc99342eb --- /dev/null +++ "b/\345\267\245\347\250\213/\345\217\215\345\260\204/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/93.eaa3fe92.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="反射包的使用">反射包的使用</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/反射/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">6/9/2023, 1:32:17 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/93.eaa3fe92.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\345\221\275\344\273\244/index.html" "b/\345\267\245\347\250\213/\345\221\275\344\273\244/index.html" new file mode 100644 index 000000000..0615acc35 --- /dev/null +++ "b/\345\267\245\347\250\213/\345\221\275\344\273\244/index.html" @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>命令 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/94.c3c51d69.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>命令</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#gofmt" class="sidebar-link">gofmt</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#goimports" class="sidebar-link">goimports</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-build" class="sidebar-link">go build</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-install" class="sidebar-link">go install</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-get" class="sidebar-link">go get</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-clean" class="sidebar-link">go clean</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-doc-godoc" class="sidebar-link">go doc godoc</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-run" class="sidebar-link">go run</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-test" class="sidebar-link">go test</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-list" class="sidebar-link">go list</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-fix-go-tool-fix" class="sidebar-link">go fix go tool fix</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-vet-go-tool-vet" class="sidebar-link">go vet / go tool vet</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-tool-pprof" class="sidebar-link">go tool pprof</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-tool-cgo" class="sidebar-link">go tool cgo</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E5%91%BD%E4%BB%A4/#go-env" class="sidebar-link">go env</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="命令">命令</h1> <p>go 拥有众多命令操作,这里将讲述关于这些命令的使用方法</p> <p>介绍一下最常见的命令</p> <ul><li>go help 显示一个命令基本的用法,例如:<code>go help fmt</code></li> <li>go doc 显示一个命令全部的用法,例如:<code>go doc cmd/gofmt</code></li></ul> <p>使用 go help 可以显示全部的形如 <code>go fmt</code> <code>go build</code> 这种挂靠在 go 后面的命令,然后 help 加具体的命令,就可以显示基本用法,然后在 help 提示的内容中,通常会有提示你,如果使用 go doc 命令去寻找更加详细的内容,比如下文要写到的,使用 <code>go help fmt</code> 就会显示去寻找 <code>go doc cmd/gofmt</code></p> <h2 id="gofmt">gofmt</h2> <blockquote><p>go fmt 命令简单封装了 gofmt 命令</p></blockquote> <p>gofmt 的目的是标准化 go 语言的代码,增加代码的亲切感,消除不同人员写的代码的之间的隔阂感</p> <p>介绍几个常见的使用方法,详细内容可以使用 <code>go doc cmd/gofmt</code></p> <ul><li><p><code>gofmt -s</code> 简化代码</p> <div class="language-go extra-class"><pre class="language-go"><code>v <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> + <span class="token comment">// 复杂</span> + <span class="token keyword">for</span> <span class="token boolean">_</span> <span class="token operator">=</span> <span class="token keyword">range</span> v <span class="token punctuation">{</span> + + <span class="token punctuation">}</span> + + <span class="token comment">// 使用 -s 后</span> + + <span class="token keyword">for</span> <span class="token keyword">range</span> v <span class="token punctuation">{</span> + + <span class="token punctuation">}</span> +</code></pre></div><p>不过,这个命令虽然会显示出来要优化的简单写法,但是,并不会更改用户的代码,需要自己去更改。</p></li> <li><p><code>gofmt -r</code> 代码重构 replace 能力</p> <p>例子:<code>gofmt -r 'a -> Student'</code> 意思可不是 a 字符改变成 Student,这里是采用的通配符,意思就是所有的英文字符都要改成 student。只要是小写字母都会被视为通配符。再举一个例子,<code>gofmt -r 'a[b:len(a)] -> a[b:]'</code> 这里的 a 代表所有的英文字符串,b 就会代表整数类型</p></li> <li><p><code>gofmt -l</code> 输出不满足 gofmt 要求的文件</p> <p>比如 <code>gofmt -l $GOROOT</code> 就会输出这个路径下不满足的文件列表,可以看出 go 的标准库不满足标准的也不少,😂</p></li></ul> <h2 id="goimports">goimports</h2> <p>安装方法 <code>go get golang.org/x/tools/cmd/goimports</code>,一般的 IDE 都会内置这个工具,比如 goland</p> <ul><li>对于代码中使用了,但是没有 import 的包</li> <li>对于代码中没有使用,但是 import 了的包</li></ul> <p>这个工具都会一一管理,少了加上,多了取消掉</p> <h2 id="go-build">go build</h2> <h2 id="go-install">go install</h2> <h2 id="go-get">go get</h2> <h2 id="go-clean">go clean</h2> <h2 id="go-doc-godoc">go doc godoc</h2> <h2 id="go-run">go run</h2> <h2 id="go-test">go test</h2> <h2 id="go-list">go list</h2> <h2 id="go-fix-go-tool-fix">go fix go tool fix</h2> <h2 id="go-vet-go-tool-vet">go vet / go tool vet</h2> <h2 id="go-tool-pprof">go tool pprof</h2> <h2 id="go-tool-cgo">go tool cgo</h2> <h2 id="go-env">go env</h2></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/命令/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/94.c3c51d69.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\345\235\221/index.html" "b/\345\267\245\347\250\213/\345\235\221/index.html" new file mode 100644 index 000000000..063eeddea --- /dev/null +++ "b/\345\267\245\347\250\213/\345\235\221/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>坑 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/95.d1eac759.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>坑</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="坑">坑</h1> <p>这里记录 go 语言开发过程中,非常容易出现错误的地方。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/坑/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/95.d1eac759.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\345\255\227\347\254\246\347\274\226\347\240\201/index.html" "b/\345\267\245\347\250\213/\345\255\227\347\254\246\347\274\226\347\240\201/index.html" new file mode 100644 index 000000000..6675ddd3b --- /dev/null +++ "b/\345\267\245\347\250\213/\345\255\227\347\254\246\347\274\226\347\240\201/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>字符编码 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/96.add14987.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>字符编码</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="字符编码">字符编码</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/字符编码/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">12/19/2022, 11:14:51 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/96.add14987.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\346\265\213\350\257\225/index.html" "b/\345\267\245\347\250\213/\346\265\213\350\257\225/index.html" new file mode 100644 index 000000000..d0aa3dbc4 --- /dev/null +++ "b/\345\267\245\347\250\213/\346\265\213\350\257\225/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 中的测试 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/97.357d16bb.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 中的测试</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/#testing-包" class="sidebar-link">testing 包</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/#testing-fstest-包" class="sidebar-link">testing/fstest 包</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/#testing-iotest-包" class="sidebar-link">testing/iotest 包</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/#testing-quick-包" class="sidebar-link">testing/quick 包</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/#net-http-test" class="sidebar-link">net/http/test</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-中的测试">go 中的测试</h1> <p>go 中的测试一共分为如下类型</p> <ul><li>测试的主要注意事项</li></ul> <h2 id="testing-包">testing 包</h2> <ul><li>基础测试</li> <li><a href="/GOFamily/工程/测试/基准测试.html">基准 (性能) 测试</a></li> <li>例子测试</li> <li>子测试/子基准测试</li> <li>main 函数测试</li> <li><a href="/GOFamily/工程/测试/模糊测试.html">模糊 (fuzzing) 测试</a></li> <li>mock</li></ul> <h2 id="testing-fstest-包">testing/fstest 包</h2> <ul><li>文件系统的测试</li></ul> <h2 id="testing-iotest-包">testing/iotest 包</h2> <ul><li>io 系统的测试</li></ul> <h2 id="testing-quick-包">testing/quick 包</h2> <ul><li>黑箱辅助测试</li></ul> <h2 id="net-http-test">net/http/test</h2> <ul><li>http 客户端测试</li> <li>http 服务端测试</li></ul> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/41ux7cA-GXYTfeS5juP3wA</li> <li>https://github.com/golang/mock</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/测试/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/97.357d16bb.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\345\207\206\346\265\213\350\257\225.html" "b/\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\345\207\206\346\265\213\350\257\225.html" new file mode 100644 index 000000000..ff036f2b9 --- /dev/null +++ "b/\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\345\207\206\346\265\213\350\257\225.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>基准测试 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/98.fe5446fa.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>基准测试</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html#hey" class="sidebar-link">hey</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html#ethr" class="sidebar-link">ethr</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="基准测试">基准测试</h1> <h2 id="hey">hey</h2> <h2 id="ethr">ethr</h2> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/kKNSKdPoeAWUXbwC_tFINw</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/测试/基准测试.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/98.fe5446fa.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\347\241\200\346\265\213\350\257\225.html" "b/\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\347\241\200\346\265\213\350\257\225.html" new file mode 100644 index 000000000..c0e76d834 --- /dev/null +++ "b/\345\267\245\347\250\213/\346\265\213\350\257\225/\345\237\272\347\241\200\346\265\213\350\257\225.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>基础测试 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/99.c9fd11f7.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>基础测试</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="基础测试">基础测试</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://www.alexedwards.net/blog/easy-test-assertions-with-go-generics</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/测试/基础测试.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/99.c9fd11f7.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\346\265\213\350\257\225/\346\250\241\347\263\212\346\265\213\350\257\225.html" "b/\345\267\245\347\250\213/\346\265\213\350\257\225/\346\250\241\347\263\212\346\265\213\350\257\225.html" new file mode 100644 index 000000000..83eae5b7c --- /dev/null +++ "b/\345\267\245\347\250\213/\346\265\213\350\257\225/\346\250\241\347\263\212\346\265\213\350\257\225.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>模糊测试 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/100.049dca94.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>模糊测试</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B7%A5%E7%A8%8B/%E6%B5%8B%E8%AF%95/%E6%A8%A1%E7%B3%8A%E6%B5%8B%E8%AF%95.html#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="模糊测试">模糊测试</h1> <h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/doc/tutorial/fuzz</li> <li>https://mp.weixin.qq.com/s/kR8pCyjpYz_9ax6P7LyB2w</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/测试/模糊测试.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">5/24/2022, 6:13:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/100.049dca94.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\347\263\273\347\273\237\344\277\241\345\217\267\347\232\204\345\244\204\347\220\206/index.html" "b/\345\267\245\347\250\213/\347\263\273\347\273\237\344\277\241\345\217\267\347\232\204\345\244\204\347\220\206/index.html" new file mode 100644 index 000000000..135413640 --- /dev/null +++ "b/\345\267\245\347\250\213/\347\263\273\347\273\237\344\277\241\345\217\267\347\232\204\345\244\204\347\220\206/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>系统信号的处理 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/101.9e4a3cce.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>系统信号的处理</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="系统信号的处理">系统信号的处理</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/系统信号的处理/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/29/2022, 1:05:58 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/101.9e4a3cce.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\350\257\273\345\206\231\346\250\241\345\236\213/index.html" "b/\345\267\245\347\250\213/\350\257\273\345\206\231\346\250\241\345\236\213/index.html" new file mode 100644 index 000000000..30631f124 --- /dev/null +++ "b/\345\267\245\347\250\213/\350\257\273\345\206\231\346\250\241\345\236\213/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 语言的读写模型 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/102.60455322.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 语言的读写模型</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-语言的读写模型">go 语言的读写模型</h1></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/读写模型/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/102.60455322.js" defer></script> + </body> +</html> diff --git "a/\345\267\245\347\250\213/\351\241\271\347\233\256\347\273\204\347\273\207\345\275\242\345\274\217/index.html" "b/\345\267\245\347\250\213/\351\241\271\347\233\256\347\273\204\347\273\207\345\275\242\345\274\217/index.html" new file mode 100644 index 000000000..9099fac3b --- /dev/null +++ "b/\345\267\245\347\250\213/\351\241\271\347\233\256\347\273\204\347\273\207\345\275\242\345\274\217/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>go 项目组织形式 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/10.993cf521.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>go 项目组织形式</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-项目组织形式">go 项目组织形式</h1> <p><img src="/GOFamily/assets/img/a.732405d8.png" alt=""></p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/工程/项目组织形式/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/16/2023, 6:44:02 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/10.993cf521.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/atomic/index.html" "b/\345\271\266\345\217\221/atomic/index.html" new file mode 100644 index 000000000..3c6db675c --- /dev/null +++ "b/\345\271\266\345\217\221/atomic/index.html" @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/104.dcbef6d1.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/atomic/#介绍一下-atomic-的内容" class="sidebar-link">介绍一下 atomic 的内容</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/atomic/#基于原子库的第三方扩展" class="sidebar-link">基于原子库的第三方扩展</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/atomic/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/atomic/#对一个地址的赋值是原子操作吗" class="sidebar-link">对一个地址的赋值是原子操作吗?</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/atomic/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="atomic">atomic</h1> <p>原子包是比互斥锁更底层的包,如果在简单的场景下,使用 sync.Mutex 可能会比较复杂,并且耗费资源,那么使用更加底层的 atomic 就更加划算了</p> <p>所谓原子操作,就是当某 goroutine 去执行原子操作时,其它 goroutine 只能看着,这个操作要么成功,要么失败,不会有第三个状态</p> <p>原子包操作对象的时候,都是操作的地址,所以谨记不要使用值操作而是要指针操作</p> <h2 id="介绍一下-atomic-的内容">介绍一下 atomic 的内容</h2> <ul><li>Add:例如 <code>func AddInt32(addr *int32,delta int32)(new int32)</code> 给第一个参数地址指向的数据值增加一个 delta 并返回新的数据</li> <li>CompareAndSwap:例如 <code>func CompareAndSwapInt32(addr *int32,old,new int32)(swapped bool)</code> 比较 addr 指向的数据是否等于 old,如果不等于返回 false,如果等于就将此地址的值切换为 new 值,并且返回 true</li> <li>Load:例如 <code>func LoadInt32(addr *int32)(val int32)</code> 读取 addr 指向的值并返回</li> <li>Store:例如 <code>func StoreInt32(addr *int32,val int32)</code> 将 val 值写入到 addr 指向的内存空间中</li> <li>Swap:例如 <code>func SwapInt32(addr *int32,new int32)(old int32)</code> 将 addr 指向的值切换为 new 值,并返回旧值</li> <li>Value:<code>type Value</code> <code>func(*Value) Load</code> <code>func(*Value) Store</code> 原子的存取数据</li></ul> <p>目前 atomic 还没有部署泛型,所以里面到处充斥者 <code>LoadInt32</code> <code>LoadInt64</code> 这种类型的函数,以后等泛型部署到原子包后就不会这么繁琐了</p> <h2 id="基于原子库的第三方扩展">基于原子库的第三方扩展</h2> <ul><li><p>uber-go/atomic 定义扩展了几种常见类型的原子操作,例如 bool error string 等</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> atom atomic<span class="token punctuation">.</span>Uint32 +atom<span class="token punctuation">.</span><span class="token function">Store</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span> +atom<span class="token punctuation">.</span><span class="token function">Sub</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> +atom<span class="token punctuation">.</span><span class="token function">CompareAndSwap</span><span class="token punctuation">(</span><span class="token number">40</span><span class="token punctuation">,</span> <span class="token number">11</span><span class="token punctuation">)</span> +</code></pre></div><p>看起来的确比官方提供的原子包更加简洁一些</p></li></ul> <h2 id="issues">issues</h2> <h3 id="对一个地址的赋值是原子操作吗">对一个地址的赋值是原子操作吗?</h3> <p>如果对于单核处理器的机器来说,地址的赋值是原子操作</p> <p>在现在的系统中,write 的地址基本上都是对齐的</p> <p>对齐地址的写,不会导致其他人看到只写了一半的数据,因为它通过一个指令就可以实现对地址的操作,如果地址不是对齐的话,那么,处理器就需要分成两个指令去处理,如果执行了一个指令,其它人就会看到更新了一半的错误的数据,这被称做撕裂写</p> <p>所以,你可以认为赋值操作是一个原子操作</p> <p>但是,对于现代的多处理多核的系统来说,由于 cache、指令重排,可见性等问题,我们 +对原子操作的意义有了更多的追求。</p> <p><em><strong>在多核系统中,一个核对地址的值的更改,在更新到主内存中之前,是在多级缓存中存放的。这时,多个核看到的数据可能是不一样的</strong></em></p> <p>多处理器多核心系统为了处理这类问题,使用了一种叫做内存屏障 (memory fence 或 +memory barrier) 的方式。一个写内存屏障会告诉处理器,必须要等到它管道中的未完成 +的操作 (特别是写操作) 都被刷新到内存中,再进行操作。</p> <p>atomic 包提供的方法会提供了一些的功能,不仅仅可以保证赋值的数据完整性,还能保证数据的可见性,一旦一个核更新了该地址的值,其它处理器总是能读取到它的最新值。</p> <p>atomic 包主要利用了以下几点技术:</p> <ul><li><p>编译器插入内存屏障 (Memory Barrier) 指令 +编译器会在 atomic 操作前后插入内存屏障指令,来限制 CPU 的乱序执行,保证在该操作前的读写操作都完成,之后的读写都待其完成后再执行。</p></li> <li><p>硬件支持的原子 CPU 指令 +如 X86 的 LOCK 指令可以将某些指令变为原子指令。atomic 会利用 CPU 提供的这些原子指令实现加锁。</p></li> <li><p>缓存一致性硬件协议 +如 Intel 的 MESI 协议可以在多核间保证缓存的一致性。atomic 利用缓存一致性,使得多个核心缓存中的数据版本是一致的。</p></li> <li><p>核心间互斥 +atomic 中的原子操作会在多核间加锁,保证同时只有一个核心可以操作共享变量。</p></li></ul> <p>需要注意的是,因为需要处理器之间保证数据的一致性,atomic 的操作是会降低性能的。</p> <p>综上所述,<em><strong>对于单核机器来说,普通的地址赋值就是原子操作,但是对于多核机器来说,不属于原子操作,原子包去进行的赋值一定是原子操作</strong></em></p> <h2 id="参考资料">参考资料</h2> <ul><li>go.dev</li> <li>https://time.geekbang.org/column/intro/100061801</li> <li>《go 进阶训练营》</li> <li>《go 语言精进之路》</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/atomic/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/5/2024, 2:48:04 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/104.dcbef6d1.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/channel/index.html" "b/\345\271\266\345\217\221/channel/index.html" new file mode 100644 index 000000000..a7181249a --- /dev/null +++ "b/\345\271\266\345\217\221/channel/index.html" @@ -0,0 +1,922 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>channel | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/105.76803baf.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>channel</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#基础用法" class="sidebar-link">基础用法</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#创建-channel" class="sidebar-link">创建 channel</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channel-分为三种类型" class="sidebar-link">channel 分为三种类型</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#发送数据" class="sidebar-link">发送数据</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#接收数据" class="sidebar-link">接收数据</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#关闭-channel" class="sidebar-link">关闭 channel</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#判断从-channel-中取出的值是否有效" class="sidebar-link">判断从 channel 中取出的值是否有效</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#range-channel" class="sidebar-link">range channel</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#其它操作-len-cap" class="sidebar-link">其它操作:len cap</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#不同状态-channel-的总结" class="sidebar-link">不同状态 channel 的总结</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#select" class="sidebar-link">select</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#对于-select-for-和-time-sleep-的阻塞机制的理解" class="sidebar-link">对于 select for 和 time.Sleep 的阻塞机制的理解</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#定时器" class="sidebar-link">定时器</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#cron-规则定时任务框架-robfig-cron" class="sidebar-link">cron 规则定时任务框架 robfig/cron</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#使用反射执行未知数量的-channel" class="sidebar-link">使用反射执行未知数量的 channel</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#数据交流-生产者-消费者模式" class="sidebar-link">数据交流---生产者/消费者模式</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#传递信号-通知" class="sidebar-link">传递信号/通知</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#收发同时进行的信号" class="sidebar-link">收发同时进行的信号</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#使用计时器去解决长等待问题" class="sidebar-link">使用计时器去解决长等待问题</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#信号传递之-or-do-模式" class="sidebar-link">信号传递之 or-do 模式</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#锁" class="sidebar-link">锁</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#任务编排" class="sidebar-link">任务编排</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#fan-in" class="sidebar-link">fan-in</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#fan-out" class="sidebar-link">fan-out</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#map-reduce" class="sidebar-link">map-reduce</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#pipeline-流水线模式" class="sidebar-link">pipeline-流水线模式</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#stream-流模式" class="sidebar-link">stream-流模式</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#pipeline-流水线模式和-stream-流模式的对比" class="sidebar-link">pipeline 流水线模式和 stream 流模式的对比</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channel-注意事项" class="sidebar-link">channel 注意事项</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#goroutine-泄露" class="sidebar-link">goroutine 泄露</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channel-的实现原理" class="sidebar-link">channel 的实现原理</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#创建" class="sidebar-link">创建</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#send" class="sidebar-link">send</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#recive" class="sidebar-link">recive</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#close" class="sidebar-link">close</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channel-是并发银弹吗" class="sidebar-link">channel 是并发银弹吗?</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#有无-buffer-的-channel-区别" class="sidebar-link">有无 buffer 的 channel 区别</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channel-close-后-read-write-close-的区别" class="sidebar-link">channel close 后,read write close 的区别</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channle-底层是什么" class="sidebar-link">channle 底层是什么</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#channle-和运行时调度如何交互" class="sidebar-link">channle 和运行时调度如何交互</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#编程题-使用三个-goroutine-打印-abc-100-次" class="sidebar-link">编程题,使用三个 goroutine 打印 abc 100 次</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/channel/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="channel">channel</h1> <p>channel 是 csp 并发模型中的重要组成部分,它完成的使命是 goroutine 之间的通信。也就是 csp 中的 c。</p> <p>channel 是 go 语言语言级的线程安全的通信组件,它是 go 语言的一个内置类型,也因此 go 语言才被称之为在设计之初就考虑了并发的语言。</p> <p>go 语言之父 rob pike 曾说到 “不要使用共享内存的方式去通信,而是通过通信的方式去共享内存” 这句话就是形容的 channel,这句话的意思是说,我们正在执行的程序不应该通过共享内存的方式去完成这个并发操作,各个线程应该各自运行,互不干涉,使用通信的方式去交流去分享内存信息即可。</p> <h2 id="基础用法">基础用法</h2> <h3 id="创建-channel">创建 channel</h3> <p>channel 是一个引用类型,所以创建一个 channel 必须划定底层内存给 channel,所以需要使用 make,不使用 make 只用来声明的 channel,其初始值就是 nil,这一点跟其它引用类型,例如接口,切片,map 是一致的。</p> <p>对于 nil 的 channel,发送和接收数据总是会阻塞的,对于 nil 的 channel,关闭它直接会 panic <code>panic: close of nil channel</code></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 创建一个无缓存channel</span> +ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> +<span class="token comment">// 创建一个有缓存的channel</span> +ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> +</code></pre></div><p>一个无缓存的 channel,只有接收了数据,才能发送下一个数据往通道中,一个有缓存的数据,比如这里是 10,那么可以往这个 channel 中发送 10 个数据,并且不需要接收,只有发送第十一个数据的时候才会发送阻塞。</p> <blockquote><p>关于 channel 的多线程规则,请参考<a href="../%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B">内存模型</a>这一章节</p></blockquote> <h3 id="channel-分为三种类型">channel 分为三种类型</h3> <ul><li>只能发送的 channel <code>chan<-</code></li> <li>只能接收的 channel <code><-chan</code></li> <li>可发可收的 channel <code>chan</code></li></ul> <p>channel 里面理论上可以存在任意的类型数据,当然也包括 channel 自己,那么当 channel 中出现了很多符号时该如何区分呢?</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">chan</span><span class="token operator"><-</span> <span class="token keyword">chan</span> <span class="token builtin">int</span> +</code></pre></div><p>这里有个规则,符号总是跟左侧的 chan 在一起表示含义,比如这里,就是一个只能发送的 channel,里面保存的是一个 int 类型的 channel</p> <p>我们知道,channel 可以拥有三种不同的类型,能发能收的 channel 是满足前两者的,也就是说,当你声明的是一个只能接收的 channel,你可以传入一个能收能发的 channel,但当你声明的是一个能收也能发的 channel 时,就不能传递进去一个只能发或者只能收的 channel</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> + <span class="token function">age</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>c <span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// ❌ </span> +<span class="token comment">// cannot use c (variable of type <-chan int) as chan int value in argument to age</span> + +<span class="token keyword">package</span> main + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> + <span class="token function">age</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>c <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +</code></pre></div><p>所以,通常我们实际使用当中都是这样的场景,某个函数中的参数是一个只读或者只发的一个 channel 类型,我们传递进去的是一个能收能发的 channel。</p> <p>因为我们在函数的参数中这么设置是为了避免使用中出现 bug,比如某个函数它就只能收数据,所以给定它的是一个只能收的 channel 非常合理,但是为什么我们创建时要创建一个能收也能发的 channel 呢?因为这个 channel 必定要在其它的 goroutine 中被发送数据,这个其它 goroutine 参数可能被设置为只能发送。</p> <p>总结一下,设置只能发或者只能收的 channel 本质上只是为了限制函数的能力是为了避免不必要的 bug,但是 channel 的本质我们还是要清楚的:在不同的 goroutine 之间传递信息</p> <p>同时,除了上面这个禁忌之外,<strong>只能收</strong>的 channel 不能 close,一旦 close 就会 panic,不过只能发的 channel 倒是可以 close 这个操作</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//❌</span> +<span class="token comment">// invalid operation: cannot close receive-only channel c (variable of type <-chan int)</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">//❌ </span> +<span class="token comment">//invalid operation: cannot close receive-only channel c (variable of type <-chan int)</span> +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>c <span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// ✅</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span><span class="token operator"><-</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token comment">//✅</span> +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>c <span class="token keyword">chan</span><span class="token operator"><-</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="发送数据">发送数据</h3> <div class="language-go extra-class"><pre class="language-go"><code>ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> +ch <span class="token operator"><-</span> <span class="token number">12</span> +</code></pre></div><h3 id="接收数据">接收数据</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span>ch <span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 接收但舍弃数值</span> + <span class="token comment">// <- ch</span> + + <span class="token comment">// 接收并赋值</span> + c <span class="token operator">:=</span> <span class="token operator"><-</span> ch + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="关闭-channel">关闭 channel</h3> <div class="language-go extra-class"><pre class="language-go"><code>ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> +<span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> +</code></pre></div><h3 id="判断从-channel-中取出的值是否有效">判断从 channel 中取出的值是否有效</h3> <div class="language-go extra-class"><pre class="language-go"><code>v<span class="token punctuation">,</span>ok <span class="token operator">:=</span> <span class="token operator"><-</span>ch + +<span class="token keyword">if</span> ok <span class="token punctuation">{</span> + <span class="token comment">// 是有效值</span> +<span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span> + <span class="token comment">//是零值</span> +<span class="token punctuation">}</span> +</code></pre></div><p>ok 的值表示的是 “接收是否会成功”,而不是 channel 是否已关闭</p> <p>当 channel 已关闭且数据已取完,再接收时 ok 会为 false,表示 “接收不会成功”</p> <p>不过值得注意的是,即使 channel 已经关闭,如果之前 channel 中还有数据未被消费,那么数据也能被正常的读取:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"fmt"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> + + <span class="token comment">// 向channel发送3个数据</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator"><-</span> <span class="token number">1</span> + ch <span class="token operator"><-</span> <span class="token number">2</span> + ch <span class="token operator"><-</span> <span class="token number">3</span> + <span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"已经关闭了channel,并且没有取值"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">2</span><span class="token punctuation">)</span> + <span class="token comment">// channel中还有未消费的数据,可以正常读取</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator"><-</span>ch<span class="token punctuation">)</span> <span class="token comment">// 1</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator"><-</span>ch<span class="token punctuation">)</span> <span class="token comment">// 2</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator"><-</span>ch<span class="token punctuation">)</span> <span class="token comment">// 3</span> + <span class="token comment">// channel数据已取完,此时会立即得到零值</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token operator"><-</span>ch<span class="token punctuation">)</span> <span class="token comment">// 0</span> + <span class="token comment">// 再次关闭channel会panic</span> + <span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="range-channel">range channel</h3> <div class="language-go extra-class"><pre class="language-go"><code>ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> +<span class="token keyword">for</span> value <span class="token operator">:=</span> <span class="token keyword">range</span> ch<span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>值得注意的是,一个 channel 如果没有被关闭,那么 range 操作将会一直阻塞,所以通常我们都会关闭这个 channel,好让程序继续执行</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + wg1<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">32</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg2<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> b <span class="token punctuation">{</span> + <span class="token comment">//</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span> +</code></pre></div><p>注意看,这个关闭的操作其实是另起了一个 goroutine,因为你为了 waitgroup 的完全执行完毕,所以使用新的 goroutine 去关闭 channel 的操作是比较常见的做法,你可以参考这个<a href="https://github.com/shgopher/collie" target="_blank" rel="noopener noreferrer">项目<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h3 id="其它操作-len-cap">其它操作:len cap</h3> <div class="language-go extra-class"><pre class="language-go"><code>ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> + +<span class="token comment">// 获取channel中缓存的中还未被取走的元素数量</span> +fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">len</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span><span class="token punctuation">)</span> + +<span class="token comment">// 获取channel的容量</span> +fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">cap</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span><span class="token punctuation">)</span> +</code></pre></div><h3 id="不同状态-channel-的总结">不同状态 channel 的总结</h3> <table><thead><tr><th style="text-align:center;">状态</th> <th style="text-align:center;">发送数据</th> <th style="text-align:center;">接收数据</th> <th style="text-align:center;">关闭chan</th></tr></thead> <tbody><tr><td style="text-align:center;">正常</td> <td style="text-align:center;">正常</td> <td style="text-align:center;">正常</td> <td style="text-align:center;">正常</td></tr> <tr><td style="text-align:center;">nil</td> <td style="text-align:center;">阻塞</td> <td style="text-align:center;">阻塞</td> <td style="text-align:center;">panic</td></tr> <tr><td style="text-align:center;">closed</td> <td style="text-align:center;">panic</td> <td style="text-align:center;">正常值+零值</td> <td style="text-align:center;">panic</td></tr></tbody></table> <p>对于正常的 channel,如果它没有缓存,那么读写都会发生阻塞,除非另一方准备好,对于有 buffer 的 channel,当它还有缓存的时候,随意发送数据,这个时候收可以不准备好,当他满了,其实跟没有 buffer 的是一样的,这里就不过多讨论了,可以去查看<a href="/GOFamily/并发/内存模型/">内存模型</a>那一章</p> <h2 id="select">select</h2> <p>select 是 go 语言提供的,供 channel 去操作的一个组件,它的基本使用方法如下</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> ch <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> + <span class="token keyword">var</span> ch1 <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> + <span class="token keyword">var</span> ch2 <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i<span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ch<span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ch被关闭了"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> ch1<span class="token operator"><-</span> i<span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ch1 发送成功"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> v<span class="token punctuation">,</span>ok <span class="token operator">:=</span> <span class="token operator"><-</span> ch2<span class="token punctuation">:</span> + <span class="token keyword">if</span> ok <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ch2 接收到值"</span><span class="token punctuation">,</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ch没有被关闭"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>首先,select 的 case 中只能存放 channel 的收和发,以及一个 default 分支,各个分支如果在相同时间满足了条件是会随机去走分支的,不存在先后顺序,在 select 中也是可以去做判断的,判断 channel 是否存在正常值</p> <p>select 本身不具有循环性质,所以通常被配合 for 循环使用</p> <p>select 在没有任何 case 的时候会陷入阻塞,我们如果希望有一个阻塞存在,使用 select 是极好的:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> +<span class="token comment">//...</span> +<span class="token keyword">select</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + + +</code></pre></div><h3 id="对于-select-for-和-time-sleep-的阻塞机制的理解">对于 select for 和 time.Sleep 的阻塞机制的理解</h3> <p><em><strong>1。使用 for 循环不会造成 cpu 的执行吗?还是说 cpu 陷入了休眠状态,time.Sleep 呢?</strong></em></p> <p>使用 <code>for{}</code> 循环会导致 CPU 高速空转。</p> <p>for 循环本质上是一个忙等待/空转,CPU 会一直执行循环体内容,只不过这里的循环体为空,所以 CPU 会一直空转浪费资源。</p> <p>相比而言,time.Sleep() 会<strong>让出 CPU 时间片</strong>,把 goroutine 暂停一段时间,在这段时间 CPU 可以去执行其他任务。当 sleep 时间结束,goroutine 会重新得到时间片继续执行。</p> <p>所以从资源利用效率来说,time.Sleep() 明显优于 for 循环的空转方式。</p> <p><em><strong>2。那么 select {} 呢是高速空转还是让出资源呢?</strong></em></p> <p>当 select 里所有的 case 都不 ready 时,它会释放 CPU 时间片,使当前 goroutine 进入阻塞状态,这就避免了空转。</p> <p><em><strong>3。select 的不同 case,在等待 case ready 的时候,select 是靠调度器去看 case 是否 ready 还是不停的轮询呢?</strong></em></p> <p>select 内部实现了更精密的监听逻辑:</p> <ul><li>为每个 case 的 channel 设置监听器</li> <li>当前 goroutine 阻塞时释放 CPU 执行权</li> <li>监听器异步监控 channel 状态</li> <li>有 channel ready 则唤醒 goroutine</li></ul> <p>所以 select 不是通过忙碌的轮询来判断 channel ready,而是通过异步监听的方式,只在必要的时刻唤醒 goroutine。</p> <p>这种方式可以极大地减少 CPU 的占用,效率也更高。</p> <p>综上所述,如果你想设置一个阻塞时,使用一个没有 case 的 select 是比一个空 for 循环更好的方法,如果你想设置一个有时间的阻塞时,使用 time.Sleep 无疑是更好的选择,不过这里需要注意的是 time.Sleep 的精度并不高,特别高精度的阻塞不要使用这个函数,select 设计非常精妙,在等待 case 的时候并不会大量耗费 cpu 的执行时间,而是让出 cpu 的执行片段,设置监听,异步的去获取状态,所以 select 的性能是非常不错的</p> <h2 id="定时器">定时器</h2> <p>在 go 语言中,go 提供了定时器给用户,基本的使用方法如下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token comment">// 在一秒后给case发送信息</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> + <span class="token comment">// 心跳信号,每间隔一秒发送一次信息</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">Tick</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>通常来说,这是为了超时而去设置的跳出机制</p> <h3 id="cron-规则定时任务框架-robfig-cron">cron 规则定时任务框架 robfig/cron</h3> <p>robfig/cron 是一个 Go 语言编写的 Cron 计划任务管理器。</p> <p>这个项目的主要功能和特点包括:</p> <ul><li>实现了 cron 规范,可以基于 cron 表达式来调度任务</li> <li>支持在代码中以声明式方式定义定时任务</li> <li>支持在配置文件中定义定时任务</li> <li>支持任务链,一个任务可以触发其他任务</li> <li>支持任务锁,防止并发执行</li> <li>支持失败重试</li> <li>有默认的日志记录器,也可以自定义日志记录器</li> <li>轻量级,没有外部依赖</li></ul> <p>robfig/cron 因为其简单、轻量和高效而被许多 Go 项目用来实现定时任务。它可以用于项目中不同粒度的调度需求,如每分钟执行、每小时执行等。</p> <p>下面解释一下 cron 机制的含义:</p> <p>cron 表达式调度是 cron 作业调度程序的核心机制。</p> <p>cron 表达式是一个字符串,由 5 或 6 个用空格分隔的字段组成,每个字段表示一个时间单位。Cron 会根据表达式中设置的值,在特定的时间点触发相应的任务。</p> <p>cron 表达式的字段与意义如下:</p> <div class="language-go extra-class"><pre class="language-go"><code># 文件格式說明 +# ┌──分钟(<span class="token number">0</span> <span class="token operator">-</span> <span class="token number">59</span>) +# │ ┌──小时(<span class="token number">0</span> <span class="token operator">-</span> <span class="token number">23</span>) +# │ │ ┌──日(<span class="token number">1</span> <span class="token operator">-</span> <span class="token number">31</span>) +# │ │ │ ┌─月(<span class="token number">1</span> <span class="token operator">-</span> <span class="token number">12</span>) +# │ │ │ │ ┌─星期(<span class="token number">0</span> <span class="token operator">-</span> <span class="token number">6</span>,表示从周日到周六) +# │ │ │ │ │ ┌─年份( <span class="token operator">*</span> 表示全部年份,<span class="token number">2024</span> 表示只在<span class="token number">2024</span>年) +# │ │ │ │ │ │ +# <span class="token operator">*</span> <span class="token operator">*</span> <span class="token operator">*</span> <span class="token operator">*</span> <span class="token operator">*</span> <span class="token operator">*</span> + +# 例如 +# <span class="token number">0</span> <span class="token number">0</span> <span class="token number">12</span> <span class="token operator">*</span> <span class="token operator">*</span> <span class="token operator">*</span> +# 每天 <span class="token number">12</span> 点触发 +</code></pre></div><p>每个字段可以使用特殊字符表示多种时间设置:</p> <ul><li><code>*</code>:表示匹配该字段的任意值</li> <li><code>,</code>:表示分隔多个值,如在分钟字段使用 “5,15,25” 就表示5分、15分、25分都触发</li> <li><code>-</code>:表示一个范围,如在小时字段使用 “9-17” 表示 9 点到 17 点之间每个整点都触发</li> <li><code>/</code>:表示一个间隔,如在分钟字段使用 “0/15” 表示每15分钟触发一次,从0分开始</li> <li><code>?</code>:表示不指定的值,会匹配该字段的任意值。</li></ul> <p>一些例子:</p> <ul><li><code>0 0 12 * * ?</code>:每天 12 点触发</li> <li><code>0 15 10 ? * *</code>:每天 10:15 触发</li> <li><code>0 0/5 14 * * ?</code>:每天 14:00 到 14:55 每5分钟触发一次</li> <li><code>0 0/5 14,18 * * ?</code>:每天 14:00 到 14:55 和 18:00 到 18:55 每5分钟触发一次</li></ul> <p>通过这种表达式,cron 可以非常灵活地设置触发时间表,从而实现各种调度需求。</p> <p>下面给出这个项目的 demo:</p> <div class="language-go extra-class"><pre class="language-go"><code>c <span class="token operator">:=</span> cron<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token comment">// 每小时的第30分钟执行</span> +c<span class="token punctuation">.</span><span class="token function">AddFunc</span><span class="token punctuation">(</span><span class="token string">"30 * * * *"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"每小时的第30分钟"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +<span class="token comment">// 在每天早上3点到6点,晚上8点到11点的范围内,每小时执行一次 </span> +c<span class="token punctuation">.</span><span class="token function">AddFunc</span><span class="token punctuation">(</span><span class="token string">"30 3-6,20-23 * * *"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"在每天早上3点到6点,晚上8点到11点的范围内,每小时执行一次"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +<span class="token comment">// 每天早上东京时间4点30分执行一次</span> +c<span class="token punctuation">.</span><span class="token function">AddFunc</span><span class="token punctuation">(</span><span class="token string">"CRON_TZ=Asia/Tokyo 30 04 * * *"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"每天早上东京时间4点30分执行一次"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +<span class="token comment">// 从现在起每小时执行一次</span> +c<span class="token punctuation">.</span><span class="token function">AddFunc</span><span class="token punctuation">(</span><span class="token string">"@hourly"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"从现在起每小时执行一次"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +<span class="token comment">// 从现在起每隔1小时30分执行一次 </span> +c<span class="token punctuation">.</span><span class="token function">AddFunc</span><span class="token punctuation">(</span><span class="token string">"@every 1h30m"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"从现在起每隔1小时30分执行一次"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +c<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token comment">// 被添加的函数会在自己的goroutine中异步执行</span> +<span class="token operator">...</span> + +<span class="token comment">// 也可以向已经启动的Cron添加新的函数</span> +c<span class="token punctuation">.</span><span class="token function">AddFunc</span><span class="token punctuation">(</span><span class="token string">"@daily"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"每天执行"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +<span class="token comment">// 检查cron任务下次和上次的执行时间</span> +<span class="token function">inspect</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span><span class="token function">Entries</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + +<span class="token comment">// 停止调度器(已经启动的任务不会被停止)</span> +c<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +</code></pre></div><h2 id="使用反射执行未知数量的-channel">使用反射执行未知数量的 channel</h2> <p>当你不确定需要多少个 channel 去处理时,你只能选择在运行时去创建未知数量的 channel,这个时候就要使用反射了。</p> <p>我们使用 <code>reflect.Select(cases []reflect.SelectCase)(chosen int,recv reflect.Value,recvok bool)</code> 去实现 select</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"reflect"</span> +<span class="token punctuation">)</span> + +<span class="token comment">// 使用反射创建的select</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch1 <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> + ch2 <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> + + <span class="token keyword">var</span> cases <span class="token operator">=</span> <span class="token function">createSelectCase</span><span class="token punctuation">(</span>ch1<span class="token punctuation">,</span> ch2<span class="token punctuation">)</span> + + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token comment">// chosen:channel 切片的索引</span> + <span class="token comment">// recv:收到的值</span> + <span class="token comment">// ok:是否是通道上发送的值(而不是因为通道关闭而接收到的零值)</span> + <span class="token comment">// Select最多支持 65536 个channel</span> + chosen<span class="token punctuation">,</span> recv<span class="token punctuation">,</span> ok <span class="token operator">:=</span> reflect<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>cases<span class="token punctuation">)</span> + + <span class="token keyword">if</span> recv<span class="token punctuation">.</span><span class="token function">IsValid</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 收</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"recv:"</span><span class="token punctuation">,</span> cases<span class="token punctuation">[</span>chosen<span class="token punctuation">]</span><span class="token punctuation">.</span>Dir<span class="token punctuation">,</span> recv<span class="token punctuation">,</span> ok<span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">// 发</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"send:"</span><span class="token punctuation">,</span> cases<span class="token punctuation">[</span>chosen<span class="token punctuation">]</span><span class="token punctuation">.</span>Dir<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">createSelectCase</span><span class="token punctuation">(</span>chs <span class="token operator">...</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>reflect<span class="token punctuation">.</span>SelectCase <span class="token punctuation">{</span> + <span class="token keyword">var</span> cases <span class="token punctuation">[</span><span class="token punctuation">]</span>reflect<span class="token punctuation">.</span>SelectCase + + <span class="token comment">// 创建 收 channel</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> ch <span class="token operator">:=</span> <span class="token keyword">range</span> chs <span class="token punctuation">{</span> + cases <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>cases<span class="token punctuation">,</span> reflect<span class="token punctuation">.</span>SelectCase<span class="token punctuation">{</span> + Dir<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span>SelectRecv<span class="token punctuation">,</span> <span class="token comment">// 发 or 收</span> + Chan<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 具体 Channel</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 创建 发 channel</span> + <span class="token keyword">for</span> i<span class="token punctuation">,</span> ch <span class="token operator">:=</span> <span class="token keyword">range</span> chs <span class="token punctuation">{</span> + cases <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>cases<span class="token punctuation">,</span> reflect<span class="token punctuation">.</span>SelectCase<span class="token punctuation">{</span> + Dir<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span>SelectSend<span class="token punctuation">,</span> <span class="token comment">// 发 or 收</span> + Chan<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 具体 channel</span> + Send<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">// 发送的值</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> cases +<span class="token punctuation">}</span> + + +</code></pre></div><h2 id="数据交流-生产者-消费者模式">数据交流---生产者/消费者模式</h2> <p>著名的 worker pool,如果使用 channel 去实现的话,就是一个标准的生产者消费者模式</p> <p>为了组成这个结构,需要一个存储任务的数据结构,那么这里肯定是使用一个 channel</p> <p>基本原理就是,一边往 channel 中发送数据,一边从 channel 中取数据,然后使用固定数量的 goroutine 去消费 channel 中的数据,刚好形成一个完整的生产者消费者模式,这就是复用 goroutine 的模式。</p> <p>具体的额外操作还有控制 worker 数量,任务放入 woker 池,以及从 woker 池取出任务这个操作</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"fmt"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + ctx<span class="token punctuation">,</span> cal <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithTimeout</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">2</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token function">cal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> c <span class="token operator">:=</span> <span class="token operator"><-</span>ch<span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token string">":"</span><span class="token punctuation">,</span> c<span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ctx<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token string">"退出"</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 往 channel 中 发送数据</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + ch <span class="token operator"><-</span> <span class="token number">89</span> + <span class="token punctuation">}</span> + + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">20</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>这就是基本的生产者消费者模式,以及 channel 去数据交流的最基础的原理,下面我们来实现一个真正的可用的 worker pool</p> <p>一个真正可用的 worker pool 不仅需要一个任务 channel,还需要存储任务 channel 的 woker pool,而这个 woker pool 是一个 chan chan 类型</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> worker <span class="token keyword">struct</span> <span class="token punctuation">{</span> + wokerPool <span class="token keyword">chan</span> <span class="token operator">*</span>worker + jobChannel <span class="token keyword">chan</span> Job +<span class="token punctuation">}</span> +</code></pre></div><p>之所以需要一个 chan chan 原因也很简单,如果只有一个 chan,那么 10 几个固定数目的 goroutine 将会互斥的读取一个 channel 的数据,如果是 chan chan 则互不打扰各自读取自己的 channel 即可。</p> <p>在这个项目中,我们会将读取的 channel 和处理的 channel 分开,读写分离,进行解耦, +读取数据的 channel 只需要一个即可,处理的 channel 可以有多个</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span><span class="token punctuation">(</span>w <span class="token operator">*</span>worker<span class="token punctuation">)</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token comment">// 将 单个channel(可以简单的这么认为为一个 channel) </span> + <span class="token comment">// 放入 wokerPool 中</span> + <span class="token comment">// 如果 这个 单个woker(这里代表单个channel)不再使用的话</span> + w<span class="token punctuation">.</span>workerPool <span class="token operator"><-</span> w + <span class="token keyword">select</span><span class="token punctuation">{</span> + <span class="token keyword">case</span> job <span class="token operator">:=</span> <span class="token operator"><-</span> w<span class="token punctuation">.</span>jobChannel<span class="token punctuation">:</span> <span class="token comment">// 从单个channel中读取数据并处理</span> + <span class="token function">job</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + + +</code></pre></div><p>接下来我们需要一个任务分发的函数,也就是从读取的单个 channel 中读取数据,然后发送给多个处理任务的 channel</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> dispatcher <span class="token keyword">struct</span> <span class="token punctuation">{</span> + workerPool <span class="token keyword">chan</span> <span class="token operator">*</span>worker + OneChannel <span class="token keyword">chan</span> Job +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>dispatcher <span class="token operator">*</span>dispatcher<span class="token punctuation">)</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> job <span class="token operator">:=</span> <span class="token operator"><-</span> dispatcher<span class="token punctuation">.</span>OneChannel<span class="token punctuation">:</span> <span class="token comment">// 从单个channel中读取数据</span> + <span class="token comment">// 从 wokerPool 中获取一个worker</span> + work <span class="token operator">:=</span><span class="token operator"><-</span> disatcher<span class="token punctuation">.</span>workerPool + <span class="token comment">// 给这个worker发送任务</span> + work<span class="token punctuation">.</span>jobChannel <span class="token operator"><-</span> job + <span class="token punctuation">}</span> + + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">RunDispatcher</span><span class="token punctuation">(</span>workerPool <span class="token keyword">chan</span> <span class="token operator">*</span>workerPool<span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 启动固定数目的goroutine去消费任务,并且每一个goroutine拥有一个独立的channel</span> + <span class="token keyword">for</span> i<span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token function">cap</span><span class="token punctuation">(</span>workerPool<span class="token punctuation">)</span><span class="token punctuation">;</span>i<span class="token operator">++</span> <span class="token punctuation">{</span> + worker <span class="token operator">:=</span> <span class="token function">newWorker</span><span class="token punctuation">(</span>workerPool<span class="token punctuation">)</span> + worker<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 启动分发器</span> + <span class="token keyword">go</span> dispatcher<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>大致的运行规律就是这些,其它的完整功能请查看这里:https://github.com/shgopher/grpool</p> <h2 id="传递信号-通知">传递信号/通知</h2> <p>当使用 channel 去传递信号的用法</p> <p>例如使用一个 channel 去充当信号量,当 channel 没有被关闭的时候,那么就会一直阻塞,一旦 closed,那么就能读取到数据,自然就完成了信号的传递,这种用法非常常见,比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">//...</span> + <span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span> ch +<span class="token punctuation">}</span> +</code></pre></div><p>这里使用的 channel 就是充当了一个传递信号的功能。一旦信号传递过来,整个函数就可以继续运行下去了。</p> <p>或者我们也可以传递一个空的结构体而不是直接 close(ch):</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">//...</span> + ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span> ch +<span class="token punctuation">}</span> +</code></pre></div><h3 id="收发同时进行的信号">收发同时进行的信号</h3> <p>你也可能见过这种表现方式,当 channel 充当信号的时候,发和收同时进行,看一个例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>w<span class="token punctuation">.</span>stop<span class="token punctuation">:</span> <span class="token comment">// B</span> + w<span class="token punctuation">.</span>stop <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// C</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token comment">// 另一段代码</span> + w<span class="token punctuation">.</span>stop <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// A</span> + <span class="token operator"><-</span>w<span class="token punctuation">.</span>stop <span class="token comment">// D</span> +<span class="token punctuation">}</span> +</code></pre></div><p>先说结论,这种用法提供了两个意思,提供信号+判断是否运行完毕</p> <p>A 代码等 B 准备好之后,发送了信号; +B 代码接受到了信号,这算完成了第一个含义,提供信号</p> <p>C 代码等 D 代码准备完毕,发送了信号,D 接受完毕,这个表示 A 通知 B 干的事儿,圆满完成,这里是表示判断是否执行完毕</p> <h3 id="使用计时器去解决长等待问题">使用计时器去解决长等待问题</h3> <p>一般来说,我们都是希望程序执行完毕之后自己主动退出,比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span> ch +<span class="token punctuation">}</span> +</code></pre></div><p>很合理,一般执行完毕之后,就会通知主 goroutine 优雅退出,但是如果执行的时间过长,用户很有可能就会失去信息,这个时候就需要我们再设置一个超时时间更加优雅的退出</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">100</span><span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ch<span class="token punctuation">:</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"处理超时"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="信号传递之-or-do-模式">信号传递之 or-do 模式</h3> <p>channel 信号传递之 or-do 模式跟 go 并发原语的 <a href="/GOFamily/并发/同步原语/#singleflight">singleflight</a> 比较类似</p> <p>区别是,channel 的 or-do 是多个信号传递,只有一个 channel 获取信号之后就可以停止其它 channel 了,并不需要将这个信号传递给其它的 channel,singleflight 是需要分享情报的。</p> <p>下面有两种实现的方式,递归和反射,递归比较适合递归树较低的场景,反射就适合了递归树更高的场景,因为如果递归过深的话很容易出现内存溢出的情况,如果你认为你项目中的 goroutine 也就几十那么递归就可以了,毕竟反射可是很浪费执行时间的,如果 goroutine 成千上万,选用反射即可。</p> <p>使用递归的方法:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">Ordo</span><span class="token punctuation">(</span>chs <span class="token operator">...</span><span class="token operator"><-</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> <span class="token operator"><-</span><span class="token keyword">chan</span> any <span class="token punctuation">{</span> + <span class="token comment">// 递归退出条件</span> + <span class="token keyword">switch</span> <span class="token function">len</span><span class="token punctuation">(</span>chs<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> + <span class="token punctuation">}</span> + or <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">close</span><span class="token punctuation">(</span>or<span class="token punctuation">)</span> + <span class="token keyword">switch</span> <span class="token function">len</span><span class="token punctuation">(</span>chs<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">:</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>chs<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + mi <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>chs<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span><span class="token function">Ordo</span><span class="token punctuation">(</span>chs<span class="token punctuation">[</span><span class="token punctuation">:</span>mi<span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token keyword">case</span> <span class="token operator"><-</span><span class="token function">Ordo</span><span class="token punctuation">(</span>chs<span class="token punctuation">[</span>mi<span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> or +<span class="token punctuation">}</span> +</code></pre></div><p>使用反射的方式:</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">Ordo1</span><span class="token punctuation">(</span>chs <span class="token operator">...</span><span class="token operator"><-</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> <span class="token operator"><-</span><span class="token keyword">chan</span> any <span class="token punctuation">{</span> + <span class="token comment">// 递归退出条件</span> + <span class="token keyword">switch</span> <span class="token function">len</span><span class="token punctuation">(</span>chs<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> + <span class="token punctuation">}</span> + or <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> + + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">close</span><span class="token punctuation">(</span>or<span class="token punctuation">)</span> + <span class="token keyword">var</span> cases <span class="token punctuation">[</span><span class="token punctuation">]</span>reflect<span class="token punctuation">.</span>SelectCase + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> chs <span class="token punctuation">{</span> + cases <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>cases<span class="token punctuation">,</span> reflect<span class="token punctuation">.</span>SelectCase<span class="token punctuation">{</span> + Dir<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span>SelectRecv<span class="token punctuation">,</span> + Chan<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + + reflect<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>cases<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> or +<span class="token punctuation">}</span> +</code></pre></div><p>开始测试:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"time"</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// output: 7</span> + start <span class="token operator">:=</span> time<span class="token punctuation">.</span><span class="token function">Now</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span><span class="token function">Ordo</span><span class="token punctuation">(</span><span class="token function">sig</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">sig</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">sig</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">13</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span><span class="token function">Since</span><span class="token punctuation">(</span>start<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">sig</span><span class="token punctuation">(</span>t time<span class="token punctuation">.</span>Duration<span class="token punctuation">)</span> <span class="token operator"><-</span><span class="token keyword">chan</span> any <span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">close</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> ch +<span class="token punctuation">}</span> + +</code></pre></div><p>测试证明这两种方法均可实现 or-do 信号通知模式,不过就我看来,反射的这种方法,完全无脑,也不用考虑递归,也不必去考虑递归导致的内存溢出,从实现逻辑上,非常的清晰,只需要组成一个 select 随便 case 即可,非常清晰,我首推这种实现方法</p> <h2 id="锁">锁</h2> <p>我们不仅可以使用 sync.Mutext 去实现互斥锁,也可以使用 channel 去做锁,锁本质上来说,其实就是一种信号量,标准的 pv 操作,p 减少数据,获取到锁,v 增加数据释放掉锁,锁是一种二进制信号量</p> <p>刚好,channel 的收发就符合信号量的指征</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> lock <span class="token keyword">struct</span> <span class="token punctuation">{</span> + ch <span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>l <span class="token operator">*</span>lock<span class="token punctuation">)</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token operator"><-</span> l<span class="token punctuation">.</span>ch +<span class="token punctuation">}</span> +<span class="token keyword">func</span><span class="token punctuation">(</span>l <span class="token operator">*</span>lock<span class="token punctuation">)</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + l<span class="token punctuation">.</span>ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>lock<span class="token punctuation">)</span> <span class="token function">tryLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>l<span class="token punctuation">.</span>ch<span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token boolean">true</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">false</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>lock<span class="token punctuation">)</span> <span class="token function">tryLockeTimeout</span><span class="token punctuation">(</span>timeout time<span class="token punctuation">.</span>Duration<span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>l<span class="token punctuation">.</span>ch<span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token boolean">true</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>timeout<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token boolean">false</span> + +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">NewLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span>lock<span class="token punctuation">{</span> + l<span class="token operator">:=</span> <span class="token operator">&</span>lock<span class="token punctuation">{</span> + ch<span class="token punctuation">:</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> + l<span class="token punctuation">.</span>ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token keyword">return</span> l +<span class="token punctuation">}</span> +</code></pre></div><p>在初始阶段,给予一个拥有一个缓存的 channel 一个数据,获取锁就是将这个数据取出来,释放锁就是将这个数据放回 channel,这样就实现了信号量以及互斥锁</p> <p>那么让我们试一下我们自己实现的互斥锁:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + l <span class="token operator">:=</span> <span class="token function">NewLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + value <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">120</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + l<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + value<span class="token operator">++</span> + l<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +<span class="token comment">// 120</span> +</code></pre></div><h2 id="任务编排">任务编排</h2> <h3 id="fan-in">fan-in</h3> <p>核心思想就是 “多个进,单个出”,这是数字电路的一个概念,场景是,多个 channel 发送数据给一个处理函数,此函数返回一个 channel 去承载众多信息,我们只需要监听最后输出的 channel 就可以达到监听众多信息的目的。</p> <p>基本样貌如下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">fanin</span><span class="token punctuation">(</span>chs <span class="token operator">...</span><span class="token operator"><-</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> <span class="token operator"><-</span><span class="token keyword">chan</span> any <span class="token punctuation">{</span> +<span class="token punctuation">}</span> +</code></pre></div><p>从这个基本构型也能看出来,我们要在函数中处理多个 channel,这跟上文 channel 传递信号的 or-do 模式类似,所以免不了我们要使用反射或者递归的方式去处理函数,首先我们使用递归的方式去实现这个功能</p> <p>递归版 <code>fan-in</code>:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">fanin</span><span class="token punctuation">(</span>chs <span class="token operator">...</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> <span class="token keyword">chan</span> any <span class="token punctuation">{</span> + <span class="token keyword">switch</span> <span class="token function">len</span><span class="token punctuation">(</span>chs<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> + <span class="token keyword">return</span> c + <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> + <span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> <span class="token function">merge</span><span class="token punctuation">(</span>chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> chs<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + m <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>chs<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span> + <span class="token keyword">return</span> <span class="token function">merge</span><span class="token punctuation">(</span><span class="token function">fanin</span><span class="token punctuation">(</span>chs<span class="token punctuation">[</span><span class="token punctuation">:</span>m<span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">fanin</span><span class="token punctuation">(</span>chs<span class="token punctuation">[</span>m<span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">merge</span><span class="token punctuation">(</span>ch1<span class="token punctuation">,</span> ch2 <span class="token keyword">chan</span> any<span class="token punctuation">)</span> <span class="token keyword">chan</span> any <span class="token punctuation">{</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">close</span><span class="token punctuation">(</span>c<span class="token punctuation">)</span> + <span class="token keyword">for</span> ch1 <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token operator">||</span> ch2 <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> v1<span class="token punctuation">,</span> ok <span class="token operator">:=</span> <span class="token operator"><-</span>ch1<span class="token punctuation">:</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + ch1 <span class="token operator">=</span> <span class="token boolean">nil</span> + <span class="token keyword">continue</span> + <span class="token punctuation">}</span> + c <span class="token operator"><-</span> v1 + <span class="token keyword">case</span> v2<span class="token punctuation">,</span> ok <span class="token operator">:=</span> <span class="token operator"><-</span>ch2<span class="token punctuation">:</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + ch2 <span class="token operator">=</span> <span class="token boolean">nil</span> + <span class="token keyword">continue</span> + <span class="token punctuation">}</span> + c <span class="token operator"><-</span> v2 + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> c +<span class="token punctuation">}</span> +</code></pre></div><p>反射版 <code>fan-int</code>:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">fanintflect</span><span class="token punctuation">(</span>chs <span class="token operator">...</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> <span class="token keyword">chan</span> any <span class="token punctuation">{</span> + out <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + + <span class="token keyword">var</span> cases <span class="token punctuation">[</span><span class="token punctuation">]</span>reflect<span class="token punctuation">.</span>SelectCase + + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> vl <span class="token operator">:=</span> <span class="token keyword">range</span> chs <span class="token punctuation">{</span> + cases <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>cases<span class="token punctuation">,</span> reflect<span class="token punctuation">.</span>SelectCase<span class="token punctuation">{</span> + Dir<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span>SelectRecv<span class="token punctuation">,</span> + Chan<span class="token punctuation">:</span> reflect<span class="token punctuation">.</span><span class="token function">ValueOf</span><span class="token punctuation">(</span>vl<span class="token punctuation">)</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + + <span class="token keyword">for</span> <span class="token function">len</span><span class="token punctuation">(</span>cases<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span> + i<span class="token punctuation">,</span> v<span class="token punctuation">,</span> ok <span class="token operator">:=</span> reflect<span class="token punctuation">.</span><span class="token function">Select</span><span class="token punctuation">(</span>cases<span class="token punctuation">)</span> + <span class="token comment">// 从 cases 取数据,一旦取完,cases 会取消已经取完的 case</span> + <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> + cases <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>cases<span class="token punctuation">[</span><span class="token punctuation">:</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> cases<span class="token punctuation">[</span>i<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span> + <span class="token keyword">continue</span> + <span class="token punctuation">}</span> + <span class="token comment">// out 发送数据</span> + out <span class="token operator"><-</span> v<span class="token punctuation">.</span><span class="token function">Interface</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> +</code></pre></div><p>反射版本这里有个小问题,从 cases 中取出数据,往 out 中添加,这个操作只能一个 case 一个 case 的取,但是你如果观察上文的递归实现模式,你会发现它开启了很多 goroutine 所以是并发的去取数据往 out 中送。</p> <h3 id="fan-out">fan-out</h3> <p>fan out 跟 fan in 模式是相反的,fan out 指的是拥有一个输入源,多个输出源,实际上这是一种广播机制,读取一个数据,广播给众多接受者。</p> <p>下面看一下代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">fanout</span><span class="token punctuation">(</span>value <span class="token keyword">chan</span> any<span class="token punctuation">,</span> out <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> any<span class="token punctuation">,</span> async <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> value <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> vi <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + vi <span class="token operator">:=</span> vi <span class="token comment">// if go version is lower then 1.22</span> + <span class="token keyword">if</span> async <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>实际上这段代码有 goroutine 泄露的风险,如果 out 一直不被消费,value 的数据越来越多,那么这么多等待发送信息的 goroutine 就会发生泄露问题</p> <p>解决方案有下面几种:</p> <ul><li>使用信号量去控制最多的 goroutine 数量</li> <li>给每一个 goroutine 设置超时时间</li> <li>控制发送的 value channel 的发送频率</li> <li>使用 worker pool 去限制并发数量</li></ul> <p>那么让我们用代码去实现这些改进的方案:</p> <p>方案一:使用信号量控制</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> <span class="token punctuation">(</span> + maxWorkers <span class="token operator">=</span> runtime<span class="token punctuation">.</span><span class="token function">GOMAXPROCS</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> + sema <span class="token operator">=</span> semaphore<span class="token punctuation">.</span><span class="token function">NewWeighted</span><span class="token punctuation">(</span><span class="token function">int64</span><span class="token punctuation">(</span>maxWorkers<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">)</span> +<span class="token comment">// 在 value传递结束之后,记得close value</span> +<span class="token keyword">func</span> <span class="token function">fanout</span><span class="token punctuation">(</span>value <span class="token keyword">chan</span> any<span class="token punctuation">,</span> out <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> any<span class="token punctuation">,</span> async <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> value <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> vi <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + vi <span class="token operator">:=</span> vi <span class="token comment">// if go version is lower then 1.22</span> + <span class="token keyword">if</span> async <span class="token punctuation">{</span> + ctx <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> sema<span class="token punctuation">.</span><span class="token function">Acquire</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">break</span> + <span class="token punctuation">}</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> sema<span class="token punctuation">.</span><span class="token function">Release</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>方案二:使用超时时间</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">fanout</span><span class="token punctuation">(</span>value <span class="token keyword">chan</span> any<span class="token punctuation">,</span> out <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> any<span class="token punctuation">,</span> async <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> value <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> vi <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + vi <span class="token operator">:=</span> vi <span class="token comment">// if go version is lower then 1.22</span> + <span class="token keyword">if</span> async <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span><span class="token punctuation">{</span> + <span class="token keyword">case</span> vi <span class="token operator"><-</span> v<span class="token punctuation">:</span> + <span class="token keyword">case</span> time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>方案三:控制发送 value 的发送频率</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"关闭了吗"</span><span class="token punctuation">)</span> + <span class="token function">close</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token keyword">case</span> value <span class="token operator"><-</span> <span class="token string">"%"</span><span class="token punctuation">:</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">>></span> <span class="token number">5</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"发送了吗"</span><span class="token punctuation">)</span> + + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +</code></pre></div><p>方案四:使用 worker 池复用 goroutine 去控制并发的 goroutine 数量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// github.com/shgopher/grpool</span> +<span class="token keyword">func</span> <span class="token function">fanout</span><span class="token punctuation">(</span>value <span class="token keyword">chan</span> any<span class="token punctuation">,</span> out <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> any<span class="token punctuation">,</span> async <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + pool <span class="token operator">:=</span> grpool<span class="token punctuation">.</span><span class="token function">NewPool</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> pool<span class="token punctuation">.</span><span class="token function">Release</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// 对一个nil的通道进行 for range 遍历会导致阻塞(block)。</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> value <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> vi <span class="token operator">:=</span> <span class="token keyword">range</span> out <span class="token punctuation">{</span> + <span class="token keyword">if</span> async <span class="token punctuation">{</span> + pool<span class="token punctuation">.</span>JobQueue <span class="token operator"><-</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + vi <span class="token operator"><-</span> v + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>按照我的工作经验,使用工作池和信号量控制 goroutine 数量的方法最为常用,他们都是保证最多同时存在 n 个 goroutine,这样就避免了 goroutine 泄漏问题</p> <h3 id="map-reduce">map-reduce</h3> <p>我们在函数那个<a href="https://github.com/shgopher/GOFamily/blob/aca91397692f99cd744fabcaca2055da3ec92c6f/%E5%9F%BA%E7%A1%80/%E5%87%BD%E6%95%B0%E6%96%B9%E6%B3%95/1.md?plain=1#L11" target="_blank" rel="noopener noreferrer">章节<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>介绍过 map-reduce 模式,不过并没有牵涉到并发,这里我们介绍一下并发版的 map-reduce 模式 +map</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">mapChan</span><span class="token punctuation">(</span>in <span class="token operator"><-</span><span class="token keyword">chan</span> any<span class="token punctuation">,</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span>any<span class="token punctuation">)</span>any<span class="token punctuation">)</span><span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token punctuation">{</span> + out <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> any<span class="token punctuation">)</span> + <span class="token keyword">if</span> in <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + <span class="token keyword">return</span> out + <span class="token punctuation">}</span> + + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> <span class="token function">close</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span> + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> in <span class="token punctuation">{</span> + out <span class="token operator"><-</span> <span class="token function">fn</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> +</code></pre></div><p>reduce</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">reduceChan</span><span class="token punctuation">(</span>in <span class="token operator"><-</span><span class="token keyword">chan</span><span class="token punctuation">,</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span>r<span class="token punctuation">,</span>v any<span class="token punctuation">)</span>any<span class="token punctuation">)</span>any <span class="token punctuation">{</span> + <span class="token keyword">if</span> in <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token boolean">nil</span> + <span class="token punctuation">}</span> + + out <span class="token operator"><-</span> in + + <span class="token keyword">for</span> v <span class="token operator">:=</span> <span class="token keyword">range</span> in <span class="token punctuation">{</span> + out <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">(</span>out<span class="token punctuation">,</span>v<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> out +<span class="token punctuation">}</span> +</code></pre></div><h3 id="pipeline-流水线模式">pipeline-流水线模式</h3> <p>pipeline 模式的核心思想就是顺序,单线模式,数据从头到尾,顺序执行,一个阶段的输出是下一阶段的输入。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> a A +a<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Download</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +</code></pre></div><p>这就是 pipeline 的一个简单掩饰,它的底层可能是这样实现的</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> A <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>A<span class="token punctuation">)</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">*</span>A<span class="token punctuation">{</span><span class="token keyword">return</span> a<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>A<span class="token punctuation">)</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">*</span>A<span class="token punctuation">{</span><span class="token keyword">return</span> a<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>a <span class="token operator">*</span>A<span class="token punctuation">)</span><span class="token function">Download</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">*</span>A<span class="token punctuation">{</span><span class="token keyword">return</span> a<span class="token punctuation">}</span> +</code></pre></div><p>那么在并发的场景里,如何使 goroutine 实现 pipeline 模式呢?</p> <p>这显然跟一般的流水线实现方法不同。</p> <p>我们将 channel 比作一个 token,所谓令牌,只要我们控制获取令牌的顺序,那么就可以控制持有这些令牌的 goroutine 顺序。</p> <p>下面我们使用 4 个 goroutine 依次打印 “a b c d”,300 次,我们使用流水线的方式实现:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">type</span> Token <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">var</span> <span class="token punctuation">(</span> + GNumber <span class="token builtin">int</span> + Number <span class="token builtin">int</span> + sign <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">world</span><span class="token punctuation">(</span>id <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">switch</span> id <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"b"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"c"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token number">3</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"d"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>id <span class="token builtin">int</span><span class="token punctuation">,</span> in <span class="token keyword">chan</span> Token<span class="token punctuation">,</span> out <span class="token keyword">chan</span> Token<span class="token punctuation">,</span> number <span class="token builtin">int</span><span class="token punctuation">,</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> number <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span> + token <span class="token operator">:=</span> <span class="token operator"><-</span>in + <span class="token function">fn</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span> + + <span class="token comment">// 这段代码是为了保证最后一个 goroutine 执行完毕退出 </span> + <span class="token keyword">if</span> id <span class="token operator">==</span> <span class="token punctuation">(</span>GNumber<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">&&</span> number <span class="token operator">==</span> <span class="token number">1</span> <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>sign<span class="token punctuation">)</span> + <span class="token keyword">break</span> + <span class="token punctuation">}</span> + + out <span class="token operator"><-</span> token + number<span class="token operator">--</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">RunPipeline</span><span class="token punctuation">(</span>GNumber <span class="token builtin">int</span><span class="token punctuation">,</span>Number <span class="token builtin">int</span><span class="token punctuation">,</span>chs<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> Token<span class="token punctuation">,</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> GNumber <span class="token punctuation">{</span> + <span class="token comment">// 核心代码: </span> + <span class="token comment">// 传入的in chan 和 out chan 刚好前后顺序</span> + <span class="token comment">// 这样 token 才能前后传递</span> + <span class="token keyword">go</span> <span class="token function">worker</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> chs<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> chs<span class="token punctuation">[</span><span class="token punctuation">(</span>i<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">%</span>GNumber<span class="token punctuation">]</span><span class="token punctuation">,</span> Number<span class="token punctuation">,</span>fn<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token operator"><-</span>sign + +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + GNumber <span class="token operator">=</span> <span class="token number">4</span> + Number <span class="token operator">=</span> <span class="token number">300</span> + chs <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> Token<span class="token punctuation">{</span><span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">}</span> + <span class="token function">RunPipeline</span><span class="token punctuation">(</span>GNumber<span class="token punctuation">,</span>Number<span class="token punctuation">,</span>chs<span class="token punctuation">,</span>world<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="stream-流模式">stream-流模式</h3> <h3 id="pipeline-流水线模式和-stream-流模式的对比">pipeline 流水线模式和 stream 流模式的对比</h3> <p>流水线模式 (Pipeline Pattern) 和流模式 (Stream Pattern) 都是将任务分解成多个阶段来处理,但两者还是有一些区别:</p> <ul><li>数据流动方向不同 +<ul><li>流水线模式是一条主线,数据从头流到尾,每个阶段处理完输出给下一个阶段。</li> <li>流模式是多条分支,数据可以从多个来源流入,经过处理流向多个去处。</li></ul></li> <li>执行方式不同 +<ul><li>流水线模式强调阶段间<strong>串行执行</strong>。<strong>一个阶段的输出是下一阶段的输入</strong>。</li> <li>流模式可以<strong>并行执行</strong>,<strong>不同阶段可以同时操作不同数据</strong>。</li></ul></li> <li>连接方式不同 +<ul><li>流水线模式中,每个阶段靠固定管道连接,顺序不能改变。</li> <li>流模式中,流可以更灵活自由地连接。</li></ul></li> <li>扩展性不同 +<ul><li>流水线模式扩展一个阶段可能影响整个流水线。</li> <li>流模式扩展一个阶段对其他阶段影响很小。</li></ul></li></ul> <p>总结:</p> <ul><li>流水线模式注重将任务划分多个线性执行的固定阶段。</li> <li>流模式注重构建灵活的流处理流程,流可以并行运动。</li></ul> <p>所以两者侧重点不同,在使用上也有区别。</p> <h2 id="channel-注意事项">channel 注意事项</h2> <p>发生下面事项一定会触发 panic:</p> <ul><li>向已经关闭的 channel 中发送数据</li> <li>关闭一个 nil channel</li> <li>关闭一个已经被关闭的 channel</li></ul> <h3 id="goroutine-泄露">goroutine 泄露</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">10</span><span class="token punctuation">)</span> + ch <span class="token operator"><-</span> <span class="token number">12</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">select</span><span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ch<span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ch 被关闭了"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当 time.After(time.Second) 执行完毕以后,上面那个 goroutine 因为无法接收数据,所以就会一直阻塞在发送数据那个地方,所以这个代码中,goroutine 就会泄露了。</p> <p>解决之道就是将容量设置为 1 即可:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token operator">*</span><span class="token number">10</span><span class="token punctuation">)</span> + ch <span class="token operator"><-</span> <span class="token number">12</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">select</span><span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ch<span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"ch 被关闭了"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>time<span class="token punctuation">.</span><span class="token function">After</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>当设置为 1 的时候,即使没有接受者了,发送这个地方的代码也能执行完毕,所以这个 goroutine 是不会泄露了。</p> <p>这里插一句,main goroutine 只要退出,其它 goroutine 不管有没有执行完毕也会退出,所以如果这种代码在 main 函数中出现,那么是不会发生 goroutine 泄露问题的,因为 main 函数结束以后,其它 goroutine 自动结束</p> <h2 id="channel-的实现原理">channel 的实现原理</h2> <h3 id="创建">创建</h3> <h3 id="send">send</h3> <h3 id="recive">recive</h3> <h3 id="close">close</h3> <h2 id="issues">issues</h2> <h3 id="channel-是并发银弹吗">channel 是并发银弹吗?</h3> <p>在 go 语言中,绝大多数情况下都是是使用 channel 更有优势,比如上文提到的那几种场景,例如数据的传递以及任务编排,需要跟 select 或者 context 结合,那么这都是 channel 的适用场景</p> <p>不过如果是对于共享资源的并发访问,使用传统的互斥锁更有优势一些</p> <p>如果只是线程安全的对于某个变量的数据变更,使用原子包显然是更加合适的选择</p> <h3 id="有无-buffer-的-channel-区别">有无 buffer 的 channel 区别</h3> <p>go 语言中经常会出现一个 bug,就是死锁,很多都很没有设置 channel 缓存有关,有的时候给 channel 设置一个缓存往往可以规避很多的 panic 风险</p> <h3 id="channel-close-后-read-write-close-的区别">channel close 后,read write close 的区别</h3> <ul><li>read:正常值+零值</li> <li>close:panic</li> <li>write:panic</li></ul> <h3 id="channle-底层是什么">channle 底层是什么</h3> <p>一个内部有锁的循环队列</p> <h3 id="channle-和运行时调度如何交互">channle 和运行时调度如何交互</h3> <h3 id="编程题-使用三个-goroutine-打印-abc-100-次">编程题,使用三个 goroutine 打印 abc 100 次</h3> <p>上文提到的 channel 任务编排中的 pipeline 流水线模式完美解决这个问题。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">type</span> Token <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + +<span class="token keyword">var</span> <span class="token punctuation">(</span> + GNumber <span class="token builtin">int</span> + Number <span class="token builtin">int</span> + sign <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">world</span><span class="token punctuation">(</span>id <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">switch</span> id <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token number">0</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"a"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"b"</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"c"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">worker</span><span class="token punctuation">(</span>id <span class="token builtin">int</span><span class="token punctuation">,</span> in <span class="token keyword">chan</span> Token<span class="token punctuation">,</span> out <span class="token keyword">chan</span> Token<span class="token punctuation">,</span> number <span class="token builtin">int</span><span class="token punctuation">,</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> number <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">{</span> + token <span class="token operator">:=</span> <span class="token operator"><-</span>in + <span class="token function">fn</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span> + <span class="token keyword">if</span> id <span class="token operator">==</span> <span class="token punctuation">(</span>GNumber<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">&&</span> number <span class="token operator">==</span> <span class="token number">1</span> <span class="token punctuation">{</span> + <span class="token function">close</span><span class="token punctuation">(</span>sign<span class="token punctuation">)</span> + <span class="token keyword">break</span> + <span class="token punctuation">}</span> + out <span class="token operator"><-</span> token + number<span class="token operator">--</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">RunPipeline</span><span class="token punctuation">(</span>GNumber <span class="token builtin">int</span><span class="token punctuation">,</span>Number <span class="token builtin">int</span><span class="token punctuation">,</span>chs<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> Token<span class="token punctuation">,</span>fn <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token builtin">int</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> GNumber <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token function">worker</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> chs<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> chs<span class="token punctuation">[</span><span class="token punctuation">(</span>i<span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">%</span>GNumber<span class="token punctuation">]</span><span class="token punctuation">,</span> Number<span class="token punctuation">,</span>fn<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + chs<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token operator"><-</span>sign + +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + GNumber <span class="token operator">=</span> <span class="token number">3</span> + Number <span class="token operator">=</span> <span class="token number">100</span> + chs <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token keyword">chan</span> Token<span class="token punctuation">{</span><span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> Token<span class="token punctuation">)</span><span class="token punctuation">}</span> + <span class="token function">RunPipeline</span><span class="token punctuation">(</span>GNumber<span class="token punctuation">,</span>Number<span class="token punctuation">,</span>chs<span class="token punctuation">,</span>world<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>包括之前的水生成工厂那道题,也可以使用 pieline 模式来解决,替换掉之前使用的 waitgroup 和信号量,以及循环栅栏</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://betterprogramming.pub/common-goroutine-leaks-that-you-should-avoid-fe12d12d6ee</li> <li>https://github.com/fortytw2/leaktest</li> <li>https://cloud.tencent.com/developer/article/1921580</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/channel/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/29/2024, 2:12:13 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/105.76803baf.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/context/index.html" "b/\345\271\266\345\217\221/context/index.html" new file mode 100644 index 000000000..2244ae8bf --- /dev/null +++ "b/\345\271\266\345\217\221/context/index.html" @@ -0,0 +1,208 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/106.26567b10.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#使用-context" class="sidebar-link">使用 context</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#withvalue" class="sidebar-link">withValue</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#withcancel" class="sidebar-link">WithCancel</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#withtimeout-withdeadline" class="sidebar-link">withTimeout withDeadline</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#带有-cause-的函数" class="sidebar-link">带有 cause 的函数</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#在-withtimeout-中-cancel-函数的存在意义是什么" class="sidebar-link">在 WithTimeout 中 cancel() 函数的存在意义是什么?</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/context/#contex-contex-如何实现并发安全的" class="sidebar-link">contex.Contex 如何实现并发安全的?</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="context">context</h1> <p>context 应该被翻译为上下文,但是 go 语言中的 context 更多的作用是<strong>取消子 goroutine</strong>,传递信息这个上下文本来的含义,在 go 的 context 反而不是重点</p> <p>context 本身是一个接口类型,它拥有四个方法:</p> <ul><li>Deadline()(deadline time.Time,ok bool):返回一个代表此上下文完成工作的时间,如果没有截止时间,返回 false</li> <li>Done() <-chan struct {}:代表了完结</li> <li>Err() error:如果 context 已经 done 了返回一个 error 错误,错误值分别为:Canceled,DeadlineExceeded,如果没有 done,error 返回 nil</li> <li>Value(key any) any:context 中存储的键值对</li></ul> <p>context 作为上下文,需要一个最顶层的 context 接口类型,你可以使用 <code>context.Background()</code> 或者 <code>context.TODO()</code> 去充当这个顶端,这两者是一个意思,用哪个都可以,这是 go 提供的已经实现了 context 接口类型的对象,它的底层是一个结构体</p> <p>context 有一些编程范式:</p> <ul><li>将 cotext 设置为参数的第一个,例如 <code>func age(ctx context.Context,a string)</code></li> <li>不要使用 nil 作为上下文参数,如果想要空的顶端上下文,使用 <code>context.Background</code>,虽然 background 底层实现接口的时候,也是内容为空,但是它的确是实现了接口</li> <li>context 只能作为函数的临时传递对象,不能持久化它,使用数据库保存,等持久化方式都是不可取的</li> <li>使用 withValue 方法的时候,key 值不要使用 string,如果起冲突,使用自建的类型,例如 <code>type A struct{}</code></li> <li>尽量不要定义输出的 key 值</li></ul> <h2 id="使用-context">使用 context</h2> <p>标准库中提供了多个 context 接口类型实例:</p> <ul><li>WithCancel</li> <li>WithCancelCause</li> <li>WithDeadline</li> <li>WithDeadlineCause</li> <li>WithTimeout</li> <li>WithTimeoutCause</li></ul> <p>其中,带有 Cause 的函数跟不带的函数基本意思相同,但是多了一个 cause 的内容,它是指的是取消的原因</p> <h2 id="withvalue">withValue</h2> <p>WithValue 基于 parent Context 生成一个新的 Context,保存了一个 key-value 键值 +对。它常常用来传递上下文。</p> <p>context 在查询 key 值的时候还支持链式查找,如果没有发现数据就往 parent context 中查询</p> <div class="language-go extra-class"><pre class="language-go"><code>ctx <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +ctx <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">WithValue</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token string">"key1"</span><span class="token punctuation">,</span> <span class="token string">"0001"</span><span class="token punctuation">)</span> +ctx <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">WithValue</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token string">"key2"</span><span class="token punctuation">,</span> <span class="token string">"0001"</span><span class="token punctuation">)</span> +ctx <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">WithValue</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token string">"key3"</span><span class="token punctuation">,</span> <span class="token string">"0001"</span><span class="token punctuation">)</span> +ctx <span class="token operator">=</span> context<span class="token punctuation">.</span><span class="token function">WithValue</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token string">"key4"</span><span class="token punctuation">,</span> <span class="token string">"0004"</span><span class="token punctuation">)</span> +fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>ctx<span class="token punctuation">.</span><span class="token function">Value</span><span class="token punctuation">(</span><span class="token string">"key1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> +</code></pre></div><h3 id="withcancel">WithCancel</h3> <p>withCancel 返回父 context 中的 ctx 实例副本,它相当于父 context 的子 context,并且在父 context 被取消时,子 context 也会被取消。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">withCancel</span><span class="token punctuation">(</span>parent Context<span class="token punctuation">)</span> <span class="token operator">*</span>cancelCtx <span class="token punctuation">{</span> + <span class="token keyword">if</span> parent <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"cannot create context from nil parent"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + c <span class="token operator">:=</span> <span class="token operator">&</span>cancelCtx<span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token comment">// 向上寻找</span> + c<span class="token punctuation">.</span><span class="token function">propagateCancel</span><span class="token punctuation">(</span>parent<span class="token punctuation">,</span> c<span class="token punctuation">)</span> + <span class="token keyword">return</span> c +<span class="token punctuation">}</span> +</code></pre></div><p>propagateCancel 部分代码:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>c <span class="token operator">*</span>cancelCtx<span class="token punctuation">)</span> <span class="token function">propagateCancel</span><span class="token punctuation">(</span>parent Context<span class="token punctuation">,</span> child canceler<span class="token punctuation">)</span> <span class="token punctuation">{</span> + c<span class="token punctuation">.</span>Context <span class="token operator">=</span> parent + + done <span class="token operator">:=</span> parent<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> done <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token comment">// parent is never canceled</span> + <span class="token punctuation">}</span> + + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>done<span class="token punctuation">:</span> + <span class="token comment">// 如果父done了,那么子ctx一定也会出发cancel</span> + child<span class="token punctuation">.</span><span class="token function">cancel</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> parent<span class="token punctuation">.</span><span class="token function">Err</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">Cause</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + + <span class="token keyword">if</span> p<span class="token punctuation">,</span> ok <span class="token operator">:=</span> <span class="token function">parentCancelCtx</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">;</span> ok <span class="token punctuation">{</span> + <span class="token comment">// parent is a *cancelCtx, or derives from one.</span> + p<span class="token punctuation">.</span>mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> p<span class="token punctuation">.</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// 如果父发生了cancel,那么子ctx也要触发cancel</span> + child<span class="token punctuation">.</span><span class="token function">cancel</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> p<span class="token punctuation">.</span>err<span class="token punctuation">,</span> p<span class="token punctuation">.</span>cause<span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> p<span class="token punctuation">.</span>children <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + p<span class="token punctuation">.</span>children <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span>canceler<span class="token punctuation">]</span><span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 将子ctx添加到父ctx中</span> + p<span class="token punctuation">.</span>children<span class="token punctuation">[</span>child<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token punctuation">}</span> + p<span class="token punctuation">.</span>mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token operator">...</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token comment">// 父 done被触发,那么子ctx就会被触发cancel操作</span> + <span class="token keyword">case</span> <span class="token operator"><-</span> parent<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + child<span class="token punctuation">.</span><span class="token function">cancel</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> parent<span class="token punctuation">.</span><span class="token function">Err</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">Cause</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>child<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">type</span> canceler <span class="token keyword">interface</span> <span class="token punctuation">{</span> + <span class="token function">cancel</span><span class="token punctuation">(</span>removeFromParent <span class="token builtin">bool</span><span class="token punctuation">,</span> err<span class="token punctuation">,</span> cause <span class="token builtin">error</span><span class="token punctuation">)</span> + <span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator"><-</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>propagateCancel 将 c 向上传播,顺着 parent 的路径一直向上查找,直到找到 parentCancelCtx,如果不为空,就把自己加入到这个 parentCancelCtx 的 children 切片中,然后就可以在父 ctx 取消的时候,通知自己也被取消</p> <p>当这个 cancelCtx 的 cancel 函数被调用的时候,parent 的 Done 被 close 的时候,或者父 ctx 触发了 cancel 的时候,这个子 ctx 会被触发 cancel 动作</p> <p>cancel 是向下传递的,如果一个 WithCancel 生成的 Context 被 cancel 时,如果它的子 Context (也有可能是孙,或者更低),就会被 cancel,但是不会向上传递。parent Context 不会因为子 Context 被 cancel 而 cancel。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"fmt"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ctx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithCancel</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ctx<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"done"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second <span class="token operator">*</span> <span class="token number">10</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>WithCancel 返回 parent context 的一个副本,它自然就是子 context,当父 context 被 cancel 的时候,子 context 也会被 cancel</p> <h3 id="withtimeout-withdeadline">withTimeout withDeadline</h3> <p>这两个只是添加了到期时间,一个是超时时间,一个是截止时间,一旦超过时间后,自动 close 这个 done 这个 channel</p> <p>综上所述,done 这个 channel 被 close 有三个原因:</p> <ul><li>截止时间到了</li> <li>cancel 函数被调用了</li> <li>parent context 的 done close 了,然后子 ctx 也要触发 cancel 方法</li> <li>parent context cancel 了触发子 ctx cancel 方法</li></ul> <p>关于第三条,解释一下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"fmt"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 创建一个父context,设置deadline为3秒</span> + parentCtx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithTimeout</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token comment">// 创建一个子context,deadline继承父context</span> + childCtx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithCancel</span><span class="token punctuation">(</span>parentCtx<span class="token punctuation">)</span> + <span class="token keyword">defer</span> <span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 注意这里需要调用cancel</span> + + <span class="token keyword">go</span> <span class="token function">doWork</span><span class="token punctuation">(</span>childCtx<span class="token punctuation">)</span> + + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">14</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">doWork</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + <span class="token keyword">select</span> <span class="token punctuation">{</span> + <span class="token keyword">case</span> <span class="token operator"><-</span>ctx<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"over"</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token keyword">default</span><span class="token punctuation">:</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"11"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +</code></pre></div><h2 id="带有-cause-的函数">带有 cause 的函数</h2> <p>我们看一个例子</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"errors"</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> myError <span class="token operator">=</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"myError"</span><span class="token punctuation">)</span> + ctx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithCancelCause</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token function">cancel</span><span class="token punctuation">(</span>myError<span class="token punctuation">)</span> + ctx<span class="token punctuation">.</span><span class="token function">Err</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Cause</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// returns myError</span> +<span class="token punctuation">}</span> +</code></pre></div><p>但我们调用 cancel 函数的时候,内部参数是一个 error 类型,调用 context.Cause(ctx) 返回的就是它的取消原因,那么这里的话就是 MyError</p> <h2 id="在-withtimeout-中-cancel-函数的存在意义是什么">在 WithTimeout 中 cancel() 函数的存在意义是什么?</h2> <p>cancel 函数的作用是可以手动提前取消 Context,使其 Done channel 关闭,不用等待 timeout 的时间或者 deadline 的时间</p> <p>所以 cancel 函数相当于手动取消的意思,并不是说有了 timeout deadline 之后,cancel 函数就没有存在的意义了。</p> <p>按照 go 的语法,即便是 timeout 触发了 <- done 操作,你仍然需要手动的去在最后调用 cancel 函数,否则就会报错</p> <p>WithTimeout 在超时时会自动 cancel context,但是 cancel 函数还是需要调用,以释放/重置 Context 内部的 timer,如果不调用 cancel,timer 不会被释放,持续运行并重复 cancel 导致 context leak,占用更多资源。</p> <div class="language-go extra-class"><pre class="language-go"><code>ctx<span class="token punctuation">,</span> cancel <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">WithTimeout</span><span class="token punctuation">(</span>parentCtx<span class="token punctuation">,</span> <span class="token number">2</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + +<span class="token keyword">go</span> <span class="token function">doWork</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span> + +<span class="token comment">// 1秒后决定取消任务</span> +time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token operator">*</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> +<span class="token function">cancel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +</code></pre></div><h2 id="issues">issues</h2> <h3 id="contex-contex-如何实现并发安全的">contex.Contex 如何实现并发安全的?</h3> <p>Go 语言中 context 实现并发安全的主要手段是通过原子操作和 Mutex 来保证状态的原子性</p> <p>根据底层代码可知,当不同的 goroutine 获取 ctx 的时候,每次操作都会加上互斥锁,来保证数据的非竞争性,线程的安全,例如</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">if</span> p<span class="token punctuation">,</span> ok <span class="token operator">:=</span> <span class="token function">parentCancelCtx</span><span class="token punctuation">(</span>parent<span class="token punctuation">)</span><span class="token punctuation">;</span> ok <span class="token punctuation">{</span> + <span class="token comment">// parent is a *cancelCtx, or derives from one.</span> + p<span class="token punctuation">.</span>mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> p<span class="token punctuation">.</span>err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token comment">// 如果父发生了cancel,那么子ctx也要触发cancel</span> + child<span class="token punctuation">.</span><span class="token function">cancel</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> p<span class="token punctuation">.</span>err<span class="token punctuation">,</span> p<span class="token punctuation">.</span>cause<span class="token punctuation">)</span> + <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> p<span class="token punctuation">.</span>children <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + p<span class="token punctuation">.</span>children <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span>canceler<span class="token punctuation">]</span><span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 将子ctx添加到父ctx中</span> + p<span class="token punctuation">.</span>children<span class="token punctuation">[</span>child<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token punctuation">}</span> + p<span class="token punctuation">.</span>mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> +</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/context/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/13/2024, 2:04:03 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/106.26567b10.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/index.html" "b/\345\271\266\345\217\221/index.html" new file mode 100644 index 000000000..5b651ee63 --- /dev/null +++ "b/\345\271\266\345\217\221/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/103.4ebce8b3.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="并发">并发</h1> <ul><li><a href="./%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B">内存模型</a></li> <li><a href="./%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B">并发模型</a></li> <li><a href="./%E5%B9%B6%E5%8F%91%E5%8E%9F%E8%AF%AD">并发原语</a></li> <li><a href="./channel">channel</a></li> <li><a href="./atomic">atomic</a></li> <li><a href="./context">context</a></li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/5/2024, 2:48:04 PM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/103.4ebce8b3.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/\345\206\205\345\255\230\346\250\241\345\236\213/index.html" "b/\345\271\266\345\217\221/\345\206\205\345\255\230\346\250\241\345\236\213/index.html" new file mode 100644 index 000000000..3260f7544 --- /dev/null +++ "b/\345\271\266\345\217\221/\345\206\205\345\255\230\346\250\241\345\236\213/index.html" @@ -0,0 +1,201 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>内存模型 | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/107.c757198e.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>内存模型</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#介绍一些-go-语言中的基本操作" class="sidebar-link">介绍一些 go 语言中的基本操作</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#内存模型存存在的意义" class="sidebar-link">内存模型存存在的意义</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#具体表现" class="sidebar-link">具体表现</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#三条定律" class="sidebar-link">三条定律</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#重排和可见性" class="sidebar-link">重排和可见性</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#同步操作的-happens-before" class="sidebar-link">同步操作的 happens-before</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#单个-goroutine" class="sidebar-link">单个 goroutine</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#init-函数" class="sidebar-link">init 函数</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#goroutine" class="sidebar-link">goroutine</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#channel" class="sidebar-link">channel</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#mutex-rwmutex" class="sidebar-link">Mutex/RWMutex</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#waitgroup" class="sidebar-link">WaitGroup</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#once" class="sidebar-link">Once</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#atomic" class="sidebar-link">atomic</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="内存模型">内存模型</h1> <p>go 官方介绍 go 内存模型的时候说:探究在什么条件下,A goroutine 在读取一个变量的值的时,能够看到其它 goroutine 对这个变量进行的写的结果。</p> <p>我们为什么需要内存模型?</p> <p>CPU 指令可能会被重排序,并且存在多级缓存,例如 Go 语言中的多级内存模型。不同的 CPU 架构 (比如 x86 和 ARM) 也会对指令顺序产生影响,编译器优化也可能改变指令顺序。</p> <p>因此,编程语言需要一个内存规范,也就是内存模型,来规定程序中的内存访问和同步的语义,保证在不同的硬件和编译器下,程序的执行结果保持一致</p> <h2 id="介绍一些-go-语言中的基本操作">介绍一些 go 语言中的基本操作</h2> <blockquote><p>除了基本的读和写之外都是同步操作,包括以下列举的,并且更多以这些基础操作衍生出的操作。</p></blockquote> <ul><li>读 +<ul><li>基础的读 +<ul><li>对超过机器 word 大小的值读,可以看作是拆成 word 大小的几个读的无序进行</li></ul></li> <li>原子包的读</li> <li>使用 sync.Mux 的读</li> <li>使用 channel 形式的读</li></ul></li> <li>写 +<ul><li>基础的写 +<ul><li>变量的初始化就是一个写操作</li> <li>对超过机器 word 大小的值写,可以看作是拆成 word 大小的几个写的无序进行</li></ul></li> <li>原子包的写</li> <li>sync.mux 的写</li> <li>向 channel 发送数据</li></ul></li> <li>atomic 的 compare and swap 操作,兼顾了写和读</li></ul> <p>我们讨论 go 内存模型的时候,主要聚焦下面四种细节的<strong>差异性</strong>:</p> <ul><li>操作的种类: +<ul><li>普通的读或者写</li> <li><strong>同步操作</strong>,比如利用 sync 包进行同步,利用 channel 在不同的 goroutine 中间进行同步,利用 atomic 包进行同步等。</li></ul></li> <li>这个操作者在程序中的位置</li> <li>被操作者在内存位置,或者是被访问的变量的位置</li> <li>被操作者值的类型</li></ul> <h2 id="内存模型存存在的意义">内存模型存存在的意义</h2> <ul><li><p>给程序员一个最根本的法则 --- 你只要遵循这个法则,那么在进行多 goroutine 数据访问的时候,做串行控制 (使用同步操作) 一定会成功。</p></li> <li><p>给编译器优化开发者一个法则,只要遵循这个法则,就能不出错的做出编译器级别的优化。</p></li></ul> <h3 id="具体表现">具体表现</h3> <ul><li><strong>探究可见性</strong></li> <li><strong>happens- before</strong>:x 操作一定在 y 操作之前执行完毕,这里说的并不是时间,而是 “执行完毕” 这个结论,我们可以放心的在 y 中使用 x 的执行结果。主要突出的是这个完成性。</li></ul> <h3 id="三条定律">三条定律</h3> <ul><li><p>在一个 goroutine 中,程序执行的顺序一定是符合代码写的顺序的。但是不同的 goroutine 中这个定理失效。</p></li> <li><p>在<strong>同步操作</strong>的时候,从 a goroutine 看到 b goroutine 的执行顺序,必须符合同步操作的顺序,这里举个例子,举例:b 的同步操作是什么顺序,那么 a 读取的就是什么顺序。比如 b 中有三个 Channel,他们执行的顺序是先 a 发 b 收,b 发,c 收,那么在 a 中读取的顺序跟这个同步的操作顺序是一致的,<strong>如果不是同步操作就可能不一致。</strong></p></li> <li><p>对于非同步操作的普通读和写,如果 b 操作了 a,那么必须成立</p> <ul><li>b 发生在 a 之前</li></ul></li></ul> <p>我们可以使用 <code>go build -race</code> 来发现数据竞争。</p> <p>接下来我们对于内存模型的具体表现进行更具体的介绍。</p> <h2 id="重排和可见性">重排和可见性</h2> <p>由于指令的重排,代码<strong>不一定</strong>会按照你写的顺序执行。</p> <p>这里给出一个案例:有两个 goroutine 分别是 g1,和 g2,g1 读某个变量的数据,g2 写这个变量的数据,当 g1 读取到 g2 写的新数据之后,你也不一定能读取到在 goroutine g2 中排列在这个写数据操作之前的操作:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">var</span> <span class="token punctuation">(</span> + a <span class="token operator">=</span> <span class="token number">1</span> + b <span class="token operator">=</span> <span class="token number">2</span> + done <span class="token builtin">bool</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + a <span class="token operator">=</span> <span class="token number">3</span> + b <span class="token operator">=</span> <span class="token number">4</span> + done <span class="token operator">=</span> <span class="token boolean">true</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> <span class="token operator">!</span>done <span class="token punctuation">{</span> + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>b<span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> <span class="token comment">// 可能观察到的就是输出的 4 3,但是无法保证必须是4 3 ,能观察到 != 保证</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>下面这种情况,a goroutine 无法观察到 b goroutine 是否完成了写操作,有可能造成 a goroutine 一直被卡的现象:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">type</span> Result <span class="token keyword">struct</span> <span class="token punctuation">{</span> + data <span class="token builtin">string</span> +<span class="token punctuation">}</span> + +<span class="token keyword">var</span> <span class="token punctuation">(</span> + r <span class="token operator">*</span>Result +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + d <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>Result<span class="token punctuation">)</span> + d<span class="token punctuation">.</span>data <span class="token operator">=</span> <span class="token string">"hi there"</span> <span class="token comment">// 这里无法确认一定会运行</span> + r <span class="token operator">=</span> d <span class="token comment">// 这里无法确认观察到</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token function">set</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> r <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>r<span class="token punctuation">.</span>data<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><blockquote><p>there is no guarantee that the write to done will ever be observed by main,<strong>since there are no synchronization events between the two threads</strong>。The loop in main is not guaranteed to finish。“</p></blockquote> <p>这一句是 go blog 中对于这代代码的描述,重点是说,这俩线程中,没有存在同步原语,所以无法做到从 main goroutine 去观测到 r 的状态,也就是说,在 goroutine 中只要存在了同步原语,那么就可以把两个 goroutine 当作正常的语句来看。</p> <p>这里有两点无法确认,第一:主 goroutine 无法<strong>确认</strong> r 的状态,这里指的就是<strong>可观测性</strong>,因为这里是非同步操作,所以主 goroutine 的读无法观测到 <code>go set()</code> 这里 <code>r = d</code> 这里的写,注意是无法完全确认,通常来说这段代码是可以运行的,我说的是通常,第二无法保证 <code>d.data</code> 一定会运行,所以有可能输出的是空字符串,这里说的就是因为编译优化导致的指令重排。</p> <h2 id="同步操作的-happens-before">同步操作的 happens-before</h2> <p>go 不直接提供 cpu 屏障,来保证编译器或者 cpu 保证顺序性,而是使用不同架构的内存屏障指令来实现统一的并发原语。</p> <h3 id="单个-goroutine">单个 goroutine</h3> <p>上文说到,<strong>在一个 goroutine 中,happens- before 其实就等于代码书写的顺序,这一点是严格成立的</strong>。</p> <h3 id="init-函数">init 函数</h3> <p>go 语言的初始化是在单一的 goroutine 中执行的,也就是 main goroutine。</p> <p><strong>p 包导入了 q 包,那么 q 的 init 函数一定 happens before p 的任何初始化代码</strong>。</p> <p>这里有点像树,导入的过程,以及初始化的过程,会形成一个多叉树,从最底层的树开始进行初始化,逐步的忘上层走,先进后出,栈一样的感觉,并且相同的包只会导入一次,进而也只会初始化一次,比如 q 包被第三层导入了,在第五层也导入了,那么这个包在从底层往上走的过程中,只会在第五层先全局变量后 init 函数的初始化一次。这导入的包全部初始化一遍之后,才开始进行 main 包的 mian 函数,然后进而去运行接下来的逻辑。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span><span class="token punctuation">(</span> + a <span class="token operator">=</span> c <span class="token operator">+</span> b + + b <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + c <span class="token operator">=</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + d <span class="token operator">=</span> <span class="token number">3</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">int</span><span class="token punctuation">{</span> + d <span class="token operator">++</span> + <span class="token keyword">return</span> d +<span class="token punctuation">}</span> +</code></pre></div><p>初始化的顺序是这样的,首先初始化 a,因为 a = c + b,那么系统开始初始化 c 和 b,c 和 b 等于一个函数 f,那么就开始初始化这个函数,函数里面是 d 那么开始初始化 d,所以 b = 3+1 c = 3+1+1 a = 9,这个时候 d 已经++ 两次了,所以最终的初始化以后 a = 9 b = 4 c = 5 d = 5</p> <p>包级别的变量按照代码顺序初始化,同一个包的众多文件会按照文件名的排列顺序进行初始化。</p> <h3 id="goroutine">goroutine</h3> <p>启动 goroutine 的 go 语言执行,一定 happens - before 此 goroutine 内的代码执行。退出可就没有任何 happens- before 的理论了,所以退出我们通常要部署同步语句。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> a <span class="token builtin">string</span> +<span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + a <span class="token operator">=</span> <span class="token string">"hi"</span> + <span class="token keyword">go</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>从单个 goroutine 的 happens- before 的关系来看,a = “hi” 一定 happens- before go f (),从新 goroutine 的开辟来说,go f () 一定 happens- before fmt.Println 所以这个代码中,hi 一定能被输出。</p> <h3 id="channel">channel</h3> <p>go 语言有一句经典名言,不要使用共享内存来通信 (sync.Mutex) 而应该采用通信的方式来共享内存,这个后者说的就是 channel,channel 是同步操作的首选。</p> <ul><li>往 channel 中发数据,happens - before 从这个 channel 接收数据<strong>完成</strong>。注意这里说的是接收完成,<strong>没说</strong>发数据 happens- before 这个 channel 接受数据开始的时候。</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> c <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span> <span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token keyword">var</span> a <span class="token builtin">string</span> + +<span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">//这里之所以a = hi 发生在 c <-0 之前,就是因为这个goroutine和main goroutine 存在同步原语,</span> + <span class="token comment">//只要存在,那么代码就会按照程序员写的顺序执行,并不会进行重排。</span> + a <span class="token operator">=</span> <span class="token string">"hi"</span> + c <span class="token operator"><-</span><span class="token number">0</span> <span class="token comment">// 这里因为有了同步操作,所以 a = “hi” 在main goroutine看 也是 a= “hi” happens- before c <- 0</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator"><-</span>c <span class="token comment">// 这里只要收到数据了,那么 c <- 0 肯定已经运行了,并且发送完毕了。</span> + <span class="token function">print</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><ul><li><p>close 一个 channel 一定 happens- before 从关闭的 channel 中读取一个零值。我们都知道可以从一个 closed 的一个 channel 中读取零值是可以的,这里说明的是读零值这个过程一定在关闭这个操作之后。</p></li> <li><p>一个 unbuffered 的 channle,读的准备好一定 happens-before 发准备好,意思是说,只有收数据准备好了,才能发,否则就会一直卡在发那个地方。</p></li> <li><p>一个容量大于 0 为 m 的 channel,第 n 个接收,一定 happens- before 第 n+m 的发送,意思是说,如果容量满了,必须先拿出来一个才能往里面再塞进去一个。比如:n=1 m=2,第一个接收一定 happens- before 第三个发送,因为容量一共是 2,要想往里面塞进去第三个,<strong>必须拿出来一个并且拿出来这个操作完毕了</strong>,才能发送第三个。</p></li></ul> <h3 id="mutex-rwmutex">Mutex/RWMutex</h3> <ul><li>第 n 次的 unlock 一定 happends- before 第 n+1 次 lock 方法的返回 +意思是说,只有先解锁才能再次加锁。</li> <li>读写锁虽然有两把锁,但是不能同时使用,必须等待一个锁解锁后,另一个锁才能上锁,比如读锁解锁后才能再次上读锁,或者才能上写锁。</li></ul> <p>互斥锁可以由 a goroutine 上锁,b goroutine 解锁</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex +<span class="token keyword">var</span> s <span class="token builtin">string</span> + +<span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + s <span class="token operator">=</span> <span class="token string">"hi"</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 这里拥有了一个同步原语,所以 s = hi 一定发生在 mu.unlock() 之前。(相当于在一段锁的内部)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 这里的lock 一定发生在 另一个goroutine 中f 的 mu.Unlock() 之后。</span> + <span class="token function">print</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="waitgroup">WaitGroup</h3> <ul><li>wait 方法等到计数值归零才能返回 (运行完毕)</li></ul> <h3 id="once">Once</h3> <ul><li>对于 once.Do(f) f 一定会在 do 方法返回之前执行。</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> s <span class="token builtin">string</span> +<span class="token keyword">var</span> once sync<span class="token punctuation">.</span>Once + +<span class="token keyword">func</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span>Second<span class="token punctuation">)</span> + s <span class="token operator">=</span> <span class="token string">"hi"</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + once<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span>f<span class="token punctuation">)</span> + <span class="token function">print</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token comment">// 这里 f 的执行完毕 一定在 Do()返回之前,所以一定能输出 s = hi</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="atomic">atomic</h3> <p>按照 atomic load / store 顺序来保证 happens - before 不过 go 官方并没有严格定义,直到目前为止并没有严格定义。</p> <div class="language-go extra-class"><pre class="language-go"><code> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> a<span class="token punctuation">,</span> b <span class="token builtin">int32</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span> + + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + atomic<span class="token punctuation">.</span><span class="token function">StoreInt32</span><span class="token punctuation">(</span><span class="token operator">&</span>a<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + atomic<span class="token punctuation">.</span><span class="token function">StoreInt32</span><span class="token punctuation">(</span><span class="token operator">&</span>b<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token keyword">for</span> atomic<span class="token punctuation">.</span><span class="token function">LoadInt32</span><span class="token punctuation">(</span><span class="token operator">&</span>b<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">{</span> + runtime<span class="token punctuation">.</span><span class="token function">Gosched</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>atomic<span class="token punctuation">.</span><span class="token function">LoadInt32</span><span class="token punctuation">(</span><span class="token operator">&</span>a<span class="token punctuation">)</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="issues">issues</h2> <p><code>使用channel实现一个互斥锁</code></p> <p>我们利用 channel 发送数据 happens- before 收到数据完毕这个特性来实现互斥锁。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Locker <span class="token keyword">struct</span> <span class="token punctuation">{</span> + ch <span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token comment">// 初始状态是已经有一个</span> +<span class="token keyword">func</span> <span class="token function">NewLocker</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">*</span>Locker<span class="token punctuation">{</span> + ch <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> + ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token operator">&</span>Locker<span class="token punctuation">{</span> + ch<span class="token punctuation">:</span> ch<span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +<span class="token comment">// lock 从缓存是1编程0,从chan中取出来数据</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>Locker<span class="token punctuation">)</span> <span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token operator"><-</span> l<span class="token punctuation">.</span>ch +<span class="token punctuation">}</span> +<span class="token comment">// unlock 将缓存从0变成1,向ch中放入数据。</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>l <span class="token operator">*</span>Locker<span class="token punctuation">)</span> <span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + l<span class="token punctuation">.</span>ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><p>一个小小的经验:channel 拥有 buffer 比没有 buffer 常用很多。</p> <p>完结。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/ref/mem</li> <li>https://time.geekbang.org/column/article/307469</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/内存模型/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/23/2024, 7:58:45 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/107.c757198e.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/\345\220\214\346\255\245\345\216\237\350\257\255/index.html" "b/\345\271\266\345\217\221/\345\220\214\346\255\245\345\216\237\350\257\255/index.html" new file mode 100644 index 000000000..6d696cbd7 --- /dev/null +++ "b/\345\271\266\345\217\221/\345\220\214\346\255\245\345\216\237\350\257\255/index.html" @@ -0,0 +1,791 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/11.25dd6abf.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-mutex" class="sidebar-link">sync.Mutex</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#临界区" class="sidebar-link">临界区</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-mutex-基础操作" class="sidebar-link">sync.Mutex 基础操作</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-locker-接口" class="sidebar-link">sync.Locker 接口</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#什么是-data-race-的本质" class="sidebar-link">什么是 data race 的本质</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#检测-data-race-的工具" class="sidebar-link">检测 data race 的工具</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#将互斥锁嵌入到结构体中" class="sidebar-link">将互斥锁嵌入到结构体中</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-mutex-互斥锁的实现原理" class="sidebar-link">sync.Mutex 互斥锁的实现原理</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-mutex-易错的几种场景" class="sidebar-link">sync.Mutex 易错的几种场景</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-mutex-扩展" class="sidebar-link">sync.Mutex 扩展</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-rwmutex" class="sidebar-link">sync.RWMutex</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-waitgroup" class="sidebar-link">sync.WaitGroup</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#常见错误" class="sidebar-link">常见错误</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#singleflight" class="sidebar-link">SingleFlight</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#cyclicbarrier" class="sidebar-link">cyclicBarrier</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#errgroup" class="sidebar-link">errgroup</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-once" class="sidebar-link">sync.Once</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#讨论线程安全的-map-在多线程中的使用" class="sidebar-link">讨论线程安全的 map 在多线程中的使用</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#直接加锁" class="sidebar-link">直接加锁</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#细颗粒度并发安全-map" class="sidebar-link">细颗粒度并发安全 Map</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-map" class="sidebar-link">sync.Map</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#sync-pool" class="sidebar-link">sync.Pool</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#pool-内存浪费" class="sidebar-link">pool 内存浪费</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#worker-pool" class="sidebar-link">worker pool</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#semaphore" class="sidebar-link">semaphore</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#使用信号量时的注意事项" class="sidebar-link">使用信号量时的注意事项</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#使用-channel-去实现一个信号量" class="sidebar-link">使用 channel 去实现一个信号量</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#issues" class="sidebar-link">issues</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#问题一-有互斥锁就一定有临界区吗" class="sidebar-link">问题一:有互斥锁就一定有临界区吗?</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#问题二-如果-mutex-已经被一个-goroutine-获取了锁-其它等待中的-goroutine-们只能一直等待。那么-等这个锁释放后-等待中的-goroutine-中哪一个会优先获取-mutex-呢" class="sidebar-link">问题二:如果 Mutex 已经被一个 goroutine 获取了锁,其它等待中的 goroutine 们只能一直等待。那么,等这个锁释放后,等待中的 goroutine 中哪一个会优先获取 Mutex 呢?</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#问题三-mutext-的底层中-使用-state-和-sema-来表示锁的状态-sema-是信号量-为什么在有信号量表示锁的状态之后还需要一个-state-表示锁是否上锁呢" class="sidebar-link">问题三:Mutext 的底层中,使用 state 和 sema 来表示锁的状态,sema 是信号量,为什么在有信号量表示锁的状态之后还需要一个 state 表示锁是否上锁呢?</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#问题四-使用循环栅栏-信号量去完成经典并发题-水的制造工厂" class="sidebar-link">问题四:使用循环栅栏,信号量去完成经典并发题:水的制造工厂</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%90%8C%E6%AD%A5%E5%8E%9F%E8%AF%AD/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="同步原语">同步原语</h1> <p>传统同步原语是 go 提供的相对底层的同步机制,它更加灵活,但是同时也更加复杂,如果可能的话,我们应该尽量使用 csp 的并发模型,使用 channel 去代替传统同步原语。</p> <p>本单元讲的传统同步原语,channel 和 contex 也属于同步原语,他们属于 csp 的并发模型,所以他们会单独为列。</p> <p>下面讲一下这么多同步原语 (也叫并发原语) 的基本功能:</p> <ul><li><code>sync.Mutex, sync.RWMutex</code> 共享资源,避免数据竞争 (data race)</li> <li><code>sync.Waitgroup, channel</code> 任务编排,各个 goroutine 所代表的任务的前后顺序关系</li> <li><code>channel</code> 传递消息</li></ul> <p>这是基本的划分,当然这个划分还不严谨,但是你只需要知道,这些属于最常见的同步原语,以及他们最常见的功能。</p> <h2 id="sync-mutex">sync.Mutex</h2> <p>下面介绍的众多并发原语,甚至下一章的 channel,都使用了这个核心内容,它就是 <code>sync.Mutex</code>,它是所有同步原语包含 channel 的底层核心。</p> <p>Mutex 也就是互斥锁,它主要是为了解决多线程下数据的竞争问题,所以互斥锁是同步原语的最底层最核心的组件</p> <p>让我们看几个场景</p> <ol><li><p>计数器,多个线程去更新一个计数器的时候,如果不加锁,就会出现数据的错误,本来你只加上了 1,正当你读的时候你发现别的线程也加上了 1,所以导致读取的错误</p></li> <li><p>秒杀服务,这也是一个常见的场景,如果不加锁,就会导致超卖的情况出现</p></li> <li><p>往一个 buffer 中传入数据,如果不加锁,数据的顺序就会发生乱序</p></li></ol> <h3 id="临界区">临界区</h3> <p>临界区的概念是指在多线程的时候,临界区域的内容会被不同的线程去获取和释放,这个区域会发生数据的争夺问题。</p> <p>这个区域因为会发生争夺,所以会被保护起来,可以这么说,临界区是<strong>多线程中整体数据中的共享部分</strong></p> <p>所以临界区是要保护的区域,<strong>一次只能让一个线程去使用</strong></p> <p>所以 sync.Mutex 就是用来保护临界区的,它可以保证临界区的互斥</p> <p>共享资源通常是某个变量,例如临界区是变量 count,临界区操作是 count++,只要在临界区前面获取 +锁,在离开临界区的时候释放锁,就能解决 data race 的问题。</p> <h3 id="sync-mutex-基础操作">sync.Mutex 基础操作</h3> <p>我们现看一下它的基础使用功能:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span><span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 跨goroutine 加解锁</span> +<span class="token keyword">func</span> <span class="token function">age1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi there"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>sync.Mutex 即为互斥锁,规则是:</p> <ul><li>锁的加锁和解锁可以跨 goroutine 使用,比如 a goroutine 加锁,在 b goroutine 将锁解开。</li> <li>只有现解锁才能继续上锁,happens-before 就是:<em><strong>n 次解锁一定 happens-before n+1 次加锁</strong></em></li></ul> <h3 id="sync-locker-接口">sync.Locker 接口</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Locker <span class="token keyword">interface</span><span class="token punctuation">{</span> + <span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>Mutex 就实现了这个 Locker 接口</p> <p>Locker 定义了锁的基本方法,加锁 + 解锁</p> <h3 id="什么是-data-race-的本质">什么是 data race 的本质</h3> <p>我们常说 data race 的情况,是多线程同时对于某块内存进行数据的变更,那么问题来了,这个地方谈到的同时,是真的物理层面的同时还是近似同时?</p> <p>关于 data race 中的 “同时” 通常是<strong>指逻辑上的同时或近似同时,而不是物理层面严格的同一时刻。</strong></p> <p>主要原因有以下几点:</p> <ul><li>现代 CPU 中,同一时刻真正执行指令的只有一个核心。不同核心之间以及同一核心的不同执行周期之间,不存在物理层面严格的同步。</li> <li>即使在单核 CPU 上,由于指令流水线、内存缓存、分支预测等机制,实际执行顺序也可能与代码顺序不一致,很难定义物理层面严格的同步。</li> <li>不同线程之间进行切换的时间间隔非常小 (几十到几百纳秒),对程序逻辑而言可以视为同时进行。</li> <li>要构成 data race,不同线程对同一地址的访问之间间隔不能太长,必须在一个指令/操作的启始和完成之间,所以也符合逻辑上的近似同时。</li></ul> <p>所以,data race 中的 “同时” 就是指逻辑上近似同时,或者无法确定准确执行顺序的情况,而不是物理层面严格同一时刻。这种近似同时从程序角度就是可能造成冲突,需要进行同步处理。</p> <h3 id="检测-data-race-的工具">检测 data race 的工具</h3> <p>并发问题不是一定能肉眼看出来的,如果只是基础的,容易看出来的也就罢了,但是很多隐藏的 data race 问题必须使用专业的工具去鉴别,go 语言提供了 <code>-race</code> 功能,在编译,测试,run 的时候,会自动检测到 data race 问题,并且给出详细的错误信息。</p> <div class="language-bash extra-class"><pre class="language-bash"><code> go run -race main.go +</code></pre></div><p>我们看一个例子</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + value <span class="token operator">:=</span> <span class="token number">0</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + value <span class="token operator">++</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>本能的你会以为能输出 10000,但是结果确实 9000 多,而且还不一定,这是为啥呢?</p> <p>因为你以为 ++ 操作是原子操作,其实并不是。</p> <p>++ 操作分为三个步骤</p> <ul><li>获取 value 值</li> <li>值+1</li> <li>将新值写回</li></ul> <p>这其实是三个步骤,10000 个线程,假如同时有 10 个去读了这个 value,在他们看来都是初始值是 0,然后他们+1,然后写回去了结果 value 是 1,相当于 10 个 goroutine 都去写,本来应该是 10,但是赋值回去都变成了 1</p> <p>这个时候,如果你使用 run -race 就能检测出来</p> <div class="language-bash extra-class"><pre class="language-bash"><code>go1 go run -race main.go +<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> +WARNING: DATA RACE +Read at 0x00c00010a018 by goroutine <span class="token number">8</span>: + main.main.func1<span class="token punctuation">(</span><span class="token punctuation">)</span> + /Users/shgopher/Desktop/1/go1/main.go:23 +0x2c + +Previous <span class="token function">write</span> at 0x00c00010a018 by goroutine <span class="token number">6</span>: + main.main.func1<span class="token punctuation">(</span><span class="token punctuation">)</span> + /Users/shgopher/Desktop/1/go1/main.go:23 +0x3c + +Goroutine <span class="token number">8</span> <span class="token punctuation">(</span>running<span class="token punctuation">)</span> created at: + main.main<span class="token punctuation">(</span><span class="token punctuation">)</span> + /Users/shgopher/Desktop/1/go1/main.go:22 +0x48 + +Goroutine <span class="token number">6</span> <span class="token punctuation">(</span>finished<span class="token punctuation">)</span> created at: + main.main<span class="token punctuation">(</span><span class="token punctuation">)</span> + /Users/shgopher/Desktop/1/go1/main.go:22 +0x48 +<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span> +<span class="token number">9957</span> +Found <span class="token number">1</span> data race<span class="token punctuation">(</span>s<span class="token punctuation">)</span> +<span class="token builtin class-name">exit</span> status <span class="token number">66</span> +</code></pre></div><p>多线程多某个区域的内存进行同时 (或者近似同时) 操作,这就是数据竞争</p> <p>使用这个内置工具有个很大的缺陷,就是只有在数据真的执行中发生了数据竞争才能被发现,并且,使用-race 会影响编译的程序执行速度</p> <p>如果我们使用 <code>go tool compile -race -S x.go</code> 的时候就发现使用-race 之后,编译的时候 go 编译器往代码中加入了很多运行时监控代码,<strong>这些运行时的监控代码</strong>会影响性能</p> <div class="language-go extra-class"><pre class="language-go"><code> <span class="token number">0x001c</span> <span class="token number">00028</span> <span class="token punctuation">(</span>a<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">)</span> PCDATA $<span class="token number">1</span><span class="token punctuation">,</span> $<span class="token number">0</span> + <span class="token number">0x001c</span> <span class="token number">00028</span> <span class="token punctuation">(</span>a<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">)</span> CALL runtime<span class="token punctuation">.</span><span class="token function">racefuncenter</span><span class="token punctuation">(</span>SB<span class="token punctuation">)</span> + <span class="token number">0x0020</span> <span class="token number">00032</span> <span class="token punctuation">(</span>a<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">4</span><span class="token punctuation">)</span> MOVD $<span class="token keyword">type</span><span class="token punctuation">:</span><span class="token function">int</span><span class="token punctuation">(</span>SB<span class="token punctuation">)</span><span class="token punctuation">,</span> R0 + <span class="token number">0x0028</span> <span class="token number">00040</span> <span class="token punctuation">(</span>a<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">4</span><span class="token punctuation">)</span> CALL runtime<span class="token punctuation">.</span><span class="token function">newobject</span><span class="token punctuation">(</span>SB<span class="token punctuation">)</span> +</code></pre></div><p><code>runtime.xx</code> 的代码就是添加的运行时监控</p> <blockquote><p>小知识,使用 go tool compile 的时候不要加入第三方库,标准库也不行,编译工具只能编译本文件,跟 go build 那种能查找依赖树的方式不同</p></blockquote> <h3 id="将互斥锁嵌入到结构体中">将互斥锁嵌入到结构体中</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> MyAge <span class="token keyword">struct</span> <span class="token punctuation">{</span> + mu sync<span class="token punctuation">.</span>Mutex + value <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><p>或者直接嵌入</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> MyAge <span class="token keyword">struct</span> <span class="token punctuation">{</span> + sync<span class="token punctuation">.</span>Mutex + value <span class="token builtin">int</span> +<span class="token punctuation">}</span> +</code></pre></div><div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> age MyAge + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + age<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> age<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + age<span class="token punctuation">.</span>value <span class="token operator">++</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>age<span class="token punctuation">.</span>value<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="sync-mutex-互斥锁的实现原理">sync.Mutex 互斥锁的实现原理</h3> <p>go 语言互斥锁的实现非常简单,只有这一个结构体就是核心:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> Mutex <span class="token keyword">struct</span> <span class="token punctuation">{</span> + state <span class="token builtin">int32</span> + sema <span class="token builtin">uint32</span> +<span class="token punctuation">}</span> +</code></pre></div><blockquote><p>在阅读下面互斥锁的几个阶段之前,建议先读一下 G:M:P 模型</p></blockquote> <h4 id="互斥锁演变的四个阶段一-简单实现">互斥锁演变的四个阶段一:简单实现</h4> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 最初的代码</span> +<span class="token keyword">type</span> Mutex <span class="token keyword">struct</span> <span class="token punctuation">{</span> + key <span class="token builtin">int32</span> <span class="token comment">// 锁是否被持有的标志,1 被持有,0 没有被持有</span> + sema <span class="token builtin">uint32</span> <span class="token comment">// 锁的具体状态,此信号量具有高级语意,用来控制goroutine的状态</span> +<span class="token punctuation">}</span> +<span class="token comment">// compare and swap 操作:val 和 old 进行对比,如果相同,使用new去替代 val的值</span> +<span class="token keyword">func</span> <span class="token function">cas</span><span class="token punctuation">(</span>val <span class="token operator">*</span><span class="token builtin">int32</span><span class="token punctuation">,</span> old<span class="token punctuation">,</span><span class="token builtin">new</span> <span class="token builtin">int32</span><span class="token punctuation">)</span><span class="token builtin">bool</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token comment">// val 数据添加一个 delta 值,返回新的值</span> +<span class="token keyword">func</span> <span class="token function">xadd</span><span class="token punctuation">(</span>val <span class="token operator">*</span><span class="token builtin">int32</span><span class="token punctuation">,</span> delta <span class="token builtin">int32</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token builtin">new</span> <span class="token builtin">int32</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + v <span class="token operator">:=</span> <span class="token operator">*</span>val + <span class="token keyword">if</span> <span class="token function">cas</span><span class="token punctuation">(</span>val<span class="token punctuation">,</span>v<span class="token punctuation">,</span>v<span class="token operator">+</span>delta<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">return</span> v<span class="token operator">+</span>delta + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"unreached"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>mutex<span class="token punctuation">)</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token function">xadd</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>key<span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">1</span> <span class="token punctuation">{</span> <span class="token comment">// 标识+1 ,如果等于1 获取到锁</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token comment">// 这里就是说,当key >1 的时候,我们通知goroutine休眠等待锁</span> + <span class="token comment">// 只有key 等于 1 才能算获取锁</span> + <span class="token function">semacquire</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>sema<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>mutex<span class="token punctuation">)</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">if</span> <span class="token function">xadd</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>key<span class="token punctuation">,</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span> <span class="token comment">// 标识-1 ,如果等于0 表示没有其它等待者</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token comment">// 这个函数是汇编语言写的,上面那个 semacquire 也是</span> + <span class="token function">semrelease</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>sema<span class="token punctuation">)</span> <span class="token comment">// 唤醒等待锁的其它的goroutine中的一个</span> +<span class="token punctuation">}</span> +</code></pre></div><p>可以看到,这种简单的实现,完全没有考虑任何的情况,仅仅是简单的加锁和解锁,不考虑 goroutne 的任何情况,就是随机的,随机的获取锁然后解锁。</p> <p>注意 go 语言的锁可以 a 加 b 解,所以一定要谁加锁就谁解锁,不然就无法构成互斥锁这个概念了。</p> <h4 id="互斥锁演变的四个阶段二-优先新-goroutine">互斥锁演变的四个阶段二:优先新 goroutine</h4> <p>在这个演变中,go 的互斥锁调度会优先将锁权分给新创建的 goroutine</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">const</span> <span class="token punctuation">(</span> + <span class="token comment">// 1</span> + mutexLock <span class="token operator">=</span> <span class="token number">1</span> <span class="token operator"><<</span> <span class="token boolean">iota</span> + <span class="token comment">// 2</span> + mutexWoken + <span class="token comment">// 2</span> + mutexWaiterShift <span class="token operator">=</span> <span class="token boolean">iota</span> +<span class="token punctuation">)</span> +<span class="token keyword">type</span> Mutex <span class="token keyword">struct</span> <span class="token punctuation">{</span> + state <span class="token builtin">int32</span> + sema <span class="token builtin">uint32</span> +<span class="token punctuation">}</span> + +</code></pre></div><p>state 的内容变成了三个:</p> <ul><li>第一个字段:mutexWaiters 阻塞等待的数量</li> <li>第二个字段:mutexWoken 唤醒标记</li> <li>第三个字段:mutexLocked 持有锁的标记</li></ul> <p>我们先前知道,如果想要获取锁的 goroutine 没有机会获取到锁,就会进行休眠,但是在锁释放唤醒之后,它并不能像先前一样直接获取到锁,还是要和正在请求锁 goroutine 进行竞争。这会给后来请求锁的 goroutine 一个机会,也让 CPU 中正在执行的 goroutine 有更多的机会获取到锁,在一定程度上提高了程序的性能。</p> <p>在这次演变中,go 的调度器会将新的 goroutine 给赋予锁,因为新的 goroutine 就是正在 cpu 执行片段中执行的 goroutine,这个时候将锁给他们无疑是效率最高的。</p> <h4 id="互斥锁演变的四个阶段三-多给机会-优先新-goroutine-以及被唤醒的-goroutine">互斥锁演变的四个阶段三:多给机会,优先新 goroutine 以及被唤醒的 goroutine</h4> <p>如果新来的 goroutine 或者是被唤醒的 goroutine 首次获取不 +到锁,它们就会通过<strong>自旋</strong> (spin,通过循环不断尝试) 的方式,尝试检查锁是否被释放。在尝试<strong>一定</strong>的自旋次数后,再执行原来的逻辑。</p> <h4 id="互斥锁演变的四个阶段四-在第三个阶段的基础上引入饥饿模式">互斥锁演变的四个阶段四:在第三个阶段的基础上引入饥饿模式</h4> <p>为什么会加入饥饿模式呢?就是因为如果都优先给新的 goroutine,那么等待队列中的 goroutine 就永远不会被执行,所以引入了饥饿模式,优先执行等待中的 goroutine +然后新的 gorontine 就被添加到了等待队列中的队尾,这个时期称之为饥饿模式,因为新的 goroutine 基本上都要在 cpu 的时间片段中执行,所以在这个模式下,执行效率反而是底下的,因为正在执行的 goroutine 被强行放到队尾了。</p> <p>当等待的队首的 goroutine 等待时间超过 1ms 就会进入这个模式</p> <p>当队首的 goroutine 等待时间小于 1ms 或者已经执行到队尾了,那么这个模式就会从饥饿模式改为正常的模式</p> <h3 id="sync-mutex-易错的几种场景">sync.Mutex 易错的几种场景</h3> <h4 id="lock-unlock-不是成对出现">Lock/Unlock 不是成对出现</h4> <p>因为 go 语言中,互斥锁是无法获取 goroutine 的信息的,所以存在 a 锁 b 解的情况,即:a goroutine 上了锁,b goroutine 给解开了。</p> <p>如果你不是为了实现锁,是为了任务编排,那么可以这么做。</p> <p>如果是为了锁,请不要这么做,因为这么做的后果就是这将不能形成锁这个概念</p> <p>或者说当你使用了 lock 的时候忘记 unlock 了,那么最终都会导致系统走向失败</p> <h4 id="copy-已经使用的-mutex">Copy 已经使用的 Mutex</h4> <p>go 语言的 mutex 使用 state 字段去表示锁的含义,所以当你 copy 一个锁的时候,实际上已经 copy 了这个锁的状态,这将导致错误的结果</p> <p>go 语言的同步原语众多,使用的底层都是 mutex (包括 channel),所以说,不仅仅是 mutex 不能使用 copy,其它的同步原语都不能。</p> <h4 id="重入">重入</h4> <p>所谓重入,就是多次上锁,注意这里是拥有锁的这个线程去请求这把锁</p> <p>go 语言不支持重入,系统会 panic,这种重入锁无法实现也跟 go 语言的互斥锁没有记录使用它的 goroutine 有关系</p> <p>那么如果 go 语言也实现一个重入锁,核心就是将持有锁的 goroutine 的 id 记录下来</p> <h4 id="死锁">死锁</h4> <p>当多线程的情况下,多个线程陷入了争抢资源的情况,当他们都陷入了停滞状态,或者阻塞状态的时候,就会发生死锁,deaadlock</p> <p>一般来讲,当你发现系统多个线程都堵死的时候,就会发生死锁情况了,但是通常发生死锁是发生在满足这四个情况下</p> <ul><li>互斥:资源具有排他性,只能有一个 goroutine 访问</li> <li><strong>持有和等待</strong>:goroutine 持有资源,并还在请求其它资源</li> <li>不可剥夺:资源只有被它持有的 goroutine 释放</li> <li><strong>环路等待</strong>:发生了环路等待事件,下面这个案例可以解释这个理论</li></ul> <p>举一个案例</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span><span class="token punctuation">(</span> + <span class="token string">"sync"</span> + <span class="token string">"fmt"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup + <span class="token keyword">var</span> mu1 sync<span class="token punctuation">.</span>Mutex + <span class="token keyword">var</span> mu2 sync<span class="token punctuation">.</span>Mutex + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu1<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu1<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + mu2<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu2<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu2<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu2<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + mu1<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu1<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在这个案例中,mu1 和 mu2 代表两个资源,两个 goroutine 在争夺这两个资源,下面我们盘点一下上文说的四个理论知识:</p> <ul><li>互斥性:资源只能被一个 goroutine 持有</li> <li>持有和等待,一个 goroutine 获取了一把锁,还想获取第二把</li> <li>不可剥夺,持有锁的 goroutine 释放锁后,其他 goroutine 不能再获取该锁</li> <li>环路等待,两个 goroutine 陷入了环路这个概念总,第一个先持有 mu1,第二个 goroutine 先持有 mu2,他们又分别要获取另一个锁,所以陷入了环路等待中</li></ul> <p><img src="/GOFamily/assets/img/ringwaiter.c4e44723.png" alt="h"></p> <p>所以这个案例中,发生了死锁</p> <div class="language-go extra-class"><pre class="language-go"><code>fatal <span class="token builtin">error</span><span class="token punctuation">:</span> all goroutines are asleep <span class="token operator">-</span> deadlock<span class="token operator">!</span> + +goroutine <span class="token number">1</span> <span class="token punctuation">[</span>semacquire<span class="token punctuation">]</span><span class="token punctuation">:</span> +sync<span class="token punctuation">.</span><span class="token function">runtime_Semacquire</span><span class="token punctuation">(</span><span class="token number">0xc0000a4020</span>?<span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>runtime<span class="token operator">/</span>sema<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">62</span> <span class="token operator">+</span><span class="token number">0x25</span> +sync<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>WaitGroup<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token number">0x0</span>?<span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>sync<span class="token operator">/</span>waitgroup<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">116</span> <span class="token operator">+</span><span class="token number">0x48</span> +main<span class="token punctuation">.</span><span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator">/</span>tmp<span class="token operator">/</span>sandbox1712910389<span class="token operator">/</span>prog<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">31</span> <span class="token operator">+</span><span class="token number">0x125</span> + +goroutine <span class="token number">17</span> <span class="token punctuation">[</span>sync<span class="token punctuation">.</span>Mutex<span class="token punctuation">.</span>Lock<span class="token punctuation">]</span><span class="token punctuation">:</span> +sync<span class="token punctuation">.</span><span class="token function">runtime_SemacquireMutex</span><span class="token punctuation">(</span><span class="token number">0x1</span>?<span class="token punctuation">,</span> <span class="token number">0x58</span>?<span class="token punctuation">,</span> <span class="token number">0x459218</span>?<span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>runtime<span class="token operator">/</span>sema<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">77</span> <span class="token operator">+</span><span class="token number">0x25</span> +sync<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>Mutex<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">lockSlow</span><span class="token punctuation">(</span><span class="token number">0xc0000a2028</span><span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>sync<span class="token operator">/</span>mutex<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">171</span> <span class="token operator">+</span><span class="token number">0x15d</span> +sync<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>Mutex<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>sync<span class="token operator">/</span>mutex<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">90</span> +main<span class="token punctuation">.</span>main<span class="token punctuation">.</span><span class="token function">func1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator">/</span>tmp<span class="token operator">/</span>sandbox1712910389<span class="token operator">/</span>prog<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">20</span> <span class="token operator">+</span><span class="token number">0xd1</span> +created by main<span class="token punctuation">.</span>main in goroutine <span class="token number">1</span> + <span class="token operator">/</span>tmp<span class="token operator">/</span>sandbox1712910389<span class="token operator">/</span>prog<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">15</span> <span class="token operator">+</span><span class="token number">0xb9</span> + +goroutine <span class="token number">18</span> <span class="token punctuation">[</span>sync<span class="token punctuation">.</span>Mutex<span class="token punctuation">.</span>Lock<span class="token punctuation">]</span><span class="token punctuation">:</span> +sync<span class="token punctuation">.</span><span class="token function">runtime_SemacquireMutex</span><span class="token punctuation">(</span><span class="token number">0x1</span>?<span class="token punctuation">,</span> <span class="token number">0x58</span>?<span class="token punctuation">,</span> <span class="token number">0x459218</span>?<span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>runtime<span class="token operator">/</span>sema<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">77</span> <span class="token operator">+</span><span class="token number">0x25</span> +sync<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>Mutex<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">lockSlow</span><span class="token punctuation">(</span><span class="token number">0xc0000a2020</span><span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>sync<span class="token operator">/</span>mutex<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">171</span> <span class="token operator">+</span><span class="token number">0x15d</span> +sync<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>Mutex<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span> + <span class="token operator">/</span>usr<span class="token operator">/</span>local<span class="token operator">/</span><span class="token keyword">go</span><span class="token operator">-</span>faketime<span class="token operator">/</span>src<span class="token operator">/</span>sync<span class="token operator">/</span>mutex<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">90</span> +main<span class="token punctuation">.</span>main<span class="token punctuation">.</span><span class="token function">func2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token operator">/</span>tmp<span class="token operator">/</span>sandbox1712910389<span class="token operator">/</span>prog<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">28</span> <span class="token operator">+</span><span class="token number">0xd1</span> +created by main<span class="token punctuation">.</span>main in goroutine <span class="token number">1</span> + <span class="token operator">/</span>tmp<span class="token operator">/</span>sandbox1712910389<span class="token operator">/</span>prog<span class="token punctuation">.</span><span class="token keyword">go</span><span class="token punctuation">:</span><span class="token number">23</span> <span class="token operator">+</span><span class="token number">0x119</span> + +</code></pre></div><h3 id="sync-mutex-扩展">sync.Mutex 扩展</h3> <p>这里主要讲解如何对 sync.Mutex 进行功能扩展</p> <p>基本的原理就是<strong>将 sync.Mutex 嵌入到一个新的接口体中,然后重载 Lock 和 Unlock 的方法进行改造</strong></p> <h4 id="改造一个重入锁">改造一个重入锁</h4> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">type</span> RecursiveMutex <span class="token keyword">struct</span> <span class="token punctuation">{</span> + sync<span class="token punctuation">.</span>Mutex + owner <span class="token builtin">int64</span> <span class="token comment">// goroutine id</span> + recursion <span class="token builtin">int64</span> <span class="token comment">//当前goroutine重入次数</span> +<span class="token punctuation">}</span> +</code></pre></div><p>lock 操作</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span><span class="token punctuation">(</span>m <span class="token operator">*</span>RecursiveMutex<span class="token punctuation">)</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// 第三方包,目的是获取正在获取锁的lock 操作的 runtime id</span> + <span class="token comment">// github.com/petermattis/goid</span> + gid <span class="token operator">:=</span> goid<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token comment">// 判断当前goroutine是否是要重入的goroutine</span> + <span class="token keyword">if</span> atomic<span class="token punctuation">.</span><span class="token function">LoadInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>owner<span class="token punctuation">)</span> <span class="token operator">==</span> gid <span class="token punctuation">{</span> + <span class="token comment">// 重入指标+1</span> + atomic<span class="token punctuation">.</span><span class="token function">AddInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>recursion<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + m<span class="token punctuation">.</span>Mutex<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// 获取得到锁的goroutine的id</span> + atomic<span class="token punctuation">.</span><span class="token function">StoreInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>owner<span class="token punctuation">,</span> gid<span class="token punctuation">)</span> + atomic<span class="token punctuation">.</span><span class="token function">StoreInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>recursion<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>unlock 操作</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span><span class="token punctuation">(</span>m <span class="token operator">*</span>RecursiveMutex<span class="token punctuation">)</span> <span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + gid <span class="token operator">:=</span> goid<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token comment">// 非持有锁的goroutine去释放锁直接panic</span> + <span class="token keyword">if</span> atomic<span class="token punctuation">.</span><span class="token function">LoadInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>owner<span class="token punctuation">)</span> <span class="token operator">==</span> gid <span class="token punctuation">{</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"wrong"</span><span class="token punctuation">,</span>m<span class="token punctuation">.</span>owner<span class="token punctuation">,</span>gid<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 重入指标-1</span> + atomic<span class="token punctuation">.</span><span class="token function">StoreInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>recursion<span class="token punctuation">,</span><span class="token operator">&</span>m<span class="token punctuation">.</span>recursion <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> + + <span class="token keyword">if</span> atomic<span class="token punctuation">.</span><span class="token function">LoadInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>recursion<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span> <span class="token punctuation">{</span> <span class="token comment">// 持有的goroutine还没有全部unlock</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + <span class="token comment">// 将 重入指标设置为-1</span> + atomic<span class="token punctuation">.</span><span class="token function">StoreInt64</span><span class="token punctuation">(</span><span class="token operator">&</span>m<span class="token punctuation">.</span>recursion<span class="token punctuation">,</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> + m<span class="token punctuation">.</span>Mutex<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="sync-rwmutex">sync.RWMutex</h2> <p>上文我们提到了互斥锁,互斥锁是真的锁,不论是读还是写都只能有一个 goroutine 去操作,所以说互斥锁才是真的锁,那么我们这里讲的读写锁是什么含义呢?</p> <p>读写锁:允许多个 goroutine 同时去读一个数据,但是这个时候是不允许写的;只允许一个 goroutine 去写一个数据,并且不允许其它 goroutine 去读这个数据。</p> <p>所以,读写锁跟互斥锁相比,把读的权限给增大了,但是写的权限不变。</p> <p>当我们遇到一个读多写少的场景,那么使用读写锁的效率要比互斥锁的效率高的多。</p> <p>读写锁拥有以下几个方法:</p> <ul><li>Lock/Unlock:写操作时加的锁</li> <li>Rlock/RUnlock:读操作时加的锁</li> <li>Rlocker:为读操作返回一个 Locker 接口的对象</li></ul> <p>RWMutex 跟 mutex 一样,初始值都是未加锁的状态,当然他们都是有状态的结构体,所以也不能复制锁,因为初始值就是未加锁,所以直接声明即可。</p> <p>总结一下读写锁的几个注意事项</p> <ul><li>上文提到了,不可复制</li> <li>lock 和 unlock 要成对出现;Rlock 和 RUnlock 也要成对出现</li></ul> <p>下面我们看一下,使用读写锁造成的死锁问题</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 这个写法出问题的原因是:读锁还没结束就开启了写锁</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>RWMutex + + mu<span class="token punctuation">.</span><span class="token function">RLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + mu<span class="token punctuation">.</span><span class="token function">RUnlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + +<span class="token punctuation">}</span> +</code></pre></div><p>出现死锁的原因就是出现了环形等待,读锁等待写锁解锁,写锁等待读锁解锁</p> <h2 id="sync-waitgroup">sync.WaitGroup</h2> <p>它的作用是任务的编排</p> <p>waitgroup 一共有三个方法:</p> <ul><li>Add(delta int):增加 delta 个任务</li> <li>Done():任务完成,减少一个任务</li> <li>Wait():阻塞等待,直到所有任务完成</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token operator">&</span>wg<span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">get</span><span class="token punctuation">(</span>wg <span class="token operator">*</span>sync<span class="token punctuation">.</span>WaitGroup<span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="常见错误">常见错误</h3> <ul><li>add 的时候数值传入负值</li> <li>done 的次数超过 add 中的次数</li> <li>在 add 之前调用了 wait</li> <li>当前一个 waitgroup 还没有完结就开始重用了 waitgroup,也就是说,必须等到上一轮的 wait 执行完毕了才能开启新的一轮</li></ul> <p>最后这个错误我们看一个案例:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// AA</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>在这个案例中,AA 处的 add 行为有可能发生在主 goroutine 之后,那么相当于一轮未结束又开启了新的一轮,就会发生 panic 行为</p> <p>当然了,我不是说 add 只能调用一次,但是 add 虽然能调用多次,但是不能发生在 wait 之后</p> <p>正确的多次调用 add 的案例:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup + + <span class="token keyword">for</span> i<span class="token operator">:=</span><span class="token number">0</span><span class="token punctuation">;</span>i<span class="token operator"><</span><span class="token number">10</span><span class="token punctuation">;</span>i<span class="token operator">++</span><span class="token punctuation">{</span> + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>注意,我们这里每次循环都调用了一次 add,但是 add 的调用始终发生在 wait 之前,这还是属于同一轮的多次 add 调用,这符合 waigroup 的规定</p> <h2 id="singleflight">SingleFlight</h2> <blockquote><p>著名缓存库 <a href="https://github.com/golang/groupcache" target="_blank" rel="noopener noreferrer">groupcache<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 就使用了 singleflight 去通过缓存来减少后端查询数据库的请求</p></blockquote> <p>在处理多个 goroutine 同时调用同一个函数的时候,只让一个 goroutine 去调用这个函数,等到这个 goroutine 返回结果的时候,再把结果返回给这几个同时调用的 goroutine</p> <p>在面对多个 goroutine 并发去读一个数据的时候,使用 SingleFlight 可以大大降低请求量,从 n 的请求量降低到 1,比如在秒杀的场景下,n 个 goroutine 去请求数据,那么我们使用 SingleFlight 就能大大提高读的性能</p> <p>SingleFlight 提供了三个公开方法:</p> <ul><li><p>func (g *Group) Do(key string,fn func() (interface {},error)) (v interface {},err error,shared bool)</p></li> <li><p>func (g *Group) DoChan(key string,fn func() (interface {},error)) <-chan Result</p></li> <li><p>func (g *Group) Forget(key string)</p></li> <li><p>Do:Do 执行并返回函数的结果,同样 key 值下的只能有一个 goroutine 持有的 do 方法会执行,其它的都会等待,直到唯一一个执行完毕有了结果,那么大家 (指都执行 do 的众多 goroutine) 都有了结果</p></li> <li><p>DoChan:跟 do 类似,返回值是一个 channel</p></li> <li><p>Forget:告诉这个 group,忘记 key,之后,这个 key 请求回执行 f 函数,而不是等待前一个未完成的 fn 函数的结果</p> <div class="language-go extra-class"><pre class="language-go"><code> sf <span class="token operator">:=</span> <span class="token operator">&</span>sync<span class="token punctuation">.</span>SingleFlight<span class="token punctuation">{</span><span class="token punctuation">}</span> + + sf<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span><span class="token string">"param"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token punctuation">{</span> + <span class="token comment">// ...function logic</span> + <span class="token keyword">return</span> result + <span class="token punctuation">}</span><span class="token punctuation">)</span> + sf<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span><span class="token string">"param"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token punctuation">{</span> + <span class="token comment">//...</span> + <span class="token keyword">return</span> result + <span class="token punctuation">}</span><span class="token punctuation">)</span> + + <span class="token comment">// 对于同一个key 下(这里是param)这些动作只执行一次,后续注册的函数会直接返回第一个函数的结果。</span> + <span class="token comment">//</span> + + + <span class="token comment">// 后续想重新执行</span> + sf<span class="token punctuation">.</span><span class="token function">Forget</span><span class="token punctuation">(</span><span class="token string">"param"</span><span class="token punctuation">)</span> + + sf<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span><span class="token string">"param"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token punctuation">{</span> + <span class="token comment">// 这次会再次执行函数逻辑</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> +</code></pre></div></li></ul> <p>下面我们看一下 DoChan 的基本使用方法:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + + <span class="token string">"golang.org/x/sync/singleflight"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + g <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>singleflight<span class="token punctuation">.</span>Group<span class="token punctuation">)</span> + + block <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> + + res1c <span class="token operator">:=</span> g<span class="token punctuation">.</span><span class="token function">DoChan</span><span class="token punctuation">(</span><span class="token string">"key"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token operator"><-</span>block + + <span class="token keyword">return</span> <span class="token string">"func 1"</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> + + <span class="token punctuation">}</span><span class="token punctuation">)</span> + + res2c <span class="token operator">:=</span> g<span class="token punctuation">.</span><span class="token function">DoChan</span><span class="token punctuation">(</span><span class="token string">"key"</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token operator"><-</span>block + + <span class="token keyword">return</span> <span class="token string">"func 2"</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> + + <span class="token punctuation">}</span><span class="token punctuation">)</span> + + <span class="token function">close</span><span class="token punctuation">(</span>block<span class="token punctuation">)</span> + + res1 <span class="token operator">:=</span> <span class="token operator"><-</span>res1c + + res2 <span class="token operator">:=</span> <span class="token operator"><-</span>res2c + + <span class="token comment">// 使用相同的key执行的函数共享结果</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Shared:"</span><span class="token punctuation">,</span> res2<span class="token punctuation">.</span>Shared<span class="token punctuation">)</span> + + <span class="token comment">// 只有第一个函数被执行:它使用"key"被注册和启动,在第二个函数被注册相同的key之前就完成了执行。</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Equal results:"</span><span class="token punctuation">,</span> res1<span class="token punctuation">.</span>Val<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator">==</span> res2<span class="token punctuation">.</span>Val<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Result:"</span><span class="token punctuation">,</span> res1<span class="token punctuation">.</span>Val<span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +</code></pre></div><div class="language-bash extra-class"><pre class="language-bash"><code>Shared: <span class="token boolean">true</span> +Equal results: <span class="token boolean">true</span> +Result: func <span class="token number">1</span> +</code></pre></div><p>g.DoChan / g.Do 都会在内部会启动一个新的 goroutine 来执行传入的函数。</p> <p>g.DoChan 的签名如下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token punctuation">(</span>g <span class="token operator">*</span>Group<span class="token punctuation">)</span> <span class="token function">DoChan</span><span class="token punctuation">(</span>key <span class="token builtin">string</span><span class="token punctuation">,</span> fn <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator"><-</span><span class="token keyword">chan</span> Result +</code></pre></div><p>它接受一个 key 和一个函数 fn,并返回一个 Result 类型的 channel。</p> <p>在 g.DoChan 内部,会首先根据 key 在内部 map 中查找是否已经有相同 key 的函数在执行:</p> <ul><li>如果存在,则直接返回已有的 Result channel</li> <li>如果不存在,则启动一个新的 goroutine 执行 fn 函数,并将 Result 发送到返回的 channel 中</li></ul> <p>所以 g.DoChan 会确保对于相同的 key,最多只有一个 goroutine 在执行 fn,后续的调用会直接复用已有的结果。</p> <p>这就实现了 key 去重重复执行的语义。</p> <p>所以,g.DoChan 会隐式地启动 goroutine 来运行函数,这是它实现并发和协调的基础。</p> <p>我们在处理缓存击穿的问题时,通常采用 singleflight 会有比较好的适用,所谓缓存击穿就是大量请求在请求一个 key 值时,key 值失效了,大量数据开始请求数据库,使用 singleflight 时,大量数据只需要一次请求,完美解决了缓存击穿问题</p> <blockquote><p>缓存击穿:指一个 key 非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个 key 在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像弹丸穿透目标一样。当某个 key 在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会对数据库造成压力。</p></blockquote> <blockquote><p>缓存穿透:指查询一个数据库一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。</p></blockquote> <blockquote><p>缓存雪崩:指在某一个时间段,缓存集中过期失效。所有访问都落到数据库上,对数据库造成巨大压力。这通常因为缓存服务器宕机或缓存时效过短导致,可通过服务器保护或增大缓存过期时间来避免。</p></blockquote> <h2 id="cyclicbarrier">cyclicBarrier</h2> <blockquote><p>github.com/marusama/cyclicbarrier</p></blockquote> <p>允许一组 goroutine 彼此等待,到达一个共同的执行点。同时,因为它可 +以被重复使用,所以叫循环栅栏</p> <p>基本用法就是 Await 方法,等待所有的参与者到达,到达了就往下走,然后开始新的循环</p> <p>那么看起来很像 waitgroup,那么为什么不使用 wg 呢?</p> <p>在一种场景下 wg 通常很难使用,也就是循环这个含义,因为你需要在 wait 之后再次调用 add 方法充值,然后继续 done wait,麻烦,并且万一在继续 add 的时候发生了并发问题就跟灾难了</p> <ul><li><p>WaitGroup 更适合用在 “一个 goroutine 等待一组 goroutine 到达同一个执行点” 的场景中,或者是不需要重用的场景中。</p></li> <li><p>CyclicBarrier 更适合用在 “固定数量的 goroutine 等待同一个执行点” 的场景中,而且在放行 goroutine 之后,CyclicBarrier 可以重复利用,不像 WaitGroup 重用的时候,必须小心翼翼避免 panic。</p></li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 数字代表执行任务的 goroutine 的个数</span> +b1 <span class="token operator">:=</span> cyclicbarrier<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span> +<span class="token comment">// 或者带有方法的循环栅栏</span> +b2 <span class="token operator">:=</span> cyclicbarrier<span class="token punctuation">.</span><span class="token function">NewWithAction</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">nil</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> + +b<span class="token punctuation">.</span><span class="token function">Await</span><span class="token punctuation">(</span>ctx<span class="token punctuation">)</span> <span class="token comment">// await other parties</span> +<span class="token comment">// 将循环栅栏重置</span> +b<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// reset the barrier</span> +</code></pre></div><p>我们可以发现循环栅栏会一直循环的执行,虽然它有 await 方法,但是每次到这个 await 都会继续执行下一轮的循环,那么该如何跳出循环呢?</p> <p>通常我们会配合 sync.WaitGroup 一起执行</p> <h2 id="errgroup">errgroup</h2> <p>将一个通用的父任务,拆成几个小任务并发执行的场景</p> <ul><li>WithContex 表示创建一个 group 实例,并且创建一个 withcancel 的上下文 context,一旦子任务返回错误,或者 wait 调用返回,context 就会被 cancel</li> <li>Go Go(f func()error) 传入的子任务,一旦 error,就会促发 withcancel 的 cancel 操作</li> <li>Wait 等待所有任务都完成后,wait 才会执行</li></ul> <h2 id="sync-once">sync.Once</h2> <p>once 用来执行仅发生一次的动作,常用与单例模式,对象初始化的行为,并且经常在 init 函数中使用</p> <p>sync.Once 仅仅暴漏了一个 do 方法,而且多次调用 do,仅有第一次的无返回值的 f 函数可以执行,即便 f 不同:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> once sync<span class="token punctuation">.</span>Once + +<span class="token keyword">func</span> <span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + once<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 仅执行一次</span> + <span class="token punctuation">}</span><span class="token punctuation">)</span> + <span class="token comment">// 这次不会执行</span> + once<span class="token punctuation">.</span><span class="token function">Do</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + + <span class="token punctuation">}</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="讨论线程安全的-map-在多线程中的使用">讨论线程安全的 map 在多线程中的使用</h2> <p>go 语言中的 map 并不是并发安全的,一个 map 如果不加锁的去处理数据的时候就会出现 panic 的情况,比如:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"sync"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> m <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token comment">// 初始化一个map</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">//设置key</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">//访问这个map</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000000</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这种写法就会发生 panic,原因是 go 语言不支持并发读写 map,必须加锁</p> <p>其实我们如果分析这段代码,并没有说对同一个 key 值进行读写,也没有涉及到扩容的问题,但是仍然会 panic,go 在操作 map 时会进行 data race 的检测,只要检测有,就会直接 panic</p> <h3 id="直接加锁">直接加锁</h3> <p>我们可以人为的加锁,这样就可以避免 data race 的行为</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"sync"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex + <span class="token keyword">var</span> m <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token comment">// 初始化一个map</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">//设置key</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">//访问这个map</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000000</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>如果数据量比较低的话,这么做毫无问题,如果数据量较大,或者每次操作都比较耗时,读写公用一锁就比较浪费了。</p> <p>那么可以使用读写锁吗?当然可以啦,我们使用读写锁可以更优秀的去解决这个问题</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"fmt"</span> + <span class="token string">"sync"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>RWMutex + <span class="token keyword">var</span> m <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">int</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span> <span class="token comment">// 初始化一个map</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + m<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">//设置key</span> + mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100000</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">RLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>m<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">//访问这个map</span> + mu<span class="token punctuation">.</span><span class="token function">RUnlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">1000000</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>RWMutex 在同时有读写需求时,会优先获取写锁,读锁需要等待</p> <p>如果当前有读锁,则后续的写锁请求会被阻塞,但读锁可以继续获取,</p> <p>如果当前有写锁,则后续的读锁和写锁请求都会被阻塞。</p> <p>所以,如果读多写少,使用读写锁是非常方便的,假如读和写都异常的高,那么读和写其实是不能同时进行的,如果读贼多,写就可能被阻塞等待了。</p> <h3 id="细颗粒度并发安全-map">细颗粒度并发安全 Map</h3> <p>我们都知道,锁对于性能的影响是特别大的,尤其是线程非常多的时候,那么多线程公用一个锁,各种等待,能不影响效率吗,那么怎么做能提高效率呢?</p> <p>降低锁的颗粒度就可以提高效率,换言之就是本来 1000 个线程公用一个,现在,我们把数据分为 10 份,100 个线程用一个锁,性能就能大范围的提高</p> <p>我们可以使用 https://github.com/orcaman/concurrent-map 这个分片儿锁去替代互斥锁</p> <p>分片儿锁的基本原理就是将一个大的 map 的内容,变成 10 个或者是更多个 map 的内容,我们可以这么做:</p> <p>本身需要一个 map 的数据结构,我们改成一个 slice,slice 含有 10 个 map 的数据结构 +我们还需要一个定位分片的算法,基本上都是使用一个哈希算法先定位分片,然后后续就跟一般的互斥锁一致了。 +用法如下:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// Create a new map.</span> + m <span class="token operator">:=</span> cmap<span class="token punctuation">.</span>New<span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + + <span class="token comment">// Sets item within map, sets "bar" under key "foo"</span> + m<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span><span class="token string">"foo"</span><span class="token punctuation">,</span> <span class="token string">"bar"</span><span class="token punctuation">)</span> + + <span class="token comment">// Retrieve item from map.</span> + bar<span class="token punctuation">,</span> ok <span class="token operator">:=</span> m<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">"foo"</span><span class="token punctuation">)</span> + + <span class="token comment">// Removes item under key "foo"</span> + m<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span><span class="token string">"foo"</span><span class="token punctuation">)</span> +</code></pre></div><h3 id="sync-map">sync.Map</h3> <p>这是 go 官方提供的一个线程安全的 map,先说使用场景,只写一次,大量读的场景。</p> <p>sync.Map 跟分片锁不同,分片锁是直接降低颗粒度,sync.Map 它的基本原理是读写分离,用空间换时间。通过一个只读的数据结构来提高读取速度。</p> <p>当读少写多的时候,它的效率甚至比直接使用互斥锁还低,总之如果不是写少读多的场景,千万不要用,这个包的使用率挺低的。</p> <h2 id="sync-pool">sync.Pool</h2> <p>sync.Pool 是一个对象池,如果我们有一些重复使用的,并且需要频繁的申请和释放的临时对象,那么可以用这个对象池来提高性能。不过这个池子里的对象有可能会被垃圾回收,所以非常重要的数据不能使用这种方法</p> <p>我来描述一种场景,我们有数据需要被 goroutine 去处理,但是谁处理都行,不 care 是哪位,那么我们就可以创建很多的 goroutine,然后放入到 goroutine 池中 (就跟外包一样。。。)</p> <p>sync.Pool 有两个注意事项,首先,它线程安全,其次,不能复制 sync.Pool,如果你复制一个 sync.Pool,实际上得到的只是一个指针的拷贝,并不会复制本地池子,所以多个拷贝的 sync.Pool 指针指向的是同一个本地池子,达不到复用的目的。应该定义一个全局的 sync.Pool 实例,不同的 goroutine 都使用这个实例,才能达到对象复用和减少内存分配的目的</p> <p>pool 包拥有三个方法</p> <ul><li>New,pool 的 new 方法后面跟的是创建的内容,一旦 pool 里面空了,就会调用这个 new 方法,当然你也可以不指定这个参数,那么创建的就是 nil 了</li> <li>Get 从 pool 中获取一个对象</li> <li>Set 将对象送回 pool 中</li></ul> <p>下面举一个演示的例子:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span> buffer <span class="token operator">=</span> sync<span class="token punctuation">.</span>Pool<span class="token punctuation">{</span> + New<span class="token punctuation">:</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> any <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token function">new</span><span class="token punctuation">(</span>bytes<span class="token punctuation">.</span>Buffer<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">,</span> +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">GetBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">*</span>bytes<span class="token punctuation">.</span>Buffer <span class="token punctuation">{</span> + <span class="token keyword">return</span> buffer<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>bytes<span class="token punctuation">.</span>Buffer<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">PutBuffer</span><span class="token punctuation">(</span>buf <span class="token operator">*</span>bytes<span class="token punctuation">.</span>Buffer<span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// Reset会将缓冲区重置为空,但它会保留底层存储以供将来写入使用</span> + buf<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + buffers<span class="token punctuation">.</span><span class="token function">Put</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这段代码是会有内存泄露的风险的,原因也很简单,buf.Reset() 并不会删除底层 slice 的容量,它会保存底层数据结构中的容量,所以 gc 的时候这个 buffer 就非常有可能不会被回收,造成内存泄露</p> <p>改正方法也很简单,底层数据太大了直接丢弃 gc 就 ok 了,小的放到池子里</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">PutBuffer</span><span class="token punctuation">(</span>buf <span class="token operator">*</span>bytes<span class="token punctuation">.</span>Buffer<span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token comment">// Reset会将缓冲区重置为空,但它会保留底层存储以供将来写入使用</span> + buf<span class="token punctuation">.</span><span class="token function">Reset</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> buf<span class="token punctuation">.</span><span class="token function">Cap</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">></span> maxSize<span class="token punctuation">{</span> + <span class="token keyword">return</span> + <span class="token punctuation">}</span> + buffers<span class="token punctuation">.</span><span class="token function">Put</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="pool-内存浪费">pool 内存浪费</h3> <p>当我们需求的内存比池子中的内存小很多的时候,就会造成内存浪费,解决方法就是多造几个池子,比如小池子,中池子,大池子,使用这种方案合理的使用内存</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">var</span><span class="token punctuation">(</span> + readerPool sync<span class="token punctuation">.</span>Pool + reader2kPool sync<span class="token punctuation">.</span>Pool + reader4kPool sync<span class="token punctuation">.</span>Pool +<span class="token punctuation">)</span> +</code></pre></div><p>推荐一个三方库,特点是能更加高效的发挥系统性能节约内存以及避免内存泄露问题等,他可以动态的去调节池子的 dafault size 和 max size</p> <p>https://github.com/valyala/bytebufferpool</p> <p>连接池也是一个很常见的需求,但是通常不会使用 pool,因为 pool 会被 gc,所以并不靠谱,通常我们使用 map 或者 slice 去实现一个需要真的长时间稳定连接的连接池比如:</p> <ul><li>http client 池</li> <li>tcp 连接池,推荐三方库:https://github.com/fatih/pool</li> <li>数据库连接池</li> <li>memcached client 连接池</li></ul> <h3 id="worker-pool">worker pool</h3> <p>worker pool 其实就是 goroutine 的池子,虽然 go 语言的 goroutine 非常的轻量化,但是如果几十万上百万的 goroutine 被创建还是会出问题的</p> <p>因为 goroutine 是一种要求长期存在的资源,所以一般不使用 pool,而是使用 channel 去作为池子,毕竟 channel 自带线程安全</p> <p>Worker pool 的目的是为了重用 goroutine。但它重用的不是 goroutine 本身,而是通过 goroutine 执行任务的能力。</p> <p>如果直接在 channel 中传递 goroutine,那么每个 goroutine 只能执行唯一的一个任务,执行完就退出了。这并没有实现重用。</p> <p>而 worker pool 的设计是:</p> <p>创建固定数量的 goroutine 作为 workers。 +workers 在 loop 中持续从任务 channel 接收任务并执行。 +向任务 channel 不断发送不同的任务。 +这样,每个 worker(goroutine) 就可以执行多个任务,实现重用。</p> <p>所以 channel 中的内容不是 goroutine,而是任务信息,用于指导 goroutine 执行什么任务。goroutine 从 channel 收任务,利用自身的执行能力反复执行不同的任务。</p> <p>这才是 worker pool 设计的核心思想 - 通过固定数量的 goroutine 反复执行不同的任务,以重用 goroutine 实现高效调度。</p> <p>所以,worker pool 的目的是重用 goroutine 的执行能力,而不是重用 goroutine 本身。这是通过 channel+goroutine 的组合实现的,channel 用于传递任务信息,goroutine 负责执行任务</p> <p>让我们简单的实现一个方案:</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">// 任务类型</span> +<span class="token keyword">type</span> Task <span class="token keyword">struct</span> <span class="token punctuation">{</span> + f <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 任务函数</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 执行任务</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>t <span class="token operator">*</span>Task<span class="token punctuation">)</span> <span class="token function">Execute</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + t<span class="token punctuation">.</span><span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 单个worker池 </span> +<span class="token keyword">type</span> Worker <span class="token keyword">struct</span> <span class="token punctuation">{</span> + TaskChan <span class="token keyword">chan</span> <span class="token operator">*</span>Task +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token punctuation">(</span>w <span class="token operator">*</span>Worker<span class="token punctuation">)</span> <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">for</span> <span class="token punctuation">{</span> + task <span class="token operator">:=</span> <span class="token operator"><-</span>w<span class="token punctuation">.</span>TaskChan + task<span class="token punctuation">.</span><span class="token function">Execute</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 为worker 池 分配 goroutine ,这得结合下面的 Newpool 才能看出来</span> +<span class="token keyword">type</span> Pool <span class="token keyword">struct</span> <span class="token punctuation">{</span> + TaskChan <span class="token keyword">chan</span> <span class="token operator">*</span>Task + Workers <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">*</span>Worker +<span class="token punctuation">}</span> + +<span class="token comment">// 创建worker池</span> +<span class="token keyword">func</span> <span class="token function">NewPool</span><span class="token punctuation">(</span>numWorkers <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token operator">*</span>Pool <span class="token punctuation">{</span> + + taskChan <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token operator">*</span>Task<span class="token punctuation">)</span> + + <span class="token comment">// 初始化workers</span> + <span class="token keyword">var</span> workers <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">*</span>Worker + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> numWorkers<span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + worker <span class="token operator">:=</span> <span class="token operator">&</span>Worker<span class="token punctuation">{</span> + TaskChan<span class="token punctuation">:</span> taskChan<span class="token punctuation">,</span> + <span class="token punctuation">}</span> + workers <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>workers<span class="token punctuation">,</span> worker<span class="token punctuation">)</span> + <span class="token keyword">go</span> worker<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + + <span class="token keyword">return</span> <span class="token operator">&</span>Pool<span class="token punctuation">{</span> + TaskChan<span class="token punctuation">:</span> taskChan<span class="token punctuation">,</span> + Workers<span class="token punctuation">:</span> workers<span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 分发任务</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>p <span class="token operator">*</span>Pool<span class="token punctuation">)</span> <span class="token function">Schedule</span><span class="token punctuation">(</span>task <span class="token operator">*</span>Task<span class="token punctuation">)</span> <span class="token punctuation">{</span> + p<span class="token punctuation">.</span>TaskChan <span class="token operator"><-</span> task +<span class="token punctuation">}</span> +</code></pre></div><p>使用方式</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> +<span class="token comment">// 定义任务</span> +task1 <span class="token operator">:=</span> <span class="token operator">&</span>Task<span class="token punctuation">{</span> + f<span class="token punctuation">:</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// do something</span> + <span class="token punctuation">}</span><span class="token punctuation">}</span> + +pool <span class="token operator">:=</span> <span class="token function">NewPool</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span> + +<span class="token comment">// 分发任务</span> +pool<span class="token punctuation">.</span><span class="token function">Schedule</span><span class="token punctuation">(</span>task1<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>提供一些个优秀的 worker pool 方案</p> <ul><li>gammazero/workerpool</li> <li>ivpusic/grpool</li> <li>dpaks/goworkers</li> <li>https://github.com/alitto/pond</li></ul> <h2 id="semaphore">semaphore</h2> <p>信号量 (英语:semaphore) 又称为信号标,是一个同步对象,用于保持在 0 至指定最大值之间的一个计数值。</p> <p>在系统中,给予每一个进程一个信号量,代表每个进程目前的状态,未得到控制权的进程会在特定地方被强迫停下来,等待可以继续进行的信号到来</p> <p>根据信号量的不同可以分为计数信号量和二进制信号量,前者使用一个整数作为信号量,后者使用一个二进制 0 1 作为信号量</p> <p>信号量拥有两个操作:</p> <ul><li>p 操作会减少信号量的数值</li> <li>v 操作会增加信号量的数值</li></ul> <p>其中二进制信号量是特殊的信号量,它就是互斥锁的功能</p> <p>go 语言在 x/sync 中提供了一个 weighted 的包,它就是提供的信号量的功能</p> <ul><li>Acquire p 操作,减少信号量的数值,表示获取了资源 -1</li> <li>Release v 操作,增加信号量的数值,表示释放了资源 +1</li> <li>TryAcquire 尝试获取资源,如果获取成功,则返回 true,否则返回 false +它类似于 trylock 锁,也就是失败直接返回 false,并不会阻塞</li></ul> <p>注意,信号量为了简洁的设计要求,pv 操作使用 +1 和 -1 这种非常简单的递增递减设计,是有意为之的。这种简单性使得信号量在各种同步情况下都很容易理解和正确使用。更复杂的操作可能会引入难以发现的 bug 或误用场景。</p> <p>让我们使用信号量来实现一个 worker pool</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"fmt"</span> + <span class="token string">"log"</span> + <span class="token string">"runtime"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token keyword">var</span> <span class="token punctuation">(</span> + <span class="token comment">// 最大的worker数量</span> + maxWorkers <span class="token operator">=</span> runtime<span class="token punctuation">.</span><span class="token function">GOMAXPROCS</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> + sema <span class="token operator">=</span> semaphore<span class="token punctuation">.</span><span class="token function">NewWeighted</span><span class="token punctuation">(</span><span class="token function">int64</span><span class="token punctuation">(</span>maxWorkers<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">//信号量</span> + task <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span> maxWorkers<span class="token operator">*</span><span class="token number">4</span><span class="token punctuation">)</span> <span class="token comment">// 任务数,是worker的四倍</span> +<span class="token punctuation">)</span> + +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ctx <span class="token operator">:=</span> context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> task <span class="token punctuation">{</span> + <span class="token comment">// 如果没有worker可用,会阻塞在这里,直到某个worker被释放</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> sema<span class="token punctuation">.</span><span class="token function">Acquire</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + <span class="token keyword">break</span> + <span class="token punctuation">}</span> + <span class="token comment">// 启动worker goroutine</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> sema<span class="token punctuation">.</span><span class="token function">Release</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">100</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Millisecond<span class="token punctuation">)</span> <span class="token comment">// 模拟一个耗时操作</span> + task<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> i <span class="token operator">+</span> <span class="token number">1</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token comment">// 请求所有的worker,这样能确保前面的worker都执行完</span> + <span class="token keyword">if</span> err <span class="token operator">:=</span> sema<span class="token punctuation">.</span><span class="token function">Acquire</span><span class="token punctuation">(</span>ctx<span class="token punctuation">,</span> <span class="token function">int64</span><span class="token punctuation">(</span>maxWorkers<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> + log<span class="token punctuation">.</span><span class="token function">Printf</span><span class="token punctuation">(</span><span class="token string">"获取所有的worker失败: %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>task<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="使用信号量时的注意事项">使用信号量时的注意事项</h3> <ul><li>请求了资源,忘记了释放</li> <li>释放了从未请求的资源</li> <li>长时间持有一个资源但是不使用它</li> <li>不持有一个资源,但是直接使用了它</li></ul> <h3 id="使用-channel-去实现一个信号量">使用 channel 去实现一个信号量</h3> <p>使用一个缓存为 n 的 channel 去实现一个信号量</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token string">"sync"</span> + +<span class="token comment">// Semaphore 数据结构,并且还实现了Locker接口</span> +<span class="token keyword">type</span> semaphore <span class="token keyword">struct</span> <span class="token punctuation">{</span> + ch <span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 创建一个新的信号量</span> +<span class="token keyword">func</span> <span class="token function">NewSemaphore</span><span class="token punctuation">(</span>capacity <span class="token builtin">int</span><span class="token punctuation">)</span> sync<span class="token punctuation">.</span>Locker <span class="token punctuation">{</span> + <span class="token keyword">if</span> capacity <span class="token operator"><=</span> <span class="token number">0</span> <span class="token punctuation">{</span> + capacity <span class="token operator">=</span> <span class="token number">1</span> <span class="token comment">// 容量为1就变成了一个互斥锁</span> + <span class="token punctuation">}</span> + <span class="token keyword">return</span> <span class="token operator">&</span>semaphore<span class="token punctuation">{</span>ch<span class="token punctuation">:</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> capacity<span class="token punctuation">)</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 请求一个资源</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>semaphore<span class="token punctuation">)</span> <span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + s<span class="token punctuation">.</span>ch <span class="token operator"><-</span> <span class="token keyword">struct</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 释放资源</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>s <span class="token operator">*</span>semaphore<span class="token punctuation">)</span> <span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token operator"><-</span>s<span class="token punctuation">.</span>ch +<span class="token punctuation">}</span> + +</code></pre></div><h2 id="issues">issues</h2> <h3 id="问题一-有互斥锁就一定有临界区吗">问题一:有互斥锁就一定有临界区吗?</h3> <p>互斥锁的存在不等于必须存在临界区。</p> <p>构成一个合理的临界区,需要满足:</p> <ul><li>有真正需要互斥访问的共享资源 (比如共享内存,变量等)</li> <li>通过加锁,在访问该资源前后形成互斥的代码区域</li> <li>确保同一时间只有一个线程/goroutine 可以进入该互斥区域</li></ul> <p>所以互斥锁只是手段之一,用于保证临界区互斥性的需要。</p> <p>如果没有需要保护的共享资源,或者互斥逻辑不严密,那么使用再多的锁也不等于形成了临界区</p> <h3 id="问题二-如果-mutex-已经被一个-goroutine-获取了锁-其它等待中的-goroutine-们只能一直等待。那么-等这个锁释放后-等待中的-goroutine-中哪一个会优先获取-mutex-呢">问题二:如果 Mutex 已经被一个 goroutine 获取了锁,其它等待中的 goroutine 们只能一直等待。那么,等这个锁释放后,等待中的 goroutine 中哪一个会优先获取 Mutex 呢?</h3> <p>上文中的锁的饥饿模式和正常模式可以解释这个问题。</p> <p>如果是正常的模式下,就是按照正常队列 FIFO 的顺序去获取锁,除非这个时候有新的 goroutine 生成,那么这个 goroutine 会优先获取锁。</p> <p>但是如果一个队头的 goroutine 等待时间过长超过了 1ms,那么它就会将互斥锁的模式变成饥饿模式,自动获取锁</p> <h3 id="问题三-mutext-的底层中-使用-state-和-sema-来表示锁的状态-sema-是信号量-为什么在有信号量表示锁的状态之后还需要一个-state-表示锁是否上锁呢">问题三:Mutext 的底层中,使用 state 和 sema 来表示锁的状态,sema 是信号量,为什么在有信号量表示锁的状态之后还需要一个 state 表示锁是否上锁呢?</h3> <ul><li>state 作为一个 boolean 变量,可以非常简单直观地表示锁的基本状态。</li> <li>sema 是一个整数计数器,可以灵活地表示多种状态,如等待队列长度等。</li> <li>将两者分开,可以清晰地分离基本锁状态和高级同步语义,符合分而治之的设计思想。</li> <li>sema 可直接 reused 现成的信号量实现代码,state 又足够轻量不需要复杂机制。</li> <li>将两者组合可以充分发挥各自的优势,实现一个功能完备但设计简单的 mutex。</li> <li>如果全部只依赖 sema 来表示所有状态,实现可能会更复杂,语义也不够清晰。</li></ul> <h3 id="问题四-使用循环栅栏-信号量去完成经典并发题-水的制造工厂">问题四:使用循环栅栏,信号量去完成经典并发题:水的制造工厂</h3> <div class="language-go extra-class"><pre class="language-go"><code><span class="token comment">//并发趣题:一氧化二氢制造工厂</span> +<span class="token comment">//题目是这样的:</span> +<span class="token comment">//有一个名叫大自然的搬运工的工厂,生产一种叫做一氧化二氢的神秘液体。这种液体的分子是由一个氧原子和两个氢原子组成的,也就是水。</span> +<span class="token comment">//这个工厂有多条生产线,每条生产线负责生产氧原子或者是氢原子,每条生产线由一个 goroutine 负责。</span> +<span class="token comment">//这些生产线会通过一个栅栏,只有一个氧原子生产线和两个氢原子生产线都准备好,才能生成出一个水分子,</span> +<span class="token comment">//否则所有的生产线都会处于等待状态。也就是说,一个水分子必须由三个不同的生产线提供原子,而且水分子是一个一个按照顺序产生的,</span> +<span class="token comment">//每生产一个水分子,就会打印出 HHO、HOH、OHH 三种形式的其中一种。HHH、OOH、OHO、HOO、OOO 都是不允许的。</span> +<span class="token comment">//生产线中氢原子的生产线为 2N 条,氧原子的生产线为 N 条。</span> + +<span class="token keyword">package</span> main + +<span class="token keyword">import</span> <span class="token punctuation">(</span> + <span class="token string">"context"</span> + <span class="token string">"fmt"</span> + <span class="token string">"github.com/marusama/cyclicbarrier"</span> + <span class="token string">"golang.org/x/sync/semaphore"</span> + <span class="token string">"math/rand"</span> + <span class="token string">"sort"</span> + <span class="token string">"sync"</span> + <span class="token string">"time"</span> +<span class="token punctuation">)</span> + +<span class="token comment">// h2o 水的组成,其中我们需要俩h一个o所以我们给定他们信号量,来对他们的任务进行控制。</span> +<span class="token keyword">type</span> H2O <span class="token keyword">struct</span> <span class="token punctuation">{</span> + <span class="token comment">// 控制的h的信号量</span> + seaH <span class="token operator">*</span>semaphore<span class="token punctuation">.</span>Weighted + <span class="token comment">// 控制O的信号量</span> + seaO <span class="token operator">*</span>semaphore<span class="token punctuation">.</span>Weighted + <span class="token comment">// 栅栏,这里也就是重复的使用栅栏,也就是 重复栅栏。</span> + cyc cyclicbarrier<span class="token punctuation">.</span>CyclicBarrier +<span class="token punctuation">}</span> + +<span class="token keyword">func</span> <span class="token function">NewH2O</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span>H2O <span class="token punctuation">{</span> + <span class="token keyword">return</span> <span class="token operator">&</span>H2O<span class="token punctuation">{</span> + <span class="token comment">// h 两个</span> + seaH<span class="token punctuation">:</span> semaphore<span class="token punctuation">.</span><span class="token function">NewWeighted</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span> + <span class="token comment">// o 需要一个</span> + seaO<span class="token punctuation">:</span> semaphore<span class="token punctuation">.</span><span class="token function">NewWeighted</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> + <span class="token comment">// 我们要控制的循环栅栏就是3个,因为一共需要三个嘛。</span> + cyc<span class="token punctuation">:</span> cyclicbarrier<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">,</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 处理h</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>o <span class="token operator">*</span>H2O<span class="token punctuation">)</span> <span class="token function">dealH</span><span class="token punctuation">(</span>outH <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 将这个信号量给拿出来1,因为h充盈来2,所以会有俩线程做这个动作</span> + o<span class="token punctuation">.</span>seaH<span class="token punctuation">.</span><span class="token function">Acquire</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + <span class="token comment">// 输出 h</span> + <span class="token function">outH</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// wait的意思就是不等到三个线程,我就不走</span> + o<span class="token punctuation">.</span>cyc<span class="token punctuation">.</span><span class="token function">Await</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token comment">// 走动完毕后再把资源塞进去。</span> + o<span class="token punctuation">.</span>seaH<span class="token punctuation">.</span><span class="token function">Release</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> + +<span class="token comment">// 处理 o</span> +<span class="token keyword">func</span> <span class="token punctuation">(</span>o <span class="token operator">*</span>H2O<span class="token punctuation">)</span> <span class="token function">dealO</span><span class="token punctuation">(</span>outO <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 氧气将信号量中的信号取出来,</span> + o<span class="token punctuation">.</span>seaO<span class="token punctuation">.</span><span class="token function">Acquire</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + <span class="token comment">// 输出o</span> + <span class="token function">outO</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token comment">// 等待三个线程跟上一个函数一样意思,也不用担心用两次不行,随便用。这个函数调用几次都OK。</span> + o<span class="token punctuation">.</span>cyc<span class="token punctuation">.</span><span class="token function">Await</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token comment">// 释放掉。</span> + o<span class="token punctuation">.</span>seaO<span class="token punctuation">.</span><span class="token function">Release</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// channel 传递信息。</span> + <span class="token keyword">var</span> ch <span class="token keyword">chan</span> <span class="token builtin">string</span> + <span class="token keyword">var</span> outO <span class="token operator">=</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator"><-</span> <span class="token string">"O"</span> + <span class="token punctuation">}</span> + <span class="token keyword">var</span> outH <span class="token operator">=</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + ch <span class="token operator"><-</span> <span class="token string">"H"</span> + <span class="token punctuation">}</span> + <span class="token comment">// 一共有 300个channel需要。</span> + ch <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token number">300</span><span class="token punctuation">)</span> + <span class="token comment">// wg是为了控制这300个线程,栅栏是为了控制生成水的这个控制器,两者的作用不同哦。</span> + wg <span class="token operator">:=</span> <span class="token function">new</span><span class="token punctuation">(</span>sync<span class="token punctuation">.</span>WaitGroup<span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">300</span><span class="token punctuation">)</span> + h <span class="token operator">:=</span> <span class="token function">NewH2O</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span><span class="token function">Duration</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">Intn</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Millisecond<span class="token punctuation">)</span> + h<span class="token punctuation">.</span><span class="token function">dealO</span><span class="token punctuation">(</span>outO<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">200</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span><span class="token function">Duration</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">Intn</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Millisecond<span class="token punctuation">)</span> + h<span class="token punctuation">.</span><span class="token function">dealH</span><span class="token punctuation">(</span>outH<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">if</span> <span class="token function">len</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">300</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">len</span><span class="token punctuation">(</span>ch<span class="token punctuation">)</span><span class="token punctuation">)</span> + <span class="token function">panic</span><span class="token punctuation">(</span><span class="token string">"❌"</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span> + s <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token operator"><-</span>ch + s<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token operator"><-</span>ch + s<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token operator"><-</span>ch + <span class="token comment">// 这里,对于hho进行排序了,不然也不一定是hho这个顺序</span> + sort<span class="token punctuation">.</span><span class="token function">Strings</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + result <span class="token operator">:=</span> s<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">+</span> s<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> s<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> + <span class="token keyword">if</span> result <span class="token operator">!=</span> <span class="token string">"HHO"</span> <span class="token punctuation">{</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"错误 ❌ :"</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span> +</code></pre></div><h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/iPpWd8vjyaN2sJFwxzN9Bg</li> <li>https://draveness.me/golang/docs/part3-runtime/ch06-concurrency/golang-sync-primitives/</li> <li>https://time.geekbang.org/column/intro/100061801</li> <li>https://colobu.com/2018/12/18/dive-into-sync-mutex/</li> <li>《go 语言精进之路》</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/同步原语/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">1/16/2024, 9:10:50 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/11.25dd6abf.js" defer></script> + </body> +</html> diff --git "a/\345\271\266\345\217\221/\345\271\266\345\217\221\346\250\241\345\236\213/index.html" "b/\345\271\266\345\217\221/\345\271\266\345\217\221\346\250\241\345\236\213/index.html" new file mode 100644 index 000000000..e73225ab1 --- /dev/null +++ "b/\345\271\266\345\217\221/\345\271\266\345\217\221\346\250\241\345\236\213/index.html" @@ -0,0 +1,95 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/108.90ae536a.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#并发和并行的关系" class="sidebar-link">并发和并行的关系</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#多线程并发模型" class="sidebar-link">多线程并发模型</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#csp" class="sidebar-link">csp</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#了解-goroutine" class="sidebar-link">了解 goroutine</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#创建-goroutine" class="sidebar-link">创建 goroutine</a></li><li class="sidebar-sub-header"><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#goroutine-退出" class="sidebar-link">goroutine 退出</a></li></ul></li><li><a href="/GOFamily/%E5%B9%B6%E5%8F%91/%E5%B9%B6%E5%8F%91%E6%A8%A1%E5%9E%8B/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-并发模型">go 并发模型</h1> <h2 id="并发和并行的关系">并发和并行的关系</h2> <p>并发是问题域的一种概念,它强调处理多个同时 (或者近似同时) 发生的事件。</p> <p>并行是方法域的一种概念,将问题分解为多个部分,同时并行执行来加速解决问题。</p> <blockquote><p>rob pike:并发不是并行,并发关乎结构,并行关乎执行</p></blockquote> <p>并发:一位老师,在听一个学生朗读的时候,她可以暂停学生的朗读,然后回答学生的问题,再次开始学生的朗读,虽然她一次只能干一件事,但是这也能看作处理多个近乎同时发生的事件</p> <p>并发和并行:两位老师,一个老师提问,一个老师解决学生的问题,这就是满足了并行和并发</p> <p>并行但不是并发:让全班同学制作贺卡,全班同学每个学生制作五枚,全班同学同时开始做,只能是并行,但不是并发,因为只有一个事件。</p> <h2 id="多线程并发模型">多线程并发模型</h2> <p>使用共享内存的方式去完成并发就是多线程并发模型,它的核心就是使用锁的方法,让某个线程单独拥有某块内存,其他线程只能访问该内存,从而实现了并发。</p> <p>go 语言中的锁就是 sync.Mutex,这也是 go 语言实现多线程并发的核心,一共有:</p> <ul><li>sync.Mutex 互斥锁,可以同时对一个资源进行读写操作,但是只能有一个线程可以对该资源进行写操作。</li> <li>sync.RWMutex 读写锁,可以同时对一个资源进行读操作,但是只能有一个写操作</li> <li>sync.Cond 条件变量,可以让一个线程等待另一个线程满足某个条件</li> <li>sync.Once 单例模式,保证某个资源只被初始化一次</li> <li>sync.Pool 资源池,可以让一个资源在内存中被复用,避免了重复创建资源的开销</li> <li>sync.Map 线程安全的 map,可以让多个线程安全的对 map 进行读写操作</li> <li>sync.Pool 资源池,可以让一个资源在内存中被复用,避免了重复创建资源的开销</li> <li>sync.WaitGroup 等待组,可以让多个线程等待,直到某个线程完成某个任务</li> <li>golang.org/x/sync/errgroup 为处理公共任务的子任务的 goroutine 组提供同步、错误传播和上下文取消</li> <li>golang.org/x/sync/semaphore 提供了一个加权信号量实现。</li> <li>golang.org/x/sync/singleflight 提供了重复函数调用抑制机制,中文叫栅栏机制</li> <li>golang.org/x/sync/syncmap 提供了一个并发映射实现</li></ul> <h2 id="csp">csp</h2> <p>go 语言推荐的并发模型使用的就是 csp 模型,csp 的核心思想就是讲各个任务等同于进程,进程顺序执行互不牵连,进程可以收发信息,使用通道的方式进行信息的通信。</p> <p>所以如果使用 channel 的方式进行通信就是使用的 csp 并发模型</p> <p>CSP 模型中的进程通信原语包括:</p> <ul><li>发送消息:一个进程可以通过发送消息到另一个进程来与之进行通信。</li> <li>接收消息:一个进程可以通过接收消息来获取另一个进程发送的消息。</li> <li>原子发送-接收:一个进程可以通过原子发送-接收操作来发送消息并等待接收消息,这相当于发送和接收两个操作的组合。</li></ul> <p>这些进程通信的都是通过内置的 channel 对象去实现的。</p> <h2 id="了解-goroutine">了解 goroutine</h2> <p>这里我们现简单的了解一些基本的使用 goroutne 的方法,后面的 channel 篇和并发原语 context atomic 定时器会进行更加详细的介绍。</p> <p>我们知道 go 使用了用户线程也就是 goroutine 去替代了传统的线程,所以在 go 语言中我们能操作的线程就是 goroutine,我们无法去触及真实的线程,线程和 goroutine 之间的关系是 go 语言运行时的调度器去调度的。</p> <h3 id="创建-goroutine">创建 goroutine</h3> <p>使用 go 关键字加上函数去创建一个 goroutine,当然后面跟方法也可以。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 注意后面跟的是一个函数的运行,这跟 defer 一致</span> + c <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token keyword">chan</span> <span class="token builtin">int</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">10000</span><span class="token punctuation">)</span> + c <span class="token operator"><-</span> <span class="token number">12</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + d <span class="token operator">:=</span> <span class="token operator"><-</span>c + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>d<span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>我们可以看到,这里使用了 csp 的并发模型,下面我们看一下使用传统的共享内存的并发模式</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token comment">// 注意后面跟的是一个函数的运行,这跟 defer 一致</span> + <span class="token keyword">var</span> mu sync<span class="token punctuation">.</span>Mutex + <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span>i <span class="token builtin">int</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + mu<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token keyword">defer</span> mu<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span> + <span class="token punctuation">}</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><h3 id="goroutine-退出">goroutine 退出</h3> <p>goroutine 使用代价很低,因为它并不是操作系统的线程,创建成本非常低,go 推荐可以多多使用 goroutine</p> <p>goroutine 退出有两种方式:</p> <ul><li>主动退出:使用 return 或者 panic 关键字退出</li> <li>非主动退出:使用 sync.WaitGroup,context 等方法,当所有的 goroutine 都退出后,等待组会自动退出</li></ul> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">var</span> wg sync<span class="token punctuation">.</span>WaitGroup + wg<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> + <span class="token keyword">go</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">defer</span> wg<span class="token punctuation">.</span><span class="token function">Done</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + wg<span class="token punctuation">.</span><span class="token function">Wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>go goroutine 执行完毕就会直接退出,程序的执行跟主 goroutine 有关,只要主 goroutine 不退出程序就会正常执行下去,反之,主 goroutine 如果退出了,其它的 goroutine 可能没有执行完毕,但是整个程序还是结束了。</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">10000</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi there"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>这个程序将无法保证能输出 hi there</p> <p>要想让 age 输出正常的值,必须保证主 goroutine 不能退出,比如使用 sync.WaitGroup,比如直接让主 goroutine 休眠</p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">go</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">20000</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +<span class="token keyword">func</span> <span class="token function">age</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span><span class="token number">10000</span><span class="token punctuation">)</span> + fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"hi there"</span><span class="token punctuation">)</span> +<span class="token punctuation">}</span> +</code></pre></div><p>下面让我们正式学习 go 并发语言,channel 等相关知识!</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://mp.weixin.qq.com/s/TvHY2i1FX1zS_WHdCvK-wA</li> <li>https://book.douban.com/subject/26337939/</li> <li>https://book.douban.com/subject/35720728/ 315 页 - 317 页</li> <li>极客时间《go 进阶训练营》</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/并发/并发模型/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/27/2023, 8:26:59 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/108.90ae536a.js" defer></script> + </body> +</html> diff --git "a/\347\274\226\350\257\221\345\231\250/gc/index.html" "b/\347\274\226\350\257\221\345\231\250/gc/index.html" new file mode 100644 index 000000000..c8ea164b7 --- /dev/null +++ "b/\347\274\226\350\257\221\345\231\250/gc/index.html" @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/110.9afae874.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/gc/#前端组件" class="sidebar-link">前端组件</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/gc/#中端组件" class="sidebar-link">中端组件</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/gc/#后端组件" class="sidebar-link">后端组件</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/gc/#参考资料" class="sidebar-link">参考资料</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-语言官方编译器-gc">go 语言官方编译器 gc</h1> <h2 id="前端组件">前端组件</h2> <ul><li>Lexer:进行词法分析,将代码分割成词法单元</li> <li>Parser:进行语法分析,检查代码正确性,生成 AST</li> <li>Type checker:进行类型检查,确保类型使用正确</li></ul> <h2 id="中端组件">中端组件</h2> <ul><li>SSA:构建程序的静态单赋值形式中间表示</li> <li>Optimizer:进行各种形式的优化,如内联、逃逸分析等</li></ul> <h2 id="后端组件">后端组件</h2> <ul><li>Code generator:将优化后的代码生成对应的汇编代码</li> <li>Assembler:汇编器,将汇编代码转换为机器代码</li> <li>Linker:链接器,将对象代码链接成最终的可执行文件</li> <li>运行时,Runtime:提供垃圾回收、协程调度等运行时功能</li></ul> <p>gc 不仅包含 frontend,还包含了中间 representation、优化器、代码生成器等组件,可以完成 Go 代码的全部编译工作。它既是一个编译器,也提供了部分运行时支持。所以说 gc 是 Go 语言的整体编译与工具链解决方案。</p> <p>gc 编译器由 Go 语言的创造者 Robert Griesemer、Rob Pike 及 Ken Thompson 开发,首次在2007年与 Go 一起开源发布。</p> <p>gc 实现了对 Go 语言的完整支持,可以编译包括复杂特性如 goroutine、channel 和接口在内的所有 Go 语言程序。它输出自包含的可执行文件,不需要外部依赖。</p> <p>gc 编译器写在 Go 语言本身并采用了 Go 的并发特性,编译速度非常快。它与 Go 的发布周期同步,确保语言 feature 得到及时支持。</p> <p>所以 Go 语言默认编译器的全称就是 gc,它是官方提供的 Go 语言编译器。</p> <h2 id="参考资料">参考资料</h2> <ul><li>https://go.dev/src/cmd/compile/README</li></ul></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/编译器/gc/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">12/6/2023, 8:24:47 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/110.9afae874.js" defer></script> + </body> +</html> diff --git "a/\347\274\226\350\257\221\345\231\250/gccgo/index.html" "b/\347\274\226\350\257\221\345\231\250/gccgo/index.html" new file mode 100644 index 000000000..646efdc4e --- /dev/null +++ "b/\347\274\226\350\257\221\345\231\250/gccgo/index.html" @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>gccgo | GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/111.fcb96ca2.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>gccgo</span> <!----></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="gccgo">gccgo</h1> <p>gccgo 是 Gо 语言到 C 语言的编译器,它将 Gо 语言源代码编译成 C 语言源代码。</p> <p>gccgo 本身只是一个编译器前端,负责解析 Gо 语言代码并生成 C 语言代码。要生成最终的可执行文件,还需要一个编译器后端。</p> <p>gccgo 常见的后端有:</p> <p>gcc - GNU 编译器,可以将 gccgo 生成的 C 语言代码进一步编译成机器代码,生成最终的可执行文件。 +clang - LLVM 编译器,同样可以将 C 语言编译成机器代码。 +tcc - Tiny C Compiler,一个小型快速的 C 语言编译器。 +所以简单来说,gccgo 编译器的常见后端是 gcc 和 clang。完整的编译流程是:</p> <p>gccgo 前端 → C 语言代码 → gcc/clang 后端 → 机器代码 (可执行文件)</p> <p>开发者可以根据需要选择不同的编译器后端,来编译 gccgo 生成的 C 语言代码。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/编译器/gccgo/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/17/2023, 4:42:45 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/111.fcb96ca2.js" defer></script> + </body> +</html> diff --git "a/\347\274\226\350\257\221\345\231\250/index.html" "b/\347\274\226\350\257\221\345\231\250/index.html" new file mode 100644 index 000000000..0ca8d090c --- /dev/null +++ "b/\347\274\226\350\257\221\345\231\250/index.html" @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/109.55b5f850.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/112.9e9125b6.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/#编译器概述" class="sidebar-link">编译器概述</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/#编译器特性" class="sidebar-link">编译器特性</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/#编译器实战" class="sidebar-link">编译器实战</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/#编译器源码" class="sidebar-link">编译器源码</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/#其他编译器" class="sidebar-link">其他编译器</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="go-编译器">go 编译器</h1> <h2 id="编译器概述">编译器概述</h2> <p>默认编译器 gc 介绍 +编译原理和过程 +编译器组件工具链 +编译优化技术</p> <h2 id="编译器特性">编译器特性</h2> <p>编译速度快 +生成自包含可执行文件 +内存安全保证 +跨平台支持 +模块化支持</p> <h2 id="编译器实战">编译器实战</h2> <p>常见编译错误和解决方法 +编译参数和定制 +增量编译 +hook 编译过程 +交叉编译</p> <h2 id="编译器源码">编译器源码</h2> <p>gc 编译器源码解析 +编译器前端实现 +编译器后端实现</p> <h2 id="其他编译器">其他编译器</h2> <p>gccgo +gollvm +编译器比较</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/编译器/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/17/2023, 4:42:45 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/109.55b5f850.js" defer></script> + </body> +</html> diff --git "a/\347\274\226\350\257\221\345\231\250/llvm/index.html" "b/\347\274\226\350\257\221\345\231\250/llvm/index.html" new file mode 100644 index 000000000..e7d35e505 --- /dev/null +++ "b/\347\274\226\350\257\221\345\231\250/llvm/index.html" @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html lang="en-US"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width,initial-scale=1"> + <title>GOFamily - go 程序员宝典</title> + <meta name="generator" content="VuePress 1.9.7"> + <link rel="shortcut icon" type="image/x-icon" href="/GOFamily/favicon.ico"> + <meta name="description" content="🔥 go 程序员宝典,包含了:算法,数据库,网络操作系统,分布式,系统设计等一揽子知识体系"> + + <link rel="preload" href="/GOFamily/assets/css/0.styles.93ee3edc.css" as="style"><link rel="preload" href="/GOFamily/assets/js/app.dbd5dba2.js" as="script"><link rel="preload" href="/GOFamily/assets/js/2.5c331e53.js" as="script"><link rel="preload" href="/GOFamily/assets/js/112.9e9125b6.js" as="script"><link rel="prefetch" href="/GOFamily/assets/js/10.993cf521.js"><link rel="prefetch" href="/GOFamily/assets/js/100.049dca94.js"><link rel="prefetch" href="/GOFamily/assets/js/101.9e4a3cce.js"><link rel="prefetch" href="/GOFamily/assets/js/102.60455322.js"><link rel="prefetch" href="/GOFamily/assets/js/103.4ebce8b3.js"><link rel="prefetch" href="/GOFamily/assets/js/104.dcbef6d1.js"><link rel="prefetch" href="/GOFamily/assets/js/105.76803baf.js"><link rel="prefetch" href="/GOFamily/assets/js/106.26567b10.js"><link rel="prefetch" href="/GOFamily/assets/js/107.c757198e.js"><link rel="prefetch" href="/GOFamily/assets/js/108.90ae536a.js"><link rel="prefetch" href="/GOFamily/assets/js/109.55b5f850.js"><link rel="prefetch" href="/GOFamily/assets/js/11.25dd6abf.js"><link rel="prefetch" href="/GOFamily/assets/js/110.9afae874.js"><link rel="prefetch" href="/GOFamily/assets/js/111.fcb96ca2.js"><link rel="prefetch" href="/GOFamily/assets/js/12.521ef871.js"><link rel="prefetch" href="/GOFamily/assets/js/13.6a579e8b.js"><link rel="prefetch" href="/GOFamily/assets/js/14.fa863532.js"><link rel="prefetch" href="/GOFamily/assets/js/15.ccbbdb7a.js"><link rel="prefetch" href="/GOFamily/assets/js/16.d5f6c328.js"><link rel="prefetch" href="/GOFamily/assets/js/17.1312d121.js"><link rel="prefetch" href="/GOFamily/assets/js/18.4b8a1599.js"><link rel="prefetch" href="/GOFamily/assets/js/19.5ed73af4.js"><link rel="prefetch" href="/GOFamily/assets/js/20.fea9a837.js"><link rel="prefetch" href="/GOFamily/assets/js/21.321b1448.js"><link rel="prefetch" href="/GOFamily/assets/js/22.e3bbafa7.js"><link rel="prefetch" href="/GOFamily/assets/js/23.6633ca8a.js"><link rel="prefetch" href="/GOFamily/assets/js/24.edf743ad.js"><link rel="prefetch" href="/GOFamily/assets/js/25.831fd7ee.js"><link rel="prefetch" href="/GOFamily/assets/js/26.83ccb127.js"><link rel="prefetch" href="/GOFamily/assets/js/27.d1524f5d.js"><link rel="prefetch" href="/GOFamily/assets/js/28.69e5608b.js"><link rel="prefetch" href="/GOFamily/assets/js/29.742dd6e8.js"><link rel="prefetch" href="/GOFamily/assets/js/3.a22689ce.js"><link rel="prefetch" href="/GOFamily/assets/js/30.4aafb94a.js"><link rel="prefetch" href="/GOFamily/assets/js/31.87baab0b.js"><link rel="prefetch" href="/GOFamily/assets/js/32.1ea926c5.js"><link rel="prefetch" href="/GOFamily/assets/js/33.4d31d0db.js"><link rel="prefetch" href="/GOFamily/assets/js/34.7610889f.js"><link rel="prefetch" href="/GOFamily/assets/js/35.32a9ec30.js"><link rel="prefetch" href="/GOFamily/assets/js/36.8d562ec5.js"><link rel="prefetch" href="/GOFamily/assets/js/37.18cb13d8.js"><link rel="prefetch" href="/GOFamily/assets/js/38.53670642.js"><link rel="prefetch" href="/GOFamily/assets/js/39.9c8315fb.js"><link rel="prefetch" href="/GOFamily/assets/js/4.a73c4d70.js"><link rel="prefetch" href="/GOFamily/assets/js/40.3bf1fd84.js"><link rel="prefetch" href="/GOFamily/assets/js/41.73deb46e.js"><link rel="prefetch" href="/GOFamily/assets/js/42.85cfacd9.js"><link rel="prefetch" href="/GOFamily/assets/js/43.1b441a63.js"><link rel="prefetch" href="/GOFamily/assets/js/44.5dc33e34.js"><link rel="prefetch" href="/GOFamily/assets/js/45.b2f02d30.js"><link rel="prefetch" href="/GOFamily/assets/js/46.7fef4e9d.js"><link rel="prefetch" href="/GOFamily/assets/js/47.6dd9b6a9.js"><link rel="prefetch" href="/GOFamily/assets/js/48.e525f69a.js"><link rel="prefetch" href="/GOFamily/assets/js/49.565c30a8.js"><link rel="prefetch" href="/GOFamily/assets/js/5.864fc44c.js"><link rel="prefetch" href="/GOFamily/assets/js/50.249734db.js"><link rel="prefetch" href="/GOFamily/assets/js/51.9dd5ff4a.js"><link rel="prefetch" href="/GOFamily/assets/js/52.9dfffd13.js"><link rel="prefetch" href="/GOFamily/assets/js/53.c98436b4.js"><link rel="prefetch" href="/GOFamily/assets/js/54.ee26f0f5.js"><link rel="prefetch" href="/GOFamily/assets/js/55.7b5dc58d.js"><link rel="prefetch" href="/GOFamily/assets/js/56.e3024720.js"><link rel="prefetch" href="/GOFamily/assets/js/57.ba1b4c58.js"><link rel="prefetch" href="/GOFamily/assets/js/58.d6c32d73.js"><link rel="prefetch" href="/GOFamily/assets/js/59.a733d97b.js"><link rel="prefetch" href="/GOFamily/assets/js/6.5f593451.js"><link rel="prefetch" href="/GOFamily/assets/js/60.f162e276.js"><link rel="prefetch" href="/GOFamily/assets/js/61.155a3987.js"><link rel="prefetch" href="/GOFamily/assets/js/62.ad6d715b.js"><link rel="prefetch" href="/GOFamily/assets/js/63.088bb315.js"><link rel="prefetch" href="/GOFamily/assets/js/64.58e4a79c.js"><link rel="prefetch" href="/GOFamily/assets/js/65.9e82002d.js"><link rel="prefetch" href="/GOFamily/assets/js/66.949483d3.js"><link rel="prefetch" href="/GOFamily/assets/js/67.613f77e3.js"><link rel="prefetch" href="/GOFamily/assets/js/68.f73d44cf.js"><link rel="prefetch" href="/GOFamily/assets/js/69.a717baf8.js"><link rel="prefetch" href="/GOFamily/assets/js/7.5280db48.js"><link rel="prefetch" href="/GOFamily/assets/js/70.b3476fa3.js"><link rel="prefetch" href="/GOFamily/assets/js/71.57746954.js"><link rel="prefetch" href="/GOFamily/assets/js/72.4cc3186e.js"><link rel="prefetch" href="/GOFamily/assets/js/73.03d8974c.js"><link rel="prefetch" href="/GOFamily/assets/js/74.4f1eeb3c.js"><link rel="prefetch" href="/GOFamily/assets/js/75.d44fc2e7.js"><link rel="prefetch" href="/GOFamily/assets/js/76.f53bf284.js"><link rel="prefetch" href="/GOFamily/assets/js/77.bad2588a.js"><link rel="prefetch" href="/GOFamily/assets/js/78.2ee31447.js"><link rel="prefetch" href="/GOFamily/assets/js/79.f5c3f20d.js"><link rel="prefetch" href="/GOFamily/assets/js/8.ff976029.js"><link rel="prefetch" href="/GOFamily/assets/js/80.5aa44af4.js"><link rel="prefetch" href="/GOFamily/assets/js/81.33455a03.js"><link rel="prefetch" href="/GOFamily/assets/js/82.9f2284bd.js"><link rel="prefetch" href="/GOFamily/assets/js/83.5e222179.js"><link rel="prefetch" href="/GOFamily/assets/js/84.b93653e7.js"><link rel="prefetch" href="/GOFamily/assets/js/85.aff346f9.js"><link rel="prefetch" href="/GOFamily/assets/js/86.ca707802.js"><link rel="prefetch" href="/GOFamily/assets/js/87.d9bc2332.js"><link rel="prefetch" href="/GOFamily/assets/js/88.87973a44.js"><link rel="prefetch" href="/GOFamily/assets/js/89.37b7fea9.js"><link rel="prefetch" href="/GOFamily/assets/js/9.e2b0263e.js"><link rel="prefetch" href="/GOFamily/assets/js/90.dedfc540.js"><link rel="prefetch" href="/GOFamily/assets/js/91.dbd4ca9b.js"><link rel="prefetch" href="/GOFamily/assets/js/92.61c0947f.js"><link rel="prefetch" href="/GOFamily/assets/js/93.eaa3fe92.js"><link rel="prefetch" href="/GOFamily/assets/js/94.c3c51d69.js"><link rel="prefetch" href="/GOFamily/assets/js/95.d1eac759.js"><link rel="prefetch" href="/GOFamily/assets/js/96.add14987.js"><link rel="prefetch" href="/GOFamily/assets/js/97.357d16bb.js"><link rel="prefetch" href="/GOFamily/assets/js/98.fe5446fa.js"><link rel="prefetch" href="/GOFamily/assets/js/99.c9fd11f7.js"> + <link rel="stylesheet" href="/GOFamily/assets/css/0.styles.93ee3edc.css"> + </head> + <body> + <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/GOFamily/" class="home-link router-link-active"><img src="https://avatars.githubusercontent.com/u/42873232" alt="GOFamily - go 程序员宝典" class="logo"> <span class="site-name can-hide">GOFamily - go 程序员宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/GOFamily/" class="nav-link"> + 首页 +</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Menu" class="dropdown-title"><span class="title">系列教程</span> <span class="arrow down"></span></button> <button type="button" aria-label="Menu" class="mobile-dropdown-title"><span class="title">系列教程</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/GOFamily/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + GOFamily 【go语言教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/408/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 408 【基础408知识教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/luban/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + luban 【系统设计教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/dingdang/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + dingdang 【工具教程】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://shgopher.github.io/god/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + god 【给程序员写的书】 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="https://shgopher.github.io/" target="_blank" rel="noopener noreferrer" class="nav-link external"> + 作者 + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <a href="https://github.com/shgopher/GOFamily" target="_blank" rel="noopener noreferrer" class="repo-link"> + GitHub + <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span></span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/#gollvm" class="sidebar-link">gollvm</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/#可以通过修改-go-compiler-工具链-在编译过程中调用-llvm-pass-执行优化。" class="sidebar-link">可以通过修改 Go Compiler 工具链,在编译过程中调用 LLVM Pass 执行优化。</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/GOFamily/%E7%BC%96%E8%AF%91%E5%99%A8/llvm/#llvm-golang" class="sidebar-link">llvm -golang</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="llvm">llvm</h1> <p>LLVM 可以通过以下两种主要方式为 Go 语言代码提供编译支持:</p> <h2 id="gollvm">gollvm</h2> <p>gollvm 项目实现了将 Go 代码编译为 LLVM IR 的 frontend。它可以直接生成 LLVM IR,然后通过 LLVM 进行后端代码生成。</p> <p>主要步骤是:</p> <ul><li>gollvm 解析 Go 代码,生成对应的 LLVM IR</li> <li>执行 LLVM 优化流水线进行优化</li> <li>LLVM 后端生成目标平台的机器码</li> <li>嵌入 LLVM pass</li></ul> <h2 id="可以通过修改-go-compiler-工具链-在编译过程中调用-llvm-pass-执行优化。">可以通过修改 Go Compiler 工具链,在编译过程中调用 LLVM Pass 执行优化。</h2> <p>主要步骤是:</p> <ul><li>Go Compiler 前端生成 initial IR</li> <li>将 IR 传递给 LLVM Pass 执行优化</li> <li>LLVM Pass 输出优化后的 IR</li> <li>Go Compiler 后端根据 IR 生成机器码</li></ul> <p>这种方式需要 invasive 修改 Go 编译器,较为复杂。</p> <p>总结:</p> <p>gollvm 通过完全 External 的方式引入 LLVM,而嵌入 LLVM Pass 需要修改 Go Compiler。</p> <p>gollvm 方式集成更简单,但是需要保证 IR 的转换正确性;嵌入 Pass 可以利用 Go Compiler 的 Context 信息进行更准确的优化。</p> <p>根据需求和成本进行抉择。</p> <h2 id="llvm-golang">llvm -golang</h2> <p>llvm-golang 是另一个用于 Go 语言编译的 LLVM 集成项目。</p> <p>它与 gollvm 的主要区别有:</p> <p>实现方式不同</p> <ul><li>gollvm 是独立的 Go frontend,将 Go 代码编译成 LLVM IR</li> <li>llvm-golang 直接使用 LLVM 对 Go 代码进行编译 +编译入口不同</li> <li>gollvm 通过调用 gollvm 命令,传入 Go 源文件</li> <li>llvm-golang 编译时调用 clang 命令,并使用-femulate-llvm-golang 参数 +编译过程不同</li> <li>gollvm 编译生成完整的 LLVM IR 然后优化</li> <li>llvm-golang 是逐函数生成 LLVM IR 并编译 +项目状态不同</li> <li>gollvm 活跃维护,可正常使用</li> <li>llvm-golang 最后更新在5年前,未维护 +总之,llvm-golang 是直接使用 LLVM 编译 Go 的早期尝试,但维护情况不佳。gollvm 作为独立 frontend 集成 LLVM,是更可靠的解决方案。</li></ul> <p>但 llvm-golang 的直接编译方式也具有借鉴意义,合理结合两种方式可以获得更好的 LLVM 集成效果。</p></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/shgopher/GOFamily/edit/release/编译器/llvm/README.md" target="_blank" rel="noopener noreferrer">在GitHub中编辑</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最后更新:</span> <span class="time">11/17/2023, 4:42:45 AM</span></div></footer> <!----> </main></div><div class="global-ui"><!----></div></div> + <script src="/GOFamily/assets/js/app.dbd5dba2.js" defer></script><script src="/GOFamily/assets/js/2.5c331e53.js" defer></script><script src="/GOFamily/assets/js/112.9e9125b6.js" defer></script> + </body> +</html>