正確理解golang slice的復(fù)制

slice 三個屬性

golang 的slice是一個指向底層的數(shù)組的指針結(jié)構(gòu)體寸谜。 這個結(jié)構(gòu)體有三個屬性竟稳,1.指向數(shù)組指針,2.len: slice中元素的數(shù)量 3.cap:slice占用內(nèi)存數(shù)量程帕。 只有深刻理解這三個屬性才能在使用slice中不至于犯錯住练。

正確理解變量和共享

多個slice之間可以共享底層的數(shù)據(jù),并且引用的數(shù)組部分區(qū)間可能重疊

以上是golang 圣經(jīng)中的一句話愁拭。深刻理解這句話對于日程編程非常有意義讲逛。

1.什么時候共享數(shù)據(jù)會被其他變量修改

func f1()  {
    a1 := []int{1,2,3,4,5,6}
    a2 := a1
    a3 := a1[1:3]

    a1[1] = 999
    
    fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}

運行結(jié)果

a1= [1 999 3 4 5 6] a2= [1 999 3 4 5 6] a3= [999 3]

Process finished with exit code 0

我們清楚的看到了數(shù)據(jù)共享,此時修改了a1 岭埠,兩位兩個變量都被修改

什么時候不會修改

func f2()  {
    a1 := []int{1,2,3,4,5,6}
    a2 := a1
    a3 := a1[1:3]

    a2 = append(a2,888)

    a1[1] = 999

    fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}

運行結(jié)果

a1= [1 999 3 4 5 6] a2= [1 2 3 4 5 6 888] a3= [999 3]

Process finished with exit code 0

可以雖然a1被修改盏混,a2并沒有修改。我們知道append函數(shù)會面臨內(nèi)存的重新分配惜论。所以等a2進行append的時候许赃,會重新申請內(nèi)存空間,將原有數(shù)組拷貝然后增加如新值馆类。也就是當append操作的時候混聊,此時a2 不在和a1 共享內(nèi)存了。所以后續(xù)對a1的操作是不會影響到a2.

3.所有的append操作都會隔斷內(nèi)存共享乾巧?

func f3()  {
    a1 := []int{1,2,3,4,5,6}
    a2 := a1
    a3 := a1[1:3]
    a2 = append(a2,888)
    a3 = append(a3,777)

    a1[1] = 999

    fmt.Println("a1=",a1,"a2=",a2,"a3=",a3)
}

運行結(jié)果

a1= [1 999 3 777 5 6] a2= [1 2 3 4 5 6 888] a3= [999 3 777]

Process finished with exit code 0

這次a3 是對a1進行切片操作賦值的新變量句喜。此時對a3進行append操作预愤,我們發(fā)現(xiàn)a1的值同步被修改了。所以此時a3 和a1 仍然是共享內(nèi)存咳胃,append并沒有申請新的內(nèi)存空間而是繼續(xù)在a3的數(shù)據(jù)末尾寫入植康,這樣對于a1 是覆蓋了原有值。

問題本質(zhì)是

a1= [1 999 3 777 5 6] cap(a1) =  6  a2= [1 2 3 4 5 6 888] cap(a2) =  12  a3= [999 3 777] cap(a3) =  5

重新運行后將三個變量cap值打印為以上輸出展懈。
問題的本質(zhì)是len 和cap 的值销睁。 在slice中,當len小于cap 的值的時候存崖, 進行append 操作是不會造成內(nèi)存的重新分配冻记。a3 是從a1切片操作而來,我們看到a3 初始化的len =2 金句,cap =5.所以在append中不會引起內(nèi)存重新分配檩赢,go 運行時會繼續(xù)將數(shù)據(jù)依次寫入。這樣就修改了a3 和a1共享的內(nèi)存空間违寞。 對于a2贞瞒,在初始化的時候len =cap =6. 在append操作的時候就會重新申請空間,go會分配當前空間 * 2 的內(nèi)存趁曼。所以append后的cap就是12 如上军浆。

總結(jié)

在對slice 復(fù)制的時候,如果面臨多個變量同時指向一個數(shù)組的時候挡闰,一定要考慮到數(shù)據(jù)的共享和內(nèi)存的重新分配乒融。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市摄悯,隨后出現(xiàn)的幾起案子赞季,更是在濱河造成了極大的恐慌,老刑警劉巖奢驯,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件申钩,死亡現(xiàn)場離奇詭異,居然都是意外死亡瘪阁,警方通過查閱死者的電腦和手機撒遣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來管跺,“玉大人义黎,你說我怎么就攤上這事』砼埽” “怎么了廉涕?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我火的,道長壶愤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任馏鹤,我火速辦了婚禮,結(jié)果婚禮上娇哆,老公的妹妹穿的比我還像新娘湃累。我一直安慰自己,他們只是感情好碍讨,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布治力。 她就那樣靜靜地躺著,像睡著了一般勃黍。 火紅的嫁衣襯著肌膚如雪宵统。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天覆获,我揣著相機與錄音马澈,去河邊找鬼。 笑死弄息,一個胖子當著我的面吹牛痊班,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摹量,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼涤伐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缨称?” 一聲冷哼從身側(cè)響起凝果,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎睦尽,沒想到半個月后器净,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡骂删,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年掌动,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宁玫。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡粗恢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出欧瘪,到底是詐尸還是另有隱情眷射,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站妖碉,受9級特大地震影響涌庭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜欧宜,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一坐榆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧冗茸,春花似錦席镀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挂绰,卻和暖如春屎篱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葵蒂。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工交播, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刹勃。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓堪侯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荔仁。 傳聞我的和親對象是個殘疾皇子伍宦,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容