2021-10-27
切片(slice)是對(duì)數(shù)組的一個(gè)連續(xù)片段的引用毅往,所以切片是一個(gè)引用類型檩淋,這個(gè)片段可以是整個(gè)數(shù)組芬为,也可以是一個(gè)片段,數(shù)組中的子集蟀悦,需要注意的是媚朦,終止索引標(biāo)識(shí)的項(xiàng)不包括在切片內(nèi)。
一個(gè)slice由三個(gè)部分構(gòu)成:指針日戈、長(zhǎng)度和容量询张。slice的語(yǔ)法和數(shù)組很像,只是沒有固定長(zhǎng)度浙炼。指針指向第一個(gè)slice元素對(duì)應(yīng)的底層數(shù)組元素的地址瑞侮,要注意的是slice的第一個(gè)元素并不一定就是數(shù)組的第一個(gè)元素的圆。長(zhǎng)度對(duì)應(yīng)slice中元素的數(shù)目;
指針:開始切片的位置
長(zhǎng)度:指針到結(jié)束的位置
容量:相當(dāng)于袋子半火,能裝多少越妈,長(zhǎng)度不能大于容量
內(nèi)置的len和cap函數(shù)分別返回slice的長(zhǎng)度和容量。
從數(shù)組或切片中生成新的切片
格式
slice [start:end]
語(yǔ)法:
- slice :切片的對(duì)象
- start:開始切片的索引
- end:結(jié)束切片的索引
例如:
package main
import "fmt"
func main() {
var array = [10]int{3,2,4,5,76,8,2,4,28,24}
fmt.Println(array,array[2:8])
}
從圖中可以看到對(duì)比結(jié)果钮糖,切片的開始是從索引為2的數(shù)開始到索引為7的結(jié)束梅掠,而切片中索引8是不包括在內(nèi)的。
總結(jié)特性:
- 取出的元素?cái)?shù)量為:start - ned店归;
- 取出元素不包含結(jié)束位置對(duì)應(yīng)的索引阎抒,切片最后一個(gè)元素使用 slice[len(slice)] 獲取消痛;
- 當(dāng)缺省開始位置時(shí)且叁,表示從連續(xù)區(qū)域開頭到結(jié)束位置;
- 當(dāng)缺省結(jié)束位置時(shí)秩伞,表示從開始位置到整個(gè)連續(xù)區(qū)域末尾逞带;
- 兩者同時(shí)缺省時(shí),與切片本身等效纱新;
- 兩者同時(shí)為 0 時(shí)展氓,等效于空切片,一般用于切片復(fù)位脸爱。
根據(jù)索引位置取切片 slice 元素值時(shí)遇汞,取值范圍是(0~len(slice)-1),超界會(huì)報(bào)運(yùn)行時(shí)錯(cuò)誤簿废,生成切片時(shí)空入,結(jié)束位置可以填寫 len(slice) 但不會(huì)報(bào)錯(cuò)。
從指定范圍中生成切片
func slice2() {
var hight [50]int
for i:=0;i<50;i++ {
hight[i]=i
}
fmt.Println(hight[15:35]) //區(qū)間
fmt.Println(hight[25:35]) //中間
fmt.Println(hight[:20]) //從開頭到中間指定的所有元素
}
直接聲明新的切片
聲明格式
var slice []type
其中slice切片的名族檬,type切片的元素類型
package main
import "fmt"
func main() {
slice_name()
}
func slice_name() {
// 聲明字符串切片
var strList []string
// 聲明整型切片
var numList []int
// 聲明一個(gè)空切片
var numListEmpty = []int{}
// 輸出3個(gè)切片
fmt.Println(strList, numList, numListEmpty)
// 輸出3個(gè)切片大小
fmt.Println(len(strList), len(numList), len(numListEmpty))
// 切片判定空的結(jié)果
fmt.Println(strList == nil)
fmt.Println(numList == nil)
fmt.Println(numListEmpty == nil)
}
第一個(gè)和第二個(gè)切片默認(rèn)的的元素值為nil执庐,而第三個(gè)切片本來會(huì)在{}
中填充切片的初始化元素,這里沒有填充导梆,所以切片是空的轨淌,但是此時(shí)的 numListEmpty 已經(jīng)被分配了內(nèi)存,只是還沒有元素看尼。
再最后的跟nil的判定中第三個(gè)切片為false递鹉,
切片是動(dòng)態(tài)結(jié)構(gòu),即沒有固定的長(zhǎng)度藏斩。只能與 nil 判定相等躏结,不能互相判定相等。聲明新的切片后狰域,可以使用 append() 函數(shù)向切片中添加元素媳拴。
使用make()函數(shù)構(gòu)造切片
格式
make([]type,size,cap)
type:切片中元素的類型
size:切片的長(zhǎng)度
cap:預(yù)分配的元素個(gè)數(shù)
package main
import "fmt"
func main() {
make_slice()
}
func make_slice() {
a := make([]int, 2)
b := make([]int, 2, 10)
fmt.Println(a, b)
fmt.Println(len(a), len(b))
}
b預(yù)分配了10個(gè)元素黄橘,但是size為2所以和a的len()值是一樣的
容量不會(huì)影響當(dāng)前的元素個(gè)數(shù),因此 a 和 b 取 len 都是 2屈溉。
溫馨提示
使用 make() 函數(shù)生成的切片一定發(fā)生了內(nèi)存分配操作塞关,但給定開始與結(jié)束位置(包括切片復(fù)位)的切片只是將新的切片結(jié)構(gòu)指向已經(jīng)分配好的內(nèi)存區(qū)域,設(shè)定開始與結(jié)束位置子巾,不會(huì)發(fā)生內(nèi)存分配操作帆赢。
學(xué)習(xí)地址:http://c.biancheng.net/view/27.html
append()添加元素
內(nèi)建函數(shù)append() ,動(dòng)態(tài)添加元素
用法
slice = append(slice,23) //追加單個(gè)元素
slice = append(slice,23,7,1,3) //追加多個(gè)元素
slice = append([]int{0},slice...) //在切片開頭加入元素,需要解包即加入...
slice = append(slice,[]int{6,7,8}...) //追加一個(gè)切片线梗,切片需要解包
slice = append([]int{6,7,8},slice...) //在原有切片開頭加入切片
例子:
package main
import "fmt"
func main() {
create_slice()
}
func create_slice() {
var slice = []int{1,2,3,4}
slice = append(slice,23) //在原有的切片基礎(chǔ)上添加上23元素
fmt.Println(slice)
fmt.Println(len(slice))
}
使用append()函數(shù)為動(dòng)態(tài)切片添加元素時(shí)椰于,如果容量不足,切片會(huì)自動(dòng)進(jìn)行"擴(kuò)容"仪搔,長(zhǎng)度就會(huì)發(fā)生變化瘾婿。
切片在擴(kuò)容的時(shí)候,容量擴(kuò)展規(guī)律時(shí)按容量的 2 倍數(shù)進(jìn)行擴(kuò)充
可以看到長(zhǎng)度和容量并不相等烤咧,容量相當(dāng)于袋子偏陪,而長(zhǎng)度就是錢,錢多了袋子也要換大的了髓削,為了防盜,位置也要發(fā)生變化了镀娶。
中間切片立膛,鏈?zhǔn)讲僮?/p>
var slice[]int{1,2,3,4}
slice = append(slice[:i], append([]int{x}, slice[i:]...)...) // 在第i個(gè)位置插入x
slice = append(slice[:i], append([]int{54,51,56}, slice[i:]...)...) // 在第i個(gè)位置插入切片
源碼
package main
import "fmt"
func main() {
Sliceinsert()
}
func Sliceinsert() {
var slice = []int{1,2,3,4}
slice = append(slice[:2], append([]int{666}, slice[2:]...)...) // 在第i個(gè)位置插入x
slice = append(slice[:3], append([]int{54,51,56}, slice[3:]...)...) // 在第i個(gè)位置插入切片
fmt.Printf("長(zhǎng)度:%d,元素:%d\n",len(slice),slice)
}