如何苗木網(wǎng)站建設(shè)全網(wǎng)推廣怎么做
Golang中的切片
- 基本介紹
- 切片在內(nèi)存中的形式
- 切片使用的三種方式
- 方式一:
- 方式二:
- 方式三:
- 切片使用的區(qū)別
- 切片的遍歷
- 切片注意事項(xiàng)和細(xì)節(jié)說(shuō)明
- append函數(shù)
- 切片的拷貝操作
- string和slice
基本介紹
- 1.切片是數(shù)組的一個(gè)引用,因此切片是引用類(lèi)型,在進(jìn)行傳遞時(shí),遵守引用傳遞的機(jī)制
- 2.切片的使用和數(shù)組類(lèi)型,遍歷切片、訪問(wèn)切片的元素和求切片長(zhǎng)度len(slice)都是一樣
- 3.切片的長(zhǎng)度是可以變化的,因此切片是一個(gè)可以動(dòng)態(tài)變化數(shù)組
- 4.切片定義的基本語(yǔ)法:
- var 變量名 [] 類(lèi)型, 比如: bar a [] int
package main
import ("fmt")func main() {var intArr [5]int = [...]int{1, 33, 22, 55, 66}//slice就是切片名//intArr[1:3]表示slice引用到intArr這個(gè)數(shù)組//引用intArr數(shù)組的起始下標(biāo)為1, 最后的下標(biāo)為3(但是不包含3)slice := intArr[1:3]fmt.Println("intArr=", intArr)fmt.Println("slice 的元素是:", slice)fmt.Println("slice 的元素個(gè)數(shù)是:", len(slice))fmt.Println("slice 的容量", cap(slice)) //切片的容量是可以動(dòng)態(tài)變化的 }
/*
intArr= [1 33 22 55 66]
slice 的元素是: [33 22]
slice 的元素個(gè)數(shù)是: 2
slice 的容量 4
*/
切片在內(nèi)存中的形式
- 切片底層的數(shù)據(jù)結(jié)構(gòu)可以理解成是一個(gè)結(jié)構(gòu)體struct
- 切片確實(shí)是一個(gè)引用類(lèi)型
切片使用的三種方式
方式一:
定義一個(gè)切片,然后讓切片去引用一個(gè)已經(jīng)創(chuàng)建好的數(shù)組,前面的案例就是這樣的
方式二:
通過(guò)make來(lái)創(chuàng)建切片
基本語(yǔ)法:var 切片名 []type = make([], len, [cap])
package main
import ("fmt")func main() {var slice []int = make([]int, 4, 10)fmt.Println(slice) //默認(rèn)值為0fmt.Println("slice len=", len(slice), "slice cap=", cap(slice))slice[0] = 100slice[2] = 200fmt.Println(slice)
}
/*
[0 0 0 0]
slice len= 4 slice cap= 10
[100 0 200 0]
*/
總結(jié):
- 1.通過(guò)make方式創(chuàng)建切片可以指定切片的大小和容量
- 2.如果沒(méi)有給切片的各個(gè)元素賦值,那么就會(huì)使用默認(rèn)值
- 3.通過(guò)make方式創(chuàng)建的切片對(duì)應(yīng)的數(shù)組的有make底層維護(hù),對(duì)外不可見(jiàn),只能通過(guò)slice去訪問(wèn)各個(gè)元素
方式三:
定義一個(gè)切片,直接就指定具體數(shù)組,使用原理類(lèi)似make的方式
func main(){var slice []int = []int {1, 3, 5}fmt.Println(slice)
}
切片使用的區(qū)別
- 方式一是直接引用數(shù)組,這個(gè)數(shù)組是事先存在的,程序員可見(jiàn)的
- 方式二是通過(guò)make來(lái)創(chuàng)建切片,make也會(huì)創(chuàng)建一個(gè)數(shù)組,是有切片在底層進(jìn)行維護(hù),程序員是看不見(jiàn)的
切片的遍歷
package main
import ("fmt")func main() {//使用常規(guī)的for循環(huán)遍歷切片var arr [5]int = [...]int{4, 5, 6, 7, 8}slice := arr[1:4]for i :=0; i < len(slice); i++ {fmt.Printf("slice[%v]=%v ", i, slice[i])}fmt.Println()//使用for-range方式切片for i, v := range slice {fmt.Printf("i=%v v=%v ", i, v)}
}//slice[0]=5 slice[1]=6 slice[2]=7
//i=0 v=5 i=1 v=6 i=2 v=7
切片注意事項(xiàng)和細(xì)節(jié)說(shuō)明
- 切片初始化時(shí) var slice = arr[startindex:endindex]
- 說(shuō)明:從arr數(shù)組下標(biāo)為startindex,取到endindex的元素(不含arr[endindex])
- 切片初始化時(shí),任然不可以越界。范圍在[0-len(arr)之間],但是可以動(dòng)態(tài)增長(zhǎng)
- var slice = arr [0:end]可以簡(jiǎn)寫(xiě):var slice = arr [:end]
- var slice = arr[start:len(arr)]可以簡(jiǎn)寫(xiě):var slice = arr[start:]
- var slice = arr[0:len(arr)]可以簡(jiǎn)寫(xiě):var slice = arr[:]
- cap是一個(gè)內(nèi)置函數(shù),用于統(tǒng)計(jì)切片的容量,即最大可以存放多少個(gè)元素
- 切片定義完后,還不能使用,因?yàn)楸臼∈且粋€(gè)空的,需要讓其引用到一個(gè)數(shù)組,或者make一個(gè)空間供切片來(lái)使用
- 切片可以繼續(xù)切片
append函數(shù)
用append內(nèi)置函數(shù),可以對(duì)切片進(jìn)行動(dòng)態(tài)追加
package main
import ("fmt")func main() {var slice []int = []int{100, 200, 300}//通過(guò)append直接給slice追加具體的元素slice = append(slice, 400, 5000)fmt.Println("slice", slice)//通過(guò)append將切片slice追加給sliceslice = append(slice, slice...)fmt.Println("slice", slice)
}
/*
slice [100 200 300 400 5000]
slice [100 200 300 400 5000 100 200 300 400 5000]
*/
底層原理分析
1.切片append操作的本質(zhì)就是對(duì)數(shù)組擴(kuò)容
2.go底層會(huì)創(chuàng)建一下新的數(shù)組newArr(安裝擴(kuò)容后大小)
3.將slice原來(lái)包含的元素拷貝到新的數(shù)組newArr
4.slice重新引用到newArr
5.注意newArr是在底層來(lái)維護(hù)的,程序員不可見(jiàn)
切片的拷貝操作
copy(para1,para2)參數(shù)的數(shù)據(jù)類(lèi)型是切片
由下面的案例可知,slice1和slice2的數(shù)據(jù)空間是獨(dú)立,相互不影響,也就是說(shuō)slice[0]=999,slice2[0]任是1
package main
import ("fmt")func main() {var slice1 []int = []int{1, 2, 3, 4, 5}var slice2 = make([]int, 10)copy(slice2, slice1)fmt.Println("slice1", slice1)fmt.Println("slice2", slice2)
}/*
slice1 [1 2 3 4 5]
slice2 [1 2 3 4 5 0 0 0 0 0]
*/
string和slice
- slice底層是一個(gè)byte數(shù)組,因此string也可以進(jìn)行切片處理
- sting是不可變的,也就是說(shuō)不能通過(guò)str[0]='z’方式來(lái)修改字符串
- 如果需要修改字符串,可以先將string->[]byte/或者[]rune->修改->重寫(xiě)轉(zhuǎn)成string
package main
import ("fmt")func main() {str := "hello@wings"//使用切片獲取內(nèi)容slice := str[6:]fmt.Println("slice=", slice)//[]byte可以處理英文和數(shù)字但是不能處理中文//[]rune是按照字符處理,兼容漢字arr1 := []byte(str)arr1[0] = 'z'str = string(arr1)fmt.Println("str=", str)
}//slice= wings
//str=zhello@wings