Go 语言切片(Slice)

Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

定义切片

你可以声明一个未指定大小的数组来定义切片:

var identifier []type

切片不需要说明长度。

或使用 make() 函数来创建切片:

make() 是 Go 语言内存分配的内置函数,默认有三个参数。

 

make(Type, len, cap)

Type:数据类型,必要参数,Type 的值只能是 slice、 map、 channel 这三种数据类型。
len:数据类型实际占用的内存空间长度,map、 channel 是可选参数,slice 是必要参数。
cap:为数据类型提前预留的内存空间长度,可选参数。所谓的提前预留是当前为数据类型申请内存空间的时候,提前申请好额外的内存空间,这样可以避免二次分配内存带来的开销,大大提高程序的性能。

为了能更好的理解这些参数的含义,我们先来看下 make() 的三种不同用法:

make(map[string]string)

make([]int, 2)

make([int, 2, 4])
  • 第一种,只传类型,不指定实际占用的内存空间和提前预留的内存空间,适用于 map 和 channel 。
  • 第二种,指定实际占用的内存空间为 2,不指定提前预留的内存空间。
  • 第三种,指定实际占用的内存空间为 2,指定提前预留的内存空间是 4。

  看到这里你有没有这样的疑惑,既然在初始化的时候已经指定数据的大小了,那为什么还要指定预留的大小呢?这是因为 make() 使用的是一种动态数组算法,一开始先向操作系统申请一小块内存,这个就是 cap,等 cap 被 len 占用满以后就需要扩容,扩容就是动态数组再去向操作系统申请当前长度的两倍的内存,然后将旧数据复制到新内存空间中。

package main
import "fmt"
func main() {
    data := make([]int,0)
    for i, n := 0, 20; i < n; i++{
        data = append(data, 1)
        fmt.Printf("len=%d cap=%d\n", len(data), cap(data))
    }
 }

// 结果:
len=1 cap=1
len=2 cap=2
len=3 cap=4
len=4 cap=4
len=5 cap=8
len=6 cap=8
len=7 cap=8
len=8 cap=8
len=9 cap=16
len=10 cap=16
len=11 cap=16
len=12 cap=16
len=13 cap=16
len=14 cap=16
len=15 cap=16
len=16 cap=16
len=17 cap=32
len=18 cap=32
len=19 cap=32
len=20 cap=32

 

append() 和 copy() 函数

如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。

var numbers []int
var numbers1 []int
numbers = append(numbers, 0)
copy(numbers1,numbers)

 

posted @ 2023-02-13 15:53  刘靖凯  阅读(65)  评论(0编辑  收藏  举报