数组(Array)和切片(Slice)

一个切片是一个数组片断的描述。它包含了指向数组的指针、片断的长度和容量(片断的最大长度)数组

Array和Slice的区别app

  • Array是值类型,固定长度,大小是类型的一部分,当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组。而Slice在新元素加入的时候能够增长长度(增加到容量的上限)函数

  • slice 一个切片是一个数组片断的描述。它包含了指向数组的指针,片断的长度和容量(底层数组的长度)。 slice内部结构3d

定义数组:指针

<!-- lang: cpp -->
var a [32]byte
var b [5] struct { x, y int32 } //记录类型的数组
var c [1000]*float64 //数组元素是指向浮点型的指针
var d [3][5]int //二维数组
var e [2][2][2]float64  // 三维数组,跟这个同样 [2]([2]([2]float64))

//也能够直接赋值,无需指定数据长度,
//变量声明中的...至关于指定了数组的长度
var p [6]int = [...]int{2, 3, 5, 7, 11, 13}
var p = [...]int{2, 3, 5, 7, 11, 13} 
p := [...]int{2, 3, 5, 7, 11, 13}
//上面定义的p至关于类型[6]int

定义Slice:code

<!-- lang: cpp -->
//与数组的声明相似,只不过少了三点...
var p = []int{2, 3, 5, 7, 11, 13}
p := []int{2, 3, 5, 7, 11, 13} 
//使用s[lo:hi]进行切片,这种操做会返回一个新的指向数组的指针,而不会复制数组
//s[lo:hi]表示从 lo 到 hi-1 的 slice 元素
x := p[1:4] //引用数组的一部分
x := p[:3] //从0开始,截取到p[2]
x := p[4:] //截取到数组结尾,即len(p)

//使用make函数建立slice
a := make([]int, 5)  // len(a)=5
b := make([]int, 0, 5) // len(b)=0, cap(b)=5

slice 能够经过“从新切片”来扩容(增加到容量上限):blog

<!-- lang: cpp -->
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4

若是要动态增长slice的容量,则须要新建一个slice并把旧slice的数据复制过去图片

<!-- lang: cpp -->
//把s扩容两倍
t := make([]byte, len(s), (cap(s)+1)*2)//加1是为了防止cap(s)==0这种状况
copy(t, s) //使用内建函数copy复制slice
s = t

内建函数append,能够在slice后面添加一个元素或另外一个slice,当超出slice的容量上限时会再建立一个更大的数组,并把原slice的值复制到新数组内存

<!-- lang: cpp -->
a := make([]int, 1)// a == []int{0}
a = append(a, 1, 2, 3)//自动扩容 a == []int{0, 1, 2, 3}

//添加另外一个slice
a := []string{"John", "Paul"}
b := []string{"George", "Ringo", "Pete"}
a = append(a, b...) // 至关于 "append(a, b[0], b[1], b[2])"

slice 的零值是 nil,一个 nil 的 slice 的长度和容量是 0get

<!-- lang: cpp -->
var z []int //定义一个空的指针,z==nil,len(z)=0, cap(z)=0
z = make([]byte, 5, 5)//分配内存 z == []byte{0, 0, 0, 0, 0}

关于内存回收

当数组没被引用时,该数组的内存会被回收,所以使用slice时必须注意是否须要保留整个数组。例如,数组有一万个元素,但slice只引用了其中10个,而且后续的处理也只须要这10个,这就会致使额外的9990元素都保留在内存里。解决方法是把这10个元素复制到一个新的slice里,并把旧slice置为nil

参考资料:

Slices使用和内幕

相关文章
相关标签/搜索