[top]
目标:什么是Golang的切片
什么是切片
在 Go 语言中,切片(slice)是一种动态数组,可以根据需要动态地增长或缩小。切片底层是一个数组,但与数组不同的是,切片的长度是可以动态改变的。
切片初始化
// 切片初始化的三种方式
package main
import "fmt"
func main() {
// 1.make方法
var makeSlice = make([]string, 3)
makeSlice := make([]string, 3) // 也可以简写为
fmt.Println(makeSlice)
// 2.从数组直接创建
arr := [5]string{"go", "gin", "grpc", "mysql", "elasticsearch"}
arrToSlice := arr[0:len(arr)]
fmt.Println(arrToSlice)
// 3.使用string{}
stringToSlice := []string{"go", "gin", "grpc"}
fmt.Println(stringToSlice)
}
Go的切片在函数传递的时候是值传递还是引用传递?
严格来讲是值传递,但是效果呈现出来是引用传递(不完全)
我们可以同一个例子得出结论:值传递
// 案例
package main
import (
"fmt"
"strconv"
)
func printSlice(data []string) {
data[0] = "java" // 方法内修改会影响传入的data
// 但是方法内的append却不会影响到传入的data
for i := 0; i < 10; i++ {
data = append(data, strconv.Itoa(i))
}
}
func main() {
courses := []string{"go", "grpc", "gin"}
printSlice(courses) // 执行方法
fmt.Println(courses) // 结果 [java grpc gin]
}
切片的原理
示例1
在 Go 中,函数参数传递都是值传递。但对于引用类型,传递的值实际上是指向底层数据结构的指针,因此在函数内部对其进行的修改会影响到原始数据。
// 案例
package main
import (
"fmt"
"strconv"
)
func main() {
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s1 := data[1:6] // s1当前:[2, 3, 4, 5, 6]
s2 := data[2:7] // s2当前:[3, 4, 5, 6, 7]
s2[0] = 22 // 修改s2的第0个数据
fmt.Println(s1) // s1结果:[2 22 4 5 6]
fmt.Println(s2) // s2的结果: [22 4 5 6 7]
fmt.Println(data) // data的结果:[1 2 22 4 5 6 7 8 9 10]
}
ç
示例1图解
切片是底层数组的一种引用形式,它们通过指向数组并确定段的起始和终止来确定如何访问数据。
多个切片可以引用同一个底层数组的不同部分,它们可能会或不会重叠。
对底层数组的修改将通过所有切片进行反映,这些切片引用了数组的被修改的部分。
示例2
在扩容前的s3[0] = 33是会影响到data/s1/s2,但是扩容(扩容:是成倍扩容)后修改的就是一个全新的数据了。
// 案例
package main
import (
"fmt"
"strconv"
)
func main() {
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s1 := data[1:6] // s1当前:[2, 3, 4, 5, 6]
s2 := data[2:7] // s2当前:[3, 4, 5, 6, 7]
s2[0] = 22 // 修改s2的第0个数据
fmt.Println(s1) // s1结果:[2 22 4 5 6]
fmt.Println(s2) // s2的结果: [22 4 5 6 7]
fmt.Println(data) // data的结果:[1 2 22 4 5 6 7 8 9 10]
// 在示例1基础上新增的
s3 := data[3:8]
s3[0] = 33
s3 = append(s3, 1, 2, 3, 4, 5, 6, 7, 8) // append超过cap上限,这个操作是为了造成扩容
s3[1] = 44
fmt.Println(s1) // s1:[2 22 33 5 6]
fmt.Println(s2) // s2:[22 33 5 6 7]
fmt.Println(s3) // s3:[33 44 6 7 8 1 2 3 4 5 6 7 8]
}
示例2图解
扩容
- 如果当前的切片容量小于 1024,那么新的容量通常是当前容量的2倍。(即:新容量 = 2倍的当前容量)
- 如果当前的切片容量大于等于 1024,新的容量增加为原来容量的 1.25,增加25%(即:新容量 = 当前容量 + 当前容量/4)。
Comments NOTHING