1. 程式人生 > 實用技巧 >go基礎筆記-切片

go基礎筆記-切片


切片的基本介紹
(1)切片的英文是 slice
(2)切片是陣列的一個引用,因此切片是引用型別,在進行傳遞時,遵守引用傳遞的機制。
(3)切片的使用和陣列類似,遍歷切片、訪問切片的元素和求切片長度 len(slice)都一樣。
(4)切片的長度是可以變化的,因此切片是一個可以動態變化陣列。
(5)切片定義的基本語法:
var 切片名 []型別
比如:var a [] int

 

切片的使用
第一種方式:
定義一個切片,然後讓切片去引用一個已經建立好的陣列。

案例:
func main() {
    // 切片入門案例:
    var intArr [5]int = [...]int{1, 22, 33, 66, 99}
    
//宣告/定義一個切片 slice := intArr[1:3] fmt.Println("intArr=", intArr) fmt.Println("slice 的元素是 =", slice) // 22, 33 fmt.Println("slice 的元素個數 =", len(slice)) // 2 fmt.Println("slice 的容量 =", cap(slice)) // 切片的容量是可以動態變化 // 上述程式碼說明: // slice 就是切片名 // intArr[1:3] 表示 slice 引用到intArr這個陣列
// 引用intArr陣列的起始下標為 1 , 最後的下標為3(但是不包含3) } 第二種方式: 通過 make 來建立切片. 基本語法: var 切片名 []type = make([]type, len, [cap]) 引數說明: type: 就是資料型別 len : 大小 cap :指定切片容量,可選, 如果你分配了 cap,則要求 cap>=len. 通過 make 方式建立切片可以指定切片的大小和容量 如果沒有給切片的各個元素賦值,那麼就會使用預設值 [ int , float=> 0 string =>”” bool =>false] 案例: func main() {
//演示切片的使用 make var slice []float64 = make([]float64, 5, 10) slice[1] = 10 slice[3] = 20 //對於切片,必須make使用. fmt.Println(slice) fmt.Println("slice的size=", len(slice)) fmt.Println("slice的cap=", cap(slice)) } 第 3 種方式: 定義一個切片,直接就指定具體陣列,使用原理類似 make 的方式 切片的遍歷 切片的遍歷和陣列一樣,也有兩種方式 方式一:for 迴圈常規方式遍歷 //使用常規的for迴圈遍歷切片 var arr [5]int = [...]int{10, 20, 30, 40, 50} slice := arr[1:4] for i := 0; i < len(slice); i++ { fmt.Printf("slice[%v]=%v ", i, slice[i]) } 方式二:for-range 結構遍歷切片 var arr [5]int = [...]int{10, 20, 30, 40, 50} slice := arr[1:4] //使用for--range 方式遍歷切片 for i, v := range slice { fmt.Printf("i=%v v=%v \n", i, v) } 切片也可以簡寫: var slice = arr[0:end] 可以簡寫 var slice = arr[:end] var slice = arr[start:len(arr)] 可以簡寫: var slice = arr[start:] var slice = arr[0:len(arr)] 可以簡寫: var slice = arr[:] 切片可以繼續切片 func main() { // 切片可以繼續切片案例演示 var arr [5]int = [...]int{10,20,30,40,50} slice := arr[1:4] for i:=0;i < len(slice);i++ { fmt.Printf("slice[%v]=%v\n",i,slice[i]) } fmt.Println() for i,v := range slice{ fmt.Printf("i=%v v=%v \n",i,v) } slice2 := slice[1:2] slice2[0] = 1000 fmt.Println("slice2=",slice2) fmt.Println("slice=",slice) fmt.Println("arr=",arr) } 用 append 內建函式,可以對切片進行動態追加 func main() { // 用 append 內建函式,可以對切片進行動態追加 var slice3 []int = []int{10,20,30,40,50} fmt.Println("slice3",slice3) slice3 = append(slice3,60,70) fmt.Println("slice3",slice3) slice3 = append(slice3,slice3...) fmt.Println("slice3",slice3) } 切片 append 操作的底層原理分析: 切片 append 操作的本質就是對陣列擴容 go 底層會建立一下新的陣列 newArr(安裝擴容後大小) 將 slice 原來包含的元素拷貝到新的陣列 newArr slice 重新引用到 newArr 注意 newArr 是在底層來維護的,程式設計師不可見. 切片的拷貝操作 切片使用 copy 內建函式完成拷貝 語法: func copy(dst,src []type) int 案例演示: func main() { // 切片的拷貝操作 var slice4 []int = []int{1, 2, 3, 4, 5} var slice5 = make([]int, 10) copy(slice5, slice4) fmt.Println("slice4=", slice4) // 1 2 3 4 5 fmt.Println("slice5=", slice5) // 1 2 3 4 5 0 0 0 0 0 slice4[1] = 100 fmt.Println("slice4=", slice4) // 1 2 3 4 5 fmt.Println("slice5=", slice5) // 1 100 3 4 5 0 0 0 0 0 } 對上面程式碼的說明: copy(para1, para2) 引數的資料型別是切片 按照上面的程式碼來看, slice4 和 slice5 的資料空間是獨立,相互不影響,也就是說 slice4[0]= 999, slice5[0] 仍然是 1 string和slice string 底層是一個 byte 陣列,因此 string 也可以進行切片處理 案例演示: //string底層是一個byte陣列,因此string也可以進行切片處理 str := "hello@xxl" //使用切片獲取到 xxl slice := str[6:] fmt.Println("slice=", slice) string 是不可變的,也就說不能通過 str[0] = 'z' 方式來修改字串 如果需要修改字串,可以先將 string -> []byte / 或者 []rune -> 修改 -> 重寫轉成 string //"hello@xxl" =>改成 "zello@xxl" str := "hello@xxl" arr1 := []byte(str) arr1[0] = 'z' str = string(arr1) fmt.Println("str=", str) 細節,我們轉成[]byte後,可以處理英文和數字,但是不能處理中文 原因是 []byte 位元組來處理 ,而一個漢字,是3個位元組,因此就會出現亂碼 解決方法是 將 string 轉成 []rune 即可, 因為 []rune是按字元處理,相容漢字 arr1 := []rune(str) arr1[0] = '' str = string(arr1) fmt.Println("str=", str)