天天看點

golang 定義一個空切片_Golang學習筆記之切片(slice)

切片slice:切片是對數組的抽象。切片在記憶體中占24個位元組runtime.hstruct Slice{      // must not move anything

byte* array;   // actual data

uintgo len;    // number of elements

uintgo cap;    // allocated number of elements};

切片包含長度、容量、以及一個指向首元素的指針• 引⽤類型。但⾃⾝是結構體,值拷⻉傳遞。

• 屬性 len 表⽰可⽤元素數量,讀寫操作不能超過該限制。

• 屬性 cap 表⽰最⼤擴張容量,不能超出數組限制。

• 如果 slice == nil,那麼 len、 cap 結果都等于 0。

• 作為變長數組的替代方案,可以關聯底層數組的局部或全部

•可以直接建立或從底層數組擷取生成

• 使用len()擷取元素個數,cap()擷取容量

• 一般使用make()建立

•如果多個slice指向相同底層數組,其中一個值的改變會影響全部

•在通過下标通路元素時下标不能超過len大小,如同數組的下标不能超出len範圍一樣。

make([]T, len, cap)

其中cap可以省略,則和len的值相同

len表示存放的元素個數,cap表示容量

1、初始化的幾種方式//第一種方式建立切片

var slice []int

fmt.Println(len(slice)) //0

//第二種方式

sl1 := []int{0, 1, 2, 3, 8: 100}     // 通過初始化表達式構造,可使⽤索引号。

fmt.Println(sl1, len(sl1), cap(sl1)) //[0 1 2 3 0 0 0 0 100] 9 9

sl2 := make([]int, 10) // 使⽤ make 建立,省略 cap,相當于 cap = len。

fmt.Println(sl2)       //[0 0 0 0 0 0 0 0 0 0]

//第三種方式

num := []int{10, 20, 30, 40, 50}

fmt.Println(num) //[10 20 30 40 50]

2、append

向 slice 尾部添加資料,傳回新的 slice 對象

切片可以通過内置函數append(slice []Type,elems …Type)追加元素,elems可以是一排type類型的資料,也可以是slice,因為追加的一個一個的元素,是以如果将一個slice追加到另一個slice中需要帶上”…”,這樣才能表示是将slice中的元素依次追加到另一個slice中。append追加元素超出實際容量會執行擴容,會擴充為slice原先容量的2倍

(1)//将一個slice追加到另一個slice中需要帶上”…”,這樣表示是将slice中的元素依次追加到另一個slice中

例:veggies := []string{"potatoes", "tomatoes", "brinjal"}

fruits := []string{"oranges", "apples"}

food := append(veggies, fruits...) //veggies+fruits

fmt.Println("food:", food)

(2)切片元素删除,可以使用append來實作

s = append(s[:i], s[i+1:]…)

首先s[:i]相當于slice截取,也就是說s[:i]本身就是一個slice。然後s[i+1:]…相當于變長參數。使用append的特性(向 slice 尾部添加資料,傳回新的 slice 對象)來實作删除的功能。可以單個也可以删除多個。

例://删除scile中元素,删除下标為2的元素    test := []int{10, 20, 30, 40, 50, 100}    test = append(test[:2], test[3:]...)

fmt.Println(test) //[10 20 40 50 100]

3、copy

函數 copy 在兩個 slice 間複制資料,複制⻓度以 len ⼩的為準。兩個 slice 可指向同⼀底層數組,允許元素區間重疊。

例://copy

countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}

neededCountries := countries[:len(countries)-2]

countriesCpy := make([]string, len(neededCountries))

copy(countriesCpy, neededCountries)

fmt.Println(countriesCpy)

fmt.Println(len(countriesCpy), cap(countriesCpy))

data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

s := data[8:]

s2 := data[:5]

copy(s2, s)       // dst:s2, src:s

fmt.Println(s2)   //[8 9 2 3 4]

fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]

應及時将所需資料 copy 到較⼩的 slice,以便釋放記憶體。

4、如果兩個切片共享同一塊位址空間,使用append删除其中一個的參數,另一個切片雖然會被影響,但len不變,會自動在最後補上len長度的參數

demofunc main() {

a1 := []int{1, 2, 3, 4, 5}

a2 := a1

a1 = append(a1[:2], a1[3:]...)

fmt.Println(a1) //[1 2 4 5]

fmt.Println(a2) //[1 2 4 5 5]}

下面是整個例子package mainimport (    "fmt"

"unsafe")func main() {    //第一種方式建立切片

var slice []int

fmt.Println(len(slice)) //0

//第二種方式

sl1 := []int{0, 1, 2, 3, 8: 100}     // 通過初始化表達式構造,可使⽤索引号。

fmt.Println(sl1, len(sl1), cap(sl1)) //[0 1 2 3 0 0 0 0 100] 9 9

sl2 := make([]int, 10) // 使⽤ make 建立,省略 cap,相當于 cap = len。

fmt.Println(sl2)       //[0 0 0 0 0 0 0 0 0 0]

//第三種方式

num := []int{10, 20, 30, 40, 50}

fmt.Println(num) //[10 20 30 40 50]

fmt.Printf("type is %T\tsize is %d\n", sl2, unsafe.Sizeof(sl2))

var b []int

b = num[1:4] //左閉右開從num下标1到3

var b1 []int

b1 = num[:] //num的全部

fmt.Println(b)

fmt.Println(b1)

//切片為數組的引用

darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}

dslice := darr[2:5]

fmt.Println("array before", darr)    for i := range dslice {

dslice[i]++

}

fmt.Println("array after", darr)    //切片指向數組,容量cap會從strartIndex取到數組結束,長度是指定截取長度

fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon",        "pine apple", "chikoo"}

fruitslice := fruitarray[0:3]    //長度2容量6

fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice))    //append追加元素超出實際容量會執行擴容,會擴充為原先容量的2倍

slice1 := make([]int, 5, 10)

fmt.Println(slice1)

slice3 := append(slice1, 1, 2, 3, 4, 5)

fmt.Println(slice3)    //執行append會會傳回一個新的數值可以用原切片接收也可以使用别的

var slice4 []int //空的切片初始為nil

fmt.Println(slice4)    if slice4 == nil {

slice4 = append(slice4, 1, 2, 3, 4)

fmt.Println(slice4)

}    //将一個slice追加到另一個slice中需要帶上"…",這樣表示是将slice中的元素依次追加到另一個slice中

veggies := []string{"potatoes", "tomatoes", "brinjal"}

fruits := []string{"oranges", "apples"}

food := append(veggies, fruits...) //veggies+fruits

fmt.Println("food:", food)    //二維切片,每一行元素的個數可以不一緻

pls := [][]string{

{"C", "C++"},

{"JavaScript"},

{"Go", "Rust"},

}

fmt.Println(len(pls), cap(pls)) //長度為3容量為3

for _, v1 := range pls {        for _, v2 := range v1 {

fmt.Printf("%s ", v2)

}

fmt.Printf("\n")

}    //copy

countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}

neededCountries := countries[:len(countries)-2]

countriesCpy := make([]string, len(neededCountries))

copy(countriesCpy, neededCountries)

fmt.Println(countriesCpy)

fmt.Println(len(countriesCpy), cap(countriesCpy))

data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

s := data[8:]

s2 := data[:5]

copy(s2, s)       // dst:s2, src:s

fmt.Println(s2)   //[8 9 2 3 4]

fmt.Println(data) //[8 9 2 3 4 5 6 7 8 9]

//删除scile中元素,删除下标為2的元素

test := []int{10, 20, 30, 40, 50, 100}

test = append(test[:2], test[3:]...)

fmt.Println(test) //[10 20 40 50 100]}

作者:學生黃哲

連結:https://www.jianshu.com/p/d60b3d779391