今天我们来学习一下Go语言中的切片和它的基本使用。

话外音

因为数组的长度是固定的且数组长度属于类型的一部分,因此数组在使用的过程中有很多的局限限。比如:

func arraySum(x [3]int) int{
    sum := 0
    for _, v := range x{
        sum = sum + v
    }
    return sum
}

这个数组求和的函数只能接收[3]int类型,其他的都不支持。再比如:

a := [3]int{1, 2, 3}

数组中已经有三个元素了,就不能继续添加新元素了。

简介

切片是拥有相同元素可变长度的序列,它是基于数组类型做的一层封装。它比数组要更加的灵活,支持自动扩容。切片是引用类型,它的内部结构包含地址长度容量。切片一般用户快速操作一块数据的集合。

定义

语法如下下:

var name []T

说明:

  • name - 变量名
  • T - 元素的类型

小示例:

func main() {
    var a []int
    var b = []int{}
    var c = []bool{false, true}
    var d = []bool{false, true}

    fmt.Println(a)        // []
    fmt.Println(b)        // []
    fmt.Println(c)        // [false true]
    fmt.Println(d)        // [false true]
    fmt.Println(a == nil) // true
    fmt.Println(b == nil) // false
    fmt.Println(c == nil) // false
    //fmt.Println(c == d) // 切片是引用类型,不支持直接比较,只能和nil比较
}

长度和容量

切片拥有自己的长度和容量,可以通过内置的len()求它的长度,通过内置的cap()求它的容量。注意:长度和容量并不是一个东西。

切片表达式

切片表达式是从字符串、数组、指向数组或切片的指针构造子字符串或切片。它有两种变体:一种指定lowhigh两个索引界限值的简单的形式,另一种是除了lowhigh索引界限值外还指定容量的完整的形式。

简单的切片表达式

切片的底层就是一个数组,因为我们可以基于数组使用切片表达式的方式得到切片。切片表达式中的lowhigh表示索引范围(左包含,右不包含),示例如下:

func main() {
    e := [5]int{0, 1, 2, 3, 4}
    f := e[1:3]
    
    fmt.Println(e)
    fmt.Println(f)
    fmt.Printf("f:%v len:%v cap:%v\n", f, len(f), cap(f))
}

输出:

f:[2 3] len:2 cap:4

为了方便起见,切片表达式中的索引还可以省略,如下:

a[2:] // 等同于a[2:len(a)]
a[:2] // 等同于a[0:2]
a[:]  // 等同于a[0:len(a)]
使用make()函数构造切片

上面都是基于数据构造切片的,其实如果想动态生成切片,我们可以使用 mark() 函数,语法如下:

make([]T, size, cap)

说明:

  • T - 切片的元素类型
  • size - 切片的元素数量
  • cap - 切片的容量

小示例:

func main() {
    a := make([]int, 3, 6)

    fmt.Println(a)      // [0 0 0]
    fmt.Println(len(a)) // 3
    fmt.Println(cap(a)) // 6
}
判断切片是否为空

判断切片是否为空,只能使用 len(a) == 0 来判断,不能使用 a == nil 来判断。

切片赋值拷贝

切片拷贝前台的两个变量是共享底层数据的,因为修改其中一个切片的值,另一个切片的值也会被修改,如下:

func main() {
    a := []int{1, 2, 3}
    b := a

    fmt.Println(a, b) // [1 2 3] [1 2 3]
    b[0] = 100        // 修改b切片值
    fmt.Println(a, b) // [100 2 3] [100 2 3]
}

切片拷贝还可以使用 copy() 函数,不同的是该函数拷贝出来的空间是独立的,如下:

func main() {
    a := []int{1, 2, 3}
    b := make([]int, 3, 3)
    
    copy(b, a)
    fmt.Println(a, b) // [1 2 3] [1 2 3]
    b[0] = 100        // 修改b切片值
    fmt.Println(a, b) // [1 2 3] [100 2 3]
}

切片添加元素

可以通过内建函数 append() 为切片添加元素,可以一次添加一个元素,可以添加多个元素,也可以添加另一个切片中的元素(后面加…),如下:

func main() {
    a := []int{1, 2}
    a = append(a, 3, 4)
    fmt.Println(a) // [1 2 3 4]
    
    b := []int{5, 6}
    a = append(a, b...)
    fmt.Println(a) // [1 2 3 4 5 6]
}
切片怎么删除元素呢?抱歉,木月内置函数,自己想办法!!!