golang中數(shù)組和切片到底有什么區(qū)別?
數(shù)組大家都知道是具有「固定長度及類型的序列集合」,但是golang中又引入了「切片」,語法上看起來還和數(shù)組差不多,為什么會引入這些呢?切片和數(shù)組到底有什么區(qū)別呢?接下來咱們來一個一個的看。
數(shù)組 array
定義數(shù)組
上述語句表示的意思是,我們來定義一個變量arr 為5個長度的int的數(shù)組類型,也就是[5]int,同時給賦值上了初始值 1、2、3、4、5,內(nèi)存分布如圖
緊密挨在一起的數(shù)據(jù)結(jié)構(gòu)集合
注意
如果定義數(shù)組的方法是;
那么arr的數(shù)據(jù)類型為*[4]int,而不是[4]int;
不定長數(shù)組
當然數(shù)組的長度4如果是不固定的,可以用...的方式代替
數(shù)組的循環(huán)
數(shù)組的循環(huán)在golang中有一個特有的語法,就是 for range
數(shù)組的常用方法
常用方法是「len()」 方法和 「cap()」 方法;
- len()方法的作用是獲取數(shù)組或者切片的「長度」
- cap()方法的作用是獲取數(shù)組或者切片的「容量」
但是「在數(shù)組中,這兩個值永遠相同」,所以在這里咱們不多做考慮,在后面切片中再詳細闡述。
切片 slice
為什么會有切片?
切片之所以會誕生,是因為golang中數(shù)組存在很大的兩個問題
固定的長度,這意味著初始化 array 后,不能再 push 超過 len(array) 長度的元素
array 作為參數(shù)在函數(shù)之間傳遞時是值傳遞,相當于把數(shù)據(jù)copy了一份,具有很大的性能浪費
切片數(shù)據(jù)類型的底層結(jié)構(gòu)
比如我們定義了一個切片
那么以上變量在內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)如下圖所示
所以由上面的分析可以看出來,「切片是依賴于數(shù)組的,而且是一個指向數(shù)組的指針」,既然切片是指針類型,那么在作為參數(shù)傳遞的時候,肯定是引用類型,不需要重新copy一份而造成空間浪費。
slice 的截取
我們上面說過切片是依賴于數(shù)組的,所以切片的截取是基于數(shù)組進行截取的,截取這塊我們直接看例子就行,看例子記住一個原則即可「左包含,右不包含」
以上例子都符合上面提到的「左包含,右不包含原則」
- s4從下標2開始截取,截取到下標4;
- s5省略了第一個參數(shù),表示從下標0開始截取;
- s6省略了第二個參數(shù),表示截取到最后一個元素;
- s7省略了兩個參數(shù),只填寫了中間的冒號:,表示取全部元素;
切片的長度len()和容量cap()
長度很好理解,簡單理解就是「元素的個數(shù)」,容量相對難理解一些「在切片引用的底層數(shù)組中從切片的第一個元素到數(shù)組最后一個元素的長度就是切片的容量」。
我們還是來直接看例子:
- a1是數(shù)組長度為9,容量也為9,值是從1~9
- s5/s6/s7都是切割數(shù)組a1得到的切片。
- s5的長度為4,因為只有1 2 3 4這4個元素,容量為9,因為s5切片是從數(shù)組起始位置開始切割的:第一個元素是1,而s5底層數(shù)組a1最后一個元素是9,1~9共9個元素,所以s5的容量為9。
- s6的長度為7,因為s6的元素是39這7個元素;容量也為7,因為s5的底層數(shù)組最后一個元素是9,39共7個元素,所以s6的容量為7。
- s7更好理解了,長度和容量都是9,大家自己理解一下。
切片的常用方法
make
make方法主要是用于切片的生成,比較簡單,比如下面的例子就是我們來定義一個長度為5,容量為10的切片。
append
append主要是用于切片的追加。我們還是直接看例子。
我們可以看到定義了一個切片,初始化了4個元素,切片此時的長度和容量都為4。
分析:長度由4變成5,我們很好理解;容量為什么會從4變成8呢?「這個是因為go語言對切片的自動擴容機制,append追加,如果cap不夠的時候,go底層會把底層數(shù)組替換,是go語言的一套擴容策略?!?nbsp;簡單說這個擴容機制就是「如果不夠,就在以前的基礎(chǔ)上翻倍,如果超過1M,則+1M」,跟redis的bitmap類型的擴容機制是一樣的。
slice 擴容的"坑"
這個坑在面試中經(jīng)常會遇到,當 slice 作為函數(shù)參數(shù)時,「如果在函數(shù)內(nèi)部發(fā)生了擴容,這時再修改 slice 中的值是不起作用的」,因為修改發(fā)生在新的 array 內(nèi)存中,對老的 array 內(nèi)存不起作用。
如何追加多個元素
copy
我們發(fā)現(xiàn)s1和s2是[11 2 3] s3是[1 2 3],說明copy方法是復(fù)制了一份,開辟了新的內(nèi)存空間,不再引用s1的內(nèi)存地址,這就是兩者的區(qū)別。
如果您覺得這篇文章還不錯,記得關(guān)注點贊哦,您的支持是我創(chuàng)作的最大動力。