【Go - MD太可怕了,小心! Go中Slice的append陷阱】

開始之前,先看下下面這個(gè)例子,

package main

import "fmt"

func main() {
    s := make([]int, 0, 10)

    s1 := append(s, 1)
    s1 = append(s1, 3)

    s2 := append(s, 2)
    s2 = append(s2, 4)

    fmt.Printf("%v\\n", s1)
    fmt.Printf("%v\\n", s2)
}

這個(gè)輸出什么 , [1,3] [2,4]?

錯(cuò)?,輸出的是[2,4] , [2, 4]。

為什么

  1. 先來看下slice,
type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}

可以看出 Slice 數(shù)據(jù)結(jié)構(gòu)是 指針 ,容量(可以存儲(chǔ)數(shù)據(jù)的大?。L(zhǎng)度(當(dāng)前數(shù)據(jù)的大?。?。使用上 ,make可以為其分配空間。

make([]int, 0, 10) 
  1. 這里有個(gè)注意點(diǎn),append操作,append(slice, …),
  • 如果slice開辟的空間足夠,則不用額外分配空間。 append的返回結(jié)果的空間仍然是slice原有分配的空間,只是基于這個(gè)空間賦值,然后返回
  • 如果slice開辟的空間不足,則重新開辟空間,賦值,然后返回。
  1. 再帶入這個(gè)例子,
    s := make([]int, 0, 10)

    s1 := append(s, 1)
    s1 = append(s1, 3)

    s2 := append(s, 2)
    s2 = append(s2, 4)

站在第二個(gè)slice的角度s2上看,先拿到一塊內(nèi)存空間,然后從這個(gè)空間的第一個(gè),第二個(gè)位置分別寫入值。則此時(shí)會(huì)把s1之前寫入的覆蓋掉。

結(jié)語

  • append追加元素,如果slice還有容量的話,則會(huì)繼續(xù)使用原先開票的空間。不會(huì)重新開辟空間。
  • 當(dāng)?shù)讓訑?shù)組裝不下的時(shí)候,Go就會(huì)創(chuàng)建新的底層數(shù)組來保存這個(gè)切片,slice地址也隨之改變。

append是否返回新地址,和原有容量和添加數(shù)據(jù)數(shù)量有關(guān),不是固定的。所以一定不要默認(rèn)append會(huì)進(jìn)行新的內(nèi)存開辟,更不要拿append 作為復(fù)制操作,認(rèn)為append完以后拿到的slice一定就是全新獨(dú)立的slice。
所以在使用append的時(shí)候,一定小心謹(jǐn)慎,認(rèn)真看好空間的分配,防止相同地址被覆蓋寫入。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • go slice append 切片的底層是一個(gè)數(shù)組,如果截取切片的一部分賦給另一個(gè)切片,那這兩個(gè)切片的數(shù)據(jù)其實(shí)指...
    小東班吉閱讀 843評(píng)論 0 0
  • 一、定義 我們都知道在 Go 語言中,數(shù)組的長(zhǎng)度是不可變的,那么為了更加靈活的處理數(shù)據(jù),Go 提供了一種功能強(qiáng)悍的...
    HenryCheng閱讀 8,562評(píng)論 0 6
  • Slice常見操作及底層原理實(shí)現(xiàn) 一 什么是Slice slice(切片)是一種數(shù)組結(jié)構(gòu),相當(dāng)于是一個(gè)動(dòng)態(tài)的數(shù)組,...
    假程序員的世界閱讀 5,380評(píng)論 0 4
  • 原文鏈接:https://blog.thinkeridea.com/201901/go/slice_de_yi_x...
    戚銀閱讀 1,698評(píng)論 0 0
  • fmt.Printf("%p\n", &xxx)的打印問題 后面的參數(shù)必須為 指針類型,否則IDE會(huì)有提示,運(yùn)行后...
    cuishuang閱讀 168評(píng)論 0 0

友情鏈接更多精彩內(nèi)容