共计 2376 个字符,预计需要花费 6 分钟才能阅读完成。
切片(slice)是建设在数组之上的更不便,更灵便,更弱小的数据结构。切片并不存储任何元素而只是对现有数组的援用。
切片的三要素
- 指向数组中的开始地位
- 切片的长度,通过内置函数 len 取得
- 切片的最大容量,通过内置函数 cap 取得
能够认为切片在外部示意为如下的构造体:
type slice struct {
// 长度
Length int
// 容量
Capacity int
// 指向首元素的指针
ZerothElement *byte
}
切片申明
// 基于数组创立一个从 a[start] 到 a[end -1] 的切片
a := [5]int{76, 77, 78, 79, 80}
var b []int = a[1:4]
// 创立了一个长度为 4 的 string 数组,并返回一个切片给 names
names := []string{"beijing", "shanghai", "guangzhou", "shenzhen"}
// 创立长度为 10 的字符串切片
str := make([]string, 10)
// 创立长度为 10,容量为 20 的字符串切片
str := make([]string, 10, 20)
arr[start:end] 的应用
// 基于数组产生新的切片,a[start:end] 为左闭右开
name1 := names[0:3]
name2 := names[:3]
name3 := names[2:]
name4 := names[:]
援用传递
切片自身不蕴含任何数据。它仅仅是底层数组的一个下层示意。对切片进行的任何批改都将反映在底层数组中。
names := []string{"beijing", "shanghai", "guangzhou", "shenzhen"}
name1 := names[0:3]
// 援用传递,会同时扭转原数组
name1[2] = "luoyang"
fmt.Println(names)
fmt.Println(name1)
获取切片长度与容量
str := "helloworld"[5:7]
fmt.Println("len:", len(str), ", cap:", cap(str))
切片追加元素
// append 会判断切片是否有残余空间,如果没有残余空间,则会主动裁减两倍空间
names = append(names, "chongqing")
如果切片是建设在数组之上的,而数组自身不能扭转长度,那么切片是如何动静扭转长度的呢?理论产生的状况是,当新元素通过调用
append
函数追加到切片开端时,如果超出了容量,append
外部会创立一个新的数组。并将原有数组的元素被拷贝给这个新的数组,最初返回建设在这个新数组上的切片。这个新切片的容量是旧切片的二倍。
切片追加切片
能够应用 ...
操作符将一个切片追加到另一个切片开端
veggies := []string{"potatoes","tomatoes","brinjal"}
fruits := []string{"oranges","apples"}
food := append(veggies, fruits...)
fmt.Println("food:", food)
遍历切片
for key, value := range names {fmt.Println("key:", key, ", value:", value)
}
复制切片
copy 用于将内容从一个数组切片复制到另一个数组切片。
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制 slice1 的前 3 个元素到 slice2 中
copy(slice1, slice2) // 只会复制 slice2 的 3 个元素到 slice1 的前 3 个地位
切片作为函数参数
func subtactOne(numbers []int) {
for i := range numbers {numbers[i] -= 2
}
}
func main() {nos := []int{8, 7, 6}
fmt.Println("slice before function call", nos)
subtactOne(nos) //function modifies the slice
fmt.Println("slice after function call", nos) //modifications are visible outside
}
// array before function call [8 7 6]
// array after function call [6 5 4]
切片内存优化
切片保留对底层数组的援用。只有切片存在于内存中,数组就不能被垃圾回收。假如咱们有一个十分大的数组,而咱们只须要解决它的一小部分,为此咱们创立这个数组的一个切片,并解决这个切片。这时候数组依然存在于内存中,因为切片正在援用它。
解决该问题的一个办法是应用 copy 函数来创立该切片的一个拷贝。这样咱们就能够应用这个新的切片,原来的数组能够被垃圾回收。
func countries() []string {countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
// 数组被切片援用,不能回收
neededCountries := countries[:len(countries)-2]
// 创立新的切片
countriesCpy := make([]string, len(neededCountries))
// 应用 copy 函数创立切片的拷贝
copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
// 返回后数组不再被援用,主动回收
return countriesCpy
}
func main() {countriesNeeded := countries()
fmt.Println(countriesNeeded)
}
正文完