<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 切片相關(guān)面試題

          共 2020字,需瀏覽 5分鐘

           ·

          2022-01-04 21:13



          399dde02e255c225d4bc2db0c76e7479.webp來(lái)自軒脈刃的刀光劍影

          這篇是關(guān)于go切片的一些問(wèn)題和回答。

          go的切片基本上是代碼中使用最多的一種數(shù)據(jù)結(jié)構(gòu)了,使用這種數(shù)據(jù)結(jié)構(gòu)有哪些要注意的點(diǎn),這個(gè)是非常必要了解的東西。基本上,以前寫的一篇博客 https://www.cnblogs.com/yjf512/p/9531282.html ?就說(shuō)的很清楚了。這里再深挖一些。

          問(wèn)題:go的切片數(shù)據(jù)結(jié)構(gòu)是什么樣子的?

          切片是有可能在編譯器就被內(nèi)聯(lián)的,而如果在編譯器沒(méi)有被內(nèi)聯(lián),進(jìn)入運(yùn)行期,就是直接使用SliceHeader數(shù)據(jù)結(jié)構(gòu)。

          type?SliceHeader?struct?{
          ?Data?uintptr
          ?Len??int
          ?Cap??int
          }

          這三個(gè)字段分別表示指針,長(zhǎng)度,容量。

          問(wèn)題:為什么在初始化slice的時(shí)候盡量補(bǔ)全cap

          當(dāng)我們要?jiǎng)?chuàng)建一個(gè)slice結(jié)構(gòu),并且往slice中append元素的時(shí)候,我們可能有兩種寫法來(lái)初始化這個(gè)slice。

          方法1:

          package?main

          import?"fmt"

          func?main()?{
          ?arr?:=?[]int{}
          ?arr?=?append(arr,?1,2,3,4,?5)
          ?fmt.Println(arr)
          }

          方法2:

          package?main

          import?"fmt"

          func?main()?{
          ???arr?:=?make([]int,?0,?5)
          ???arr?=?append(arr,?1,2,3,4,?5)
          ???fmt.Println(arr)
          }

          方法2相較于方法1,就只有一個(gè)區(qū)別:在初始化[]int slice的時(shí)候在make中設(shè)置了cap的長(zhǎng)度,就是slice的大小。

          這兩種方法對(duì)應(yīng)的功能和輸出結(jié)果是沒(méi)有任何差別的,但是實(shí)際運(yùn)行的時(shí)候,方法2會(huì)比少運(yùn)行了一個(gè)growslice的命令。

          這個(gè)我們可以通過(guò)打印匯編碼進(jìn)行查看:

          方法1:

          01b4aede70838c603e32d57f6363f505.webpimage-20211219173237557

          方法2:

          34a635a2861799d9ea80eed716676420.webpimage-20211219174112164

          我們看到方法1中使用了growsslice方法,而方法2中是沒(méi)有調(diào)用這個(gè)方法的。

          這個(gè)growslice的作用就是擴(kuò)充slice的容量大小。就好比是原先我們沒(méi)有定制容量,系統(tǒng)給了我們一個(gè)能裝兩個(gè)鞋子的盒子,但是當(dāng)我們裝到第三個(gè)鞋子的時(shí)候,這個(gè)盒子就不夠了,我們就要換一個(gè)盒子,而換這個(gè)盒子,我們勢(shì)必還需要將原先的盒子里面的鞋子也拿出來(lái)放到新的盒子里面。所以這個(gè)growsslice的操作是一個(gè)比較復(fù)雜的操作,它的表現(xiàn)和復(fù)雜度會(huì)高于最基本的初始化make方法。對(duì)追求性能的程序來(lái)說(shuō),應(yīng)該能避免盡量避免。

          具體對(duì)growsslice函數(shù)具體實(shí)現(xiàn)同學(xué)有興趣的可以參考源碼src的 runtime/slice.go 。

          當(dāng)然,我們并不是每次都能在slice初始化的時(shí)候就能準(zhǔn)確預(yù)估到最終的使用容量的。所以這里使用了一個(gè)“盡量”。明白是否設(shè)置slice容量的區(qū)別,我們?cè)谀茴A(yù)估容量的時(shí)候,請(qǐng)盡量使用方法2那種預(yù)估容量后的slice初始化方式。

          問(wèn)題:如果不設(shè)置cap,make slice的時(shí)候,創(chuàng)建的cap為多大?

          如果不設(shè)置cap,不管是使用make,還是直接使用[]slice 進(jìn)行初始化,編譯器都會(huì)計(jì)算初始化所需的空間,使用最小化的cap進(jìn)行初始化。

          a?:=?make([]int,?0)??//?cap?為0
          a?:=?[]int{1,2,3}?//?cap?為3

          可以從ssa看出

          3b847f8187577a60dfef1de4466f332c.webpimage-20211221095655104

          問(wèn)題:slice什么時(shí)候決定擴(kuò)張?

          之前寫過(guò)一篇文章 https://www.cnblogs.com/yjf512/p/10714792.html 里面得出的結(jié)論就是slice在編譯期就決定是否要調(diào)用growslice。

          這個(gè)邏輯是正確的。

          編譯器在ssa的時(shí)候 對(duì)于append是會(huì)轉(zhuǎn)換為 OAPPEND(cmd/compile/internal/typecheck/universe.go) 。而在 cmd/compile/internal/ssagen/ssa.go 中,對(duì)其進(jìn)行判斷。

          8e521090c8b12a9ba5ea6582010391f8.webpimage-20211221101614497

          目前還看不懂下面append下面的邏輯,不過(guò)基于這個(gè)注釋,能了解到這里growslice的邏輯。比較擴(kuò)容前后大小,如果原先cap小于擴(kuò)容后需要cap,就growslice。

          總結(jié)

          琢磨了四個(gè)關(guān)于切片的問(wèn)題:

          問(wèn)題:go的切片數(shù)據(jù)結(jié)構(gòu)是什么樣子的?

          問(wèn)題:為什么在初始化slice的時(shí)候盡量補(bǔ)全cap?

          問(wèn)題:如果不設(shè)置cap,make slice的時(shí)候,創(chuàng)建的cap為多大?

          問(wèn)題:slice什么時(shí)候決定擴(kuò)張?

          感覺(jué)第四個(gè)問(wèn)題還沒(méi)想透。



          推薦閱讀


          福利
          我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù)?ebook?獲??;還可以回復(fù)「進(jìn)群」,和數(shù)萬(wàn) Gopher 交流學(xué)習(xí)。

          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  2019中文字幕mv第三季歌词 | 成人做爱网站视频| 欧美全黄一级裸片 | 操巷子里的老骚货免费视频 | 人人插人人干 |