數(shù)組,切片

數(shù)組

創(chuàng)建方式

提起切片,我們必須要先了解數(shù)組,數(shù)組的類型名是[n]elementType,n代表數(shù)組長(zhǎng)度,elementType是數(shù)組元素類型。數(shù)組的定義方式如下:

// var elementName [n]elementType
var array [2]int    // [0 0];聲明一個(gè)含有兩個(gè)int類型的數(shù)組,因?yàn)槲闯跏蓟?,所以元素都為默認(rèn)值0
array2:=[...]int{1,2,3} // 可以不指定數(shù)組長(zhǎng)度,但必須指定"...",然后編譯器自動(dòng)根據(jù)字面量初始化列表推導(dǎo)數(shù)組長(zhǎng)度。

數(shù)組常見(jiàn)創(chuàng)建方式

arr1:=[3]int{1,2,3} // [1 2 3]
arr2:=[...]int{1,2,3}   // [1 2 3]
arr3:=[3]int{1:1,2:2} // [0 1 2]
arr4:=[...]int{3:3,5:5} // [0 0 0 3 0 5]

數(shù)組特點(diǎn)

  • 長(zhǎng)度固定,不可以超過(guò)長(zhǎng)度追加元素

  • 數(shù)組是值類型,數(shù)組賦值或者作為函數(shù)參數(shù)都是值拷貝

    a:=[2]int{1,2}
    b:=a
    b[0]=999
    
    fmt.Println("a:",a)   // a: [1 2]
    fmt.Println("b:",b)   // b: [999 2]
    
  • 數(shù)組長(zhǎng)度是數(shù)組類型的組成部分,[1]int和[2]int表示不同的類型

  • 可以根據(jù)數(shù)組創(chuàng)建切片,切片引用的是原數(shù)組,切片的改變會(huì)引起原數(shù)組的改變

    a:=[2]int{1,2}
    b:=a[:]
    b[0]=999
    fmt.Println("a:",a)   // a: [999 2]
    fmt.Println("b:",b)   // b: [999 2]
    

遍歷數(shù)組

a:=[2]int{1,2}
// idx是索引,v是值
for idx,v:=range a{
   fmt.Println(idx,v)
}
for i:=0;i<len(a);i++{
   fmt.Println(i,a[i])
}

切片

因?yàn)閿?shù)組的長(zhǎng)度固定,而且是值拷貝,所以限制了數(shù)組的使用場(chǎng)景。此時(shí)切片(slice)應(yīng)運(yùn)而生,它是一種變長(zhǎng)數(shù)組,它是一種引用類型(map、channel也是引用類型)。

slice的底層如下:

type slice struct {
    array unsafe.Pointer    // 指向底層數(shù)組的指針
    len   int                           // 切片的元素?cái)?shù)量
    cap   int                           // 底層數(shù)組容量
}

創(chuàng)建方式

  • 由數(shù)組創(chuàng)建:array[s:e],array是數(shù)組名,s是起始索引,e是終止索引,array[s:e]包括s索引下的數(shù)據(jù),但不包括e索引下的數(shù)據(jù)(相當(dāng)于左閉右開(kāi)[s,e)),也就是說(shuō)第一個(gè)元素的索引是s,最后一個(gè)元素的索引是e-1,該切片的長(zhǎng)度為e-s

    var array = [3]int{1,2,3}
    a1:=array[:]  // [1 2 3],如果不指定起始或者終止索引的話,起始索引默認(rèn)為0,終止索引默認(rèn)為len(array)
    a2:=array[1:2]    // [2]
    

    同樣方式也可以通過(guò)切片創(chuàng)造切片

    s:=[]int{1,2,3}
    b:=s[1:2] //[2]
    
  • 由內(nèi)置函數(shù)make創(chuàng)建

    通過(guò)make創(chuàng)建的切片的元素初始值都被默認(rèn)初始化為元素類型的零值

    arr1:=make([]int,5) // [0 0 0 0 0] len=5,cap=5,所有元素都被默認(rèn)初始化為0
    
    arr2:=make([]int,5,10) // [0 0 0 0 0] len=5,cap=10,所有元素都被默認(rèn)初始化為0
    
  • 由字面量初始化

    arr:=[]int{1,2,3} // [1 2 3] len=3 cap=3
    

常見(jiàn)操作

s:=[]int{1,2}
fmt.Println(len(s)) // len=2,返回切片長(zhǎng)度

fmt.Println(cap(s)) // cap=2,返回切片容量

s=append(s,3)               // 向s追加元素;切片元素:[1,2,3];len=3,cap=4,切片長(zhǎng)度超過(guò)原來(lái)的容量,自動(dòng)擴(kuò)容,容量擴(kuò)大為原來(lái)的兩倍

s1:=[]int{4,5}
s=append(s,s1...)   // 向s追加切片
fmt.Println(s)  // [1 2 3 4 5]

s=append(s,7,8) // 向切片追加多個(gè)元素
fmt.Println(s)  // [1 2 3 4 5 7 8]

c:=[]int{1,2,3}
b:=make([]int,2)    // [0 0]
copy(b,c)   //只會(huì)復(fù)制長(zhǎng)度較小的,第一個(gè)參數(shù)是目的切片,第二個(gè)參數(shù)是源切片
fmt.Println(b) // [1 2]

c1:=[]int{1,2,3}
b1:=make([]int,5)   // [0 0 0 0 0]
copy(b1,c1) 
fmt.Println(b1) // [1 2 3 0 0]

Tips:

  1. 當(dāng)切片的長(zhǎng)度超過(guò)容量cap的時(shí)候,切片會(huì)進(jìn)行擴(kuò)容,cap直接擴(kuò)大為原來(lái)的2倍。

  2. append函數(shù)定義如下,第一個(gè)參數(shù)表示向哪個(gè)切片追加元素,后面的是可變參數(shù),可以添加多個(gè)參數(shù),也可以添加一個(gè)切片,當(dāng)?shù)诙€(gè)參數(shù)是切片時(shí),需要在切片后面添加三個(gè)點(diǎn)來(lái)表示引用切片中所有元素"..."

    注意:可變參數(shù)可以是單個(gè)元素,也可以是一個(gè)切片…,但不能兩者同時(shí)出現(xiàn)。

func append(slice []Type, elems ...Type) []Type
    s:=[]int{1,2}
            
    s1:=[]int{4,5}
    
    // s=append(s,1,s1...) // 報(bào)錯(cuò)

    // s=append(s,s1...,1)  // 報(bào)錯(cuò)

字符串和切片相互轉(zhuǎn)換

str:="深夜幽魂"
a:=[]byte(str)  // [230 183 177 229 164 156 229 185 189 233 173 130]
b:=[]rune(str)  // [28145 22812 24189 39746]

c:=[]byte{230,183,177,229,164,156,229,185,189,233,173,130}
fmt.Println(string(c))  // 深夜幽魂
d:=[]rune{28145,22812,24189,39746}
fmt.Println(string(d))  // 深夜幽魂

Tips:字符串轉(zhuǎn)切片的時(shí)候需要注意,尤其當(dāng)字符串內(nèi)容很大的時(shí)候,因?yàn)槊恳淮味家獜?fù)制內(nèi)容

刁鉆難點(diǎn)

  1. 通過(guò)var b []int創(chuàng)建切片,該切片底層array指針不指向任何數(shù)組(也就是array的值為nil),len、cap都是0;但通過(guò)a:=[]int{}這種方式創(chuàng)建的切片,雖然len、cap也都是0,但是底層array是開(kāi)辟了空間的,不為nil
a:=[]int{}
var b []int
fmt.Println(a,a==nil,len(a),cap(a)) // [] false 0 0
fmt.Println(b,b==nil,len(b),cap(b)) // [] true 0 0
  1. 通過(guò)array[s:e]創(chuàng)建切片的時(shí)候,其實(shí)還可以這樣array[s:e:c],c的最大值是數(shù)組的長(zhǎng)度或者切片的容量的最大值。e-s是該切片的長(zhǎng)度,c-s是該切片的容量

    a:=[]int{1,2}
    b:=a[0:1:2]
    fmt.Println(b,len(b),cap(b)) // [1] 1 2
    
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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