Golang Slice切片
1. 切片的定义和初始化
- 切片是基于数组类型的封装,非常灵活,可以自动扩容
- 切片是真正意义上的动态数组,而且是一个引用类型,切片指向一个底层数组
定义切片
var 切片名[] 切片类型
创建切片方式
package main
import "fmt"
func main() {
// 1. 声明切片
var s1 []int
if s1 == nil { // 只声明没有初始化,所以是nil
fmt.Println("为空")
} else {
fmt.Println("不为空")
}
// 2. := 自动推导
s2 := []int{}
// 3. make(切片类型, 长度, 容量)
// 容量是可选的
var s3 []int = make([]int, 0)
fmt.Println(s1, s2, s3)
// 4. 初始化赋值
var s4 []int = make([]int, 0, 0)
fmt.Println(s4)
s5 := []int{1,2,3}
fmt.Println(s5)
// 5. 从数组切片
arr := [5]int{1,2,3,4,5}
var s6 []int
s6 = arr[1:4]
fmt.Println(s6)
}
2. 切片操作
操作 | 含义 |
---|---|
s[n] | 切片 s 中索引位置为 n 的项 |
s[:] | 从切片 s 的索引位置 0 到 len(s)-1 处所获得的切片 |
s[low:] | 从切片 s 的索引位置 low 到 len(s)-1 处所获得的切片 |
s[:high] | 从切片 s 的索引位置 0 到 high 处所获得的切片,len=high |
s[low:high] | 从切片 s 的索引位置 low 到 high 处所获得的切片,len=high-low |
s[low: high:max] | 从切片 s 的索引位置 low 到 high 处所获得的切片,len=high-low, cap=max-low |
len(s) | 切片 s 的长度,总是<=cap() |
cap(s) | 切片 s 的容量,总是>=len(s) |
package main
import "fmt"
func op01() {
// 定义数组
array := [...]int{1, 2, 3, 4, 5, 6, 7, 9, 0}
// 切片
fmt.Println(array[:])
fmt.Println(array[1:5])
fmt.Println(array[:6])
fmt.Println(array[2:])
fmt.Println(array[2])
}
func op02() {
s1 := make([]int, 3, 5)
fmt.Printf("s1: %v, len: %d, cap: %d", s1, len(s1), cap(s1))
}
func op03() {
// 初始化一个数组
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}
s1 := arr[2:5]
fmt.Println(s1)
// 可以向后扩展,默认是不扩展,不可以向前扩展
s2 := s1[2:7]
fmt.Println(s2)
}
func main() {
op01()
op02()
op03()
}
3. append()函数
向 slice 尾部添加数据,返回新的 slice 对象
package main
import "fmt"
func main() {
// 空切片
var s001 []int
s001 = append(s001, 1)
s001 = append(s001, 3)
s001 = append(s001, 6)
fmt.Println(s001)
// 初始化内存的切片
s002 := make([]int, 5)
s002 = append(s002, 5, 8, 9)
fmt.Println(s002)
// 初始化默认值的切片
s003 := []int{1, 3, 6}
s003 = append(s003, 4, 99, 2)
fmt.Println(s003)
}
package main
import "fmt"
func main() {
// 初始化一个数组
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8}
// 初始化一个从数组切片的slice
s1 := arr[2:]
fmt.Println(arr)
fmt.Println(s1)
// 修改s1切片的值
// view(视图)操作,会修改原数组的值
s1[0] = 100
fmt.Println(s1)
fmt.Println(arr)
}
// 输出结果
// [0 1 2 3 4 5 6 7 8]
// [2 3 4 5 6 7 8]
// [100 3 4 5 6 7 8]
// [0 1 100 3 4 5 6 7 8]
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
fmt.Println(s1)
s2 := s1[3:5]
fmt.Println(s2)
// 映射到底层是覆盖操作
s3 := append(s2, 10)
fmt.Println(s3)
fmt.Println(arr)
fmt.Println()
// 底层去自动扩容, 此时打印的是原数组
s4 := append(s3, 11)
fmt.Println(s4)
fmt.Println(arr)
s5 := append(s4, 12)
fmt.Println(s5)
fmt.Println(arr)
}
package main
import "fmt"
func main() {
var a []int = []int{1, 2, 3}
var b []int = []int{4, 5, 6}
a = append(a, 7, 8)
fmt.Println(a)
// append无法直接添加一个切片,需要使用...将切片打散
a = append(a, b...)
fmt.Println(a)
}
4. copy()函数
在两个 slice 间复制数据,两个 slice 可指向同一底层数组
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
s1 := arr[8:] // [8 9 10 11 12 13 14]
s2 := arr[:5] // [0 1 2 3 4]
fmt.Println(s1, s2)
// 从左侧开始覆盖
copy(s1, s2)
fmt.Println(s1, s2) // [0 1 2 3 4 13 14] [0 1 2 3 4]
fmt.Println(arr) // [0 1 2 3 4 5 6 7 0 1 2 3 4 13 14]
}
5. 切片扩容机制
用 make()创建切片,可以指定容量,当容量存储到上限,底层会自动扩容
package main
import "fmt"
func main() {
var a []int = make([]int, 5, 10)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a[0] = 10
a[1] = 20
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 30)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
for i := 0; i <= 8; i++ {
a = append(a, i)
fmt.Printf("for a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
}
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
}
切片再切片
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
b := a[1:3]
fmt.Printf("b=%v, len=%d, cap=%d\n", b, len(b), cap(b))
// 切片再切片
b = b[:cap(b)]
fmt.Printf("b=%v, len=%d, cap=%d\n", b, len(b), cap(b))
}
空切片的扩容机制
package main
import "fmt"
func main() {
var a []int
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 10)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 20)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 30)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 40)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 50)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
a = append(a, 60)
fmt.Printf("a=%v, len=%d, cap=%d\n", a, len(a), cap(a))
}