<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你能答對這道 Go 題目嗎?超過 80% 的人都答錯了...

          共 2254字,需瀏覽 5分鐘

           ·

          2022-03-18 12:45

          大家好,我是煎魚。

          最近在沖浪的時候,看到 Redhat 首席軟件工程師、Prometheus 等項目的維護(hù)者 Bart?omiej P?otka 在 twitter 上出了一道 Go 的 “考題”,說是要來考考大家。

          題目如下:

          func?aaa()?(done?func(),?err?error)?{
          ?return?func()?{?
          ???print("aaa:?done")?
          ?},?nil
          }

          func?bbb()?(done?func(),?_?error)?{
          ?done,?err?:=?aaa()
          ?return?func()?{?
          ???print("bbb:?surprise!");?
          ???done()?
          ?},?err
          }

          func?main()?{
          ?done,?_?:=?bbb()
          ?done()
          }

          答案的選項如下:

          想想原因,思考一下輸出結(jié)果是什么?是 A,還是 D?還是三短一長,選 B?

          分析程序

          縮小范圍,核心關(guān)注到這塊代碼。如下:

          func?bbb()?(done?func(),?_?error)?{
          ?done,?err?:=?aaa()
          ?return?func()?{?
          ???print("bbb:?surprise!")
          ???done()?
          ?},?err
          }

          在最后一行的這個閉包(匿名函數(shù))中,大家可能認(rèn)為程序調(diào)用了函數(shù) aaa 所返回的 done 值來輸出程序,應(yīng)當(dāng)是:

          aaa:?done

          這個想法是錯誤的,程序沒有這么去運(yùn)作。

          原因在于 return 實(shí)際上是一個賦值語句。結(jié)合程序,可以看到函數(shù) bbb 的第一個返回值是 done 參數(shù)。

          如下:

          func?bbb()?(done?func(),?_?error)

          也就是在函數(shù) bbb 在程序最后執(zhí)行 return 語句后,會對返回變量 done 進(jìn)行賦值,自然該值不會是由函數(shù) aaa 所設(shè)置的了。

          這是一個關(guān)鍵的地方。

          具體過程

          這個程序輸出結(jié)果是什么呢?

          會不斷地遞歸,瘋狂輸出 “bbb: surprise!”,直至棧溢出,導(dǎo)致程序運(yùn)行出錯,最終中止

          同學(xué)就疑惑了,怎么又多出了個遞歸?

          我們再看看程序:

          func?main()?{
          ?done,?_?:=?bbb()
          ?done()
          }

          func?bbb()?(done?func(),?_?error)?{
          ?...
          ?return?func()?{?
          ???print("bbb:?surprise!");?
          ???done()?
          ?},?err
          }

          本質(zhì)上在函數(shù) bbb 執(zhí)行完畢后,?變量 done 已經(jīng)變成了一個遞歸函數(shù)。

          遞歸的過程是:函數(shù) bbb 調(diào)用變量 done 后,會輸出 bbb: surprise! 字符串,然后又調(diào)用變量 done。而變量 done 又是這個閉包(匿名函數(shù)),從而實(shí)現(xiàn)不斷遞歸調(diào)用和輸出。

          最終結(jié)果如下:

          b:?surprise!bbb:?surprise!bbb:?surprise!runtime:?goroutine?stack?exceeds?1000000000-byte?limit
          runtime:?sp=0xc0200e0380?stack=[0xc0200e0000,?0xc0400e0000]
          fatal?error:?stack?overflow

          runtime?stack:
          runtime.throw(0x1074b5a,?0xe)
          ????????/usr/local/Cellar/go/1.16.6/libexec/src/runtime/panic.go:1117?+0x72
          runtime.newstack()
          ????????/usr/local/Cellar/go/1.16.6/libexec/src/runtime/stack.go:1069?+0x7ed
          runtime.morestack()
          ????????/usr/local/Cellar/go/1.16.6/libexec/src/runtime/asm_amd64.s:458?+0x8f
          ...

          也就是正確答案是:D,程序最終運(yùn)行出錯。

          一直調(diào)用一直爽,直至棧溢出程序崩潰。

          總結(jié)

          這位大佬出的題目,本質(zhì)上是比較煩人的,其結(jié)合了函數(shù)返回參數(shù)的命名用法。

          如果我們把這個函數(shù)的返回參數(shù)命名去掉,就可以避開這個問題。如下:

          func?bbb()?(func(),?error)?{
          ?...
          ?return?func()?{?
          ???print("bbb:?surprise!");?
          ???done()?
          ?},?err
          }
          ...

          輸出結(jié)果為 "bbb: surprise!"。

          很多 Go 的同學(xué)在日常代碼編寫的時候不會用到或注意到。但如果寫的時候有類似案例代碼中的模式,就會排查許久都查不到。

          這是個有警惕意義的題目,你覺得呢?

          參考

          • twitter 上的原題目
          • Go 語言返回值是引用時return后省略是推薦寫法嗎?

          關(guān)注煎魚,獲取業(yè)內(nèi)第一手消息和知識 ??



          你好,我是煎魚,出版過 Go 暢銷書《Go 語言編程之旅》,再到獲得 GOP(Go 領(lǐng)域最有觀點(diǎn)專家)榮譽(yù),點(diǎn)擊藍(lán)字查看我的出書之路。

          日常分享高質(zhì)量文章,輸出 Go 面試、工作經(jīng)驗、架構(gòu)設(shè)計,加微信拉讀者交流群,和大家交流!

          瀏覽 35
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆成人免费视频在线观看 | 91久久艹这里只有精品 | 国产无码精品黄色电影 | 国产成人无码AV在线专区 | 97色色欧美 |