Go 第6章 切片 Go 第6章 切片

2021-06-09

一、切片的概念

  • slice 本身没有数据,是对底层 array 的一个 view

  • 切片不是数组,它指向数组底层,会改变原数组

package main
import "fmt"
func updateSlice(s []int) {
    s[0] = 100
}
func main() {
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Println("arr[2:6] =", arr[2:6])
    fmt.Println("arr[:6] =", arr[:6])
    s1 := arr[2:]
    fmt.Println("s1 =", s1)
    s2 := arr[:]
    fmt.Println("s2 =", s2)
    fmt.Println("After updateSlice(s1)")
    updateSlice(s1)
    fmt.Println(s1)
    fmt.Println(arr)
    fmt.Println("After updateSlice(s2)")
    updateSlice(s2)
    fmt.Println(s2)
    fmt.Println(arr)
    fmt.Println("Reslice")
    fmt.Println(s2)
    s2 = s2[:5]
    fmt.Println(s2)
    s2 = s2[2:]
    fmt.Println(s2)
}
  • slice 扩展

package main
import "fmt"
func main() {
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Println("arr =", arr)
    s1 := arr[2:6]
    s2 := s1[3:5]
    fmt.Println("s1 =", s1)
    fmt.Println("s2 =", s2)
}

https://file.lulublog.cn/images/3/2022/08/Nf9ThBgHv9N4hQFbghFgZ90g4ZKc4k.png

  • slice 的实现如下图

  • slice 可以向后扩展,不可以向前扩展

  • s[i] 不可以超越 len(s)

  • 向后扩展不可以超越底层数组 cap(s):cap=capacity容量

  • 切片的 len(长度) 是当前切片中元素的个数

  • 切片的 cap(容量) 是他取自的数组的 cap

https://file.lulublog.cn/images/3/2022/08/f009c2cC6XaZex004Eh5eP5oXCC9H5.png

package main
import "fmt"
func main() {
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Println("arr =", arr)
    s1 := arr[2:6]
    s2 := s1[3:5]
    fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n",
s1, len(s1), cap(s1))
    fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n",
s2, len(s2), cap(s2))
}

二、切片的操作

  • 向 slice 添加元素:append(s, val)

    • 添加元素时如果超越 cap,系统会重新分配更大的底层数组

    • 由于值传递的关系,必须接收 append 的返回值

package main
import "fmt"
func main() {
    arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    fmt.Println("arr =", arr)
    s1 := arr[2:6]
    s2 := s1[3:5]
    s3 := append(s2, 10)
    s4 := append(s3, 11)
    s5 := append(s4, 12)
    fmt.Println("s3, s4, s5 =", s3, s4, s5)
    // s4 and s5 no longer view arr.
    fmt.Println("arr =", arr)
}
  • 创建 slice:make 函数

package main
import "fmt"
func main() {
    var s []int // Zero value for slice is nil
    for i := 0; i < 10; i++ {
printSlice(s)
s = append(s, 2*i+1)
    }
    fmt.Println(s)
    s1 := []int{2, 4, 6, 8}
    printSlice(s1)
    s2 := make([]int, 12)
    s3 := make([]int, 10, 32)
    printSlice(s2)
    printSlice(s3)
}
func printSlice(s []int) {
    fmt.Printf("%v, len=%d, cap=%d\n",
s, len(s), cap(s))
}
  • 复制 slice:copy 函数

    • 把第二个切片里的东西拷贝到第一个切片里要盖

package main
import "fmt"
func main() {
    s1 := []int{2, 4, 6, 8}
    printSlice(s1)
    s2 := make([]int, 12)
    printSlice(s2)
    copy(s2, s1)
    printSlice(s2)
}
func printSlice(s []int) {
    fmt.Printf("%v, len=%d, cap=%d\n",
        s, len(s), cap(s))
}
  • 删除 slice:删除第二个元素

package main
import "fmt"
func main() {
    s1 := []int{2, 4, 6, 8}
    printSlice(s1)
    s1 = append(s1[:1], s1[2:]...)
    printSlice(s1)
}
func printSlice(s []int) {
    fmt.Printf("%v, len=%d, cap=%d\n",
s, len(s), cap(s))
}
  • 删除 slice:删除头部、删除尾部

package main
import "fmt"
func main() {
   s1 := []int{2, 4, 6, 8}
   printSlice(s1)
   fmt.Println("Popping from front")
   front := s1[0]
   s1 = s1[1:]
   fmt.Println(front)
   printSlice(s1)
   fmt.Println("Popping from back")
   tail := s1[len(s1)-1]
   s1 = s1[:len(s1)-1]
   fmt.Println(tail)
   printSlice(s1)
}
func printSlice(s []int) {
   fmt.Printf("%v, len=%d, cap=%d\n",
s, len(s), cap(s))
}
阅读 926