定义切片(slice):
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
// 切片
fmt.Println(arr[2:6])
fmt.Println(arr[:6])
fmt.Println(arr[2:])
fmt.Println(arr[:])
// [2 3 4 5]
// [0 1 2 3 4 5]
// [2 3 4 5 6 7]
// [0 1 2 3 4 5 6 7]
}
切片本身没有数据,是对底层数组的视图(view):
func updateSlice(s []int) { // 切片是对数组的视图,可以通过切片来改变数组
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
// 切片
s1 := arr[2:]
s2 := arr[:]
updateSlice(s1)
fmt.Println(s1) // [100 3 4 5 6 7]
fmt.Println(arr) // [0 1 100 3 4 5 6 7]
updateSlice(s2)
fmt.Println(s2) // [100 1 100 3 4 5 6 7]
fmt.Println(arr) // [100 1 100 3 4 5 6 7]
}
func printArray(arr []int) { // 此时传入的是切片,不是数组
arr[0] = 100
for i, v := range arr {
fmt.Println(i, v)
}
}
func main() {
printArray(arr1[:])
printArray(arr3[:])
fmt.Println(arr1, arr3)
// [100 0 0 0 0] [100 4 6 8 10]
}
reslice操作(对切片再取切片):
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
// 切片
s2 = arr[:]
fmt.Println(s2) // [100 1 100 3 4 5 6 7]
// reslice
s2 = s2[:5]
fmt.Println(s2) // [100 1 100 3 4]
s2 = s2[2:]
fmt.Println(s2) // [100 3 4]
}
slice的扩展:
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
s1 := arr[2:6]
s2 := s1[3:5]
fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n", s1, len(s1), cap(s1)) // [2 3 4 5], 4, 6
fmt.Println(s1[4]) // 报错
fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n", s2, len(s2), cap(s2))
// [5 6], 2, 3
// 此处Slice进行了向后扩展(只能向后扩展,不能向前扩展)
fmt.Println(s1[3:6]) // [5 6 7]
}
slice是一个底层array的视图,其内部包含三个变量:
ptr : 指向array中slice开头的元素
len : slice的长度
cap : array中从ptr开始到结束的长度
使用s[i]进行索引不能超越len;
向后扩展可以超越len,但不能超越cap
向slice添加元素:
添加元素时如果超越cap,系统会重新分配更大的底层数组
由于值传递的关系,在使用append函数时必须接收append的返回值:
s = append(s, val)
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7} // 数组
s1 := arr[2:6]
s2 := s1[3:5] // [5 6]
s3 := append(s2, 10) // [5 6 10]
s4 := append(s3, 11) // [5 6 10 11]
s5 := append(s4, 12) // [5 6 10 11 12]
// 因为添加元素时超越了cap,s4和s5不再是arr的view,而是view了一个新的数组
fmt.Println(arr) // [0 1 2 3 4 5 6 10]
}
创建slice:
import "fmt"
func printSlice(s []int) {
fmt.Printf("%v, len=%d, cap=%d\n", s, len(s), cap(s))
}
func main() {
// 创建方式1:先定义,再初始化
var s []int // zero value for slice is nil
for i := 0; i < 100; i++ {
printSlice(s)
s = append(s, 2 * i + 1)
}
// 创建方式2:定义的同时初始化
// 该语句先创建array[2 4 6 8], 然后创建slice s1去view这个array
s1 := []int{2, 4, 6, 8}
printSlice(s1) // [2 4 6 8], len=4, cap=4
// 创建方式3:指定len
s2 := make([]int, 16)
printSlice(s2) // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
// 创建方式4: 指定len和cap
s3 := make([]int, 10, 32)
printSlice(s3) // [0 0 0 0 0 0 0 0 0 0], len=10, cap=32
}
其他操作:
func main() {
s1 := []int{2, 4, 6, 8}
printSlice(s1) // [2 4 6 8], len=4, cap=4
s2 := make([]int, 16)
printSlice(s2) // [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
s3 := make([]int, 10, 32)
printSlice(s3) // [0 0 0 0 0 0 0 0 0 0], len=10, cap=32
// copy slice
copy(s2, s1)
printSlice(s2) // [2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap=16
// deleting elements from slice
s2 = append(s2[:3], s2[4:]...)
printSlice(s2) // [2 4 6 0 0 0 0 0 0 0 0 0 0 0 0], len=15, cap=16
// popping from front
front := s2[0]
s2 = s2[1:]
fmt.Println(front) // 2
printSlice(s2) // [4 6 0 0 0 0 0 0 0 0 0 0 0 0], len=14, cap=15
// popping from back
tail := s2[len(s2)-1]
s2 = s2[:len(s2)-1]
fmt.Println(tail) // 0
printSlice(s2) // [4 6 0 0 0 0 0 0 0 0 0 0 0], len=13, cap=15
}