從一道面試題看golang slice

之前遇到一道感覺很不錯的slice面試題力试,這里分享出來贮预,先不貼答案了大家可以先思考下每個地方的打印會是什么贝室;最后再給大家公布答案
    v := make([]int, 0, 5)
    v = append(v, 2, 3, 5)
    a := append(v, 0, -1)
    fmt.Println(v) 
    fmt.Println(a) 

    b := append(v, 1)
    fmt.Println()
    fmt.Println(v) 
    fmt.Println(a) 
    fmt.Println(b) 

    c := append(v, 6, 7, 8, 9)
    fmt.Println()
    fmt.Println(v) 
    fmt.Println(a) 
    fmt.Println(b) 
    fmt.Println(c) 

    d := append(v, 12)
    fmt.Println(d) 
    fmt.Println(v) 
    fmt.Println(a) 
    fmt.Println(b) 
    fmt.Println(c) 
    fmt.Println(d) 
在解這道面試題之前先來看下slice常用用法

一般通過make([]T,len,cap)來創(chuàng)建slice
其中cap可以省略則跟len的值相同
len 表示存儲的元素個數(shù),cap表示容量

slice 初始化姿勢
    // 1仿吞、初始化時添加好了數(shù)據(jù)滑频,這時候len=cap=初始化的數(shù)據(jù)個數(shù)
    s1 := []int{1, 2, 3, 4, 5, 6}
    fmt.Println(s1, len(s1), cap(s1)) // [1 2 3 4 5 6] 6 6

    // 2、只申明 len唤冈,cap跟len相同
    s2 := make([]int, 5)
    fmt.Println(s2, len(s2), cap(s2)) // [0 0 0 0 0] 5 5

    // 3峡迷、同時申明len,cap
    s3 := make([]int, 5, 5)
    fmt.Println(s3, len(s3), cap(s3)) // [0 0 0 0 0] 5 5

    // 4、先聲明一個數(shù)組你虹,從數(shù)組處申明slice
    arr := [5]int{1, 2, 3, 4, 5}
    s4 := arr[:]
    fmt.Println(arr)                  // [1 2 3 4 5]
    fmt.Println(s4, len(s4), cap(s4)) // [1 2 3 4 5] 5 5
slice 的len很容易理解绘搞,就是slice元素個數(shù);那cap有什么用呢傅物?下面通過例子來看下
    s1 := make([]int, 5, 6)
    fmt.Println(s1, len(s1), cap(s1))
    fmt.Printf("%p\n", s1)

    s1 = append(s1, 1)
    fmt.Println(s1, len(s1), cap(s1))
    fmt.Printf("%p\n", s1)

    s1 = append(s1, 2)
    fmt.Println(s1, len(s1), cap(s1))
    fmt.Printf("%p\n", s1)

    s1 = append(s1, 3)
    fmt.Println(s1, len(s1), cap(s1))
    fmt.Printf("%p\n", s1)
=====================================================
[0 0 0 0 0] 5 6
0xc000216000
[0 0 0 0 0 1] 6 6
0xc000216000
[0 0 0 0 0 1 2] 7 12
0xc000030660
[0 0 0 0 0 1 2 3] 8 12
0xc000030660
從上面的結(jié)果可以看出來夯辖,slice cap是包含len的,也就是說len是cap的一部分董饰,而cap-len的部分是待append數(shù)據(jù)時存放數(shù)據(jù)的部分楼雹,在打印slice時也是不展示的模孩;slice在append數(shù)據(jù)時如果cap-len還有空間則會將數(shù)據(jù)添加到這部分空間中,如果cap-len已經(jīng)為0贮缅,則slice需要擴(kuò)充整個slice的cap榨咐,擴(kuò)充的元素個數(shù)就是當(dāng)前slice的cap大小。

就如上面的例子中在append 1時 cap還有剩余空間可以放數(shù)據(jù)所以添加之后 s1的地址沒變谴供;在append 2時 cap已經(jīng)為0了所以這時候需要對s1做擴(kuò)容操作块茁;擴(kuò)容的數(shù)據(jù)量就是初始化s1時設(shè)置的cap大小6,然后將之前的數(shù)據(jù)重新copy的新的slice中桂肌,所以可以看到擴(kuò)容之后slice的地址也發(fā)生了變化数焊;擴(kuò)容之后的cap大小為12;所以在初始化slice時給個合理的cap是非常重要的崎场;因為slice在擴(kuò)容時是按照當(dāng)前cap的大小成倍增長的

slice 的本質(zhì)

slice在真正做存儲時其實是對應(yīng)著一個數(shù)組佩耳;而slice只是這個數(shù)組的視圖而已;slice的len就是slice這個視圖能夠看到這個底層數(shù)組的窗口大小谭跨,而cap是這個底層數(shù)組的大小

假如初始化一個 s := make([]int,8,13)干厚;這時候s跟底層數(shù)組如下圖所示

slice存儲

如上圖所示不管用那種方式初始化slice,最終在底層都是通過一個數(shù)組來存儲數(shù)據(jù)螃宙,而slice只是這個底層數(shù)組的一個視圖蛮瞄,而len就是這個視圖的窗口大小谆扎;這個類似于數(shù)據(jù)庫中的View的概念挂捅;有了這個基礎(chǔ)之后我來再回頭看文章開頭說的面試題就很好做了

我們先把文章開頭的面試題以及答案貼出來,下面再通過圖示的方式來解答
    // v底層數(shù)組值 2,3,5,0,-1
    v := make([]int, 0, 5)
    v = append(v, 2, 3, 5)
    a := append(v, 0, -1)
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,0,-1

    // v底層數(shù)組值 2,3,5,1,-1
    b := append(v, 1)
    fmt.Println()
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,1,-1
    fmt.Println(b) // 2,3,5,1

    // v底層數(shù)組值 2,3,5,1,-1,6,7,8,9
    c := append(v, 6, 7, 8, 9)
    fmt.Println()
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,1,-1
    fmt.Println(b) // 2,3,5,1
    fmt.Println(c) // 2,3,5,6,7,8,9

    // v底層數(shù)組值 2,3,5,12,-1
    d := append(v, 12)
    fmt.Println()
    fmt.Println(d) // 2,3,5,12
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,12,-1
    fmt.Println(b) // 2,3,5,12
    fmt.Println(c) // 2,3,5,1,6,7,8,9
    fmt.Println(d) // 2,3,5,12
1堂湖、第一層打印
    v := make([]int, 0, 5)
    v = append(v, 2, 3, 5)
    a := append(v, 0, -1)
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,0,-1
圖示底層數(shù)組變化過程
2闲先、第二層打印
    b := append(v, 1)
    fmt.Println()
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,1,-1
    fmt.Println(b) // 2,3,5,1
示意圖
3、第三層打印
// v底層數(shù)組值 2,3,5,1,-1,6,7,8,9
    c := append(v, 6, 7, 8, 9)
    fmt.Println()
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,1,-1
    fmt.Println(b) // 2,3,5,1
    fmt.Println(c) // 2,3,5,6,7,8,9
示意圖
4无蜂、第四層打印
    d := append(v, 12)
    fmt.Println()
    fmt.Println(d) // 2,3,5,12
    fmt.Println(v) // 2,3,5
    fmt.Println(a) // 2,3,5,12,-1
    fmt.Println(b) // 2,3,5,12
    fmt.Println(c) // 2,3,5,1,6,7,8,9
    fmt.Println(d) // 2,3,5,12
示意圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末饵蒂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子酱讶,更是在濱河造成了極大的恐慌退盯,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泻肯,死亡現(xiàn)場離奇詭異渊迁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)灶挟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門琉朽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稚铣,你說我怎么就攤上這事箱叁∈澹” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵耕漱,是天一觀的道長算色。 經(jīng)常有香客問我,道長螟够,這世上最難降的妖魔是什么灾梦? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘词渤。我一直安慰自己,他們只是感情好赋咽,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鲫忍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天炭庙,我揣著相機(jī)與錄音饲窿,去河邊找鬼煌寇。 笑死焕蹄,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的阀溶。 我是一名探鬼主播腻脏,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼银锻!你這毒婦竟也來了永品?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤击纬,失蹤者是張志新(化名)和其女友劉穎鼎姐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體更振,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡炕桨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肯腕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片献宫。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖实撒,靈堂內(nèi)的尸體忽然破棺而出姊途,到底是詐尸還是另有隱情涉瘾,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布捷兰,位于F島的核電站立叛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏寂殉。R本人自食惡果不足惜囚巴,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望友扰。 院中可真熱鬧彤叉,春花似錦、人聲如沸村怪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甚负。三九已至柬焕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梭域,已是汗流浹背斑举。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留病涨,地道東北人富玷。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像既穆,于是被迫代替她去往敵國和親赎懦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353