这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记

56 阅读2分钟

03 切片append

`package main

import "fmt"

func main() { s := []int{2, 3, 5, 7, 11, 13} printSlice(s)

// 截取切片使其长度为 0 s = s[:0] printSlice(s)

// 拓展其长度 s = s[:5] printSlice(s)

// 第一次增加 s = append(s, 1) printSlice(s)

// 第二次增加 s = append(s, 1) printSlice(s) } func printSlice(s []int) { fmt.Printf("len=%d cap=%d ptr=%p %v\n", len(s), cap(s), s, s) }

len=6 cap=6 ptr=0x450000 [2 3 5 7 11 13] len=0 cap=6 ptr=0x450000 [] len=5 cap=6 ptr=0x450000 [2 3 5 7 11] len=6 cap=6 ptr=0x450000 [2 3 5 7 11 1] len=7 cap=12 ptr=0x44e030 [2 3 5 7 11 1 1]`

第一次append的时候,长度没有超过容量,所以容量没有变。 第二次append的时候,长度超过了容量,这时容量会扩展到原来的2倍。 同时,增加后的切片地址和原来不同,也就是说: append操作可能会导致原本使用同一个底层数组的两个Slice变量变为使用不同的底层数组。

04 切片append`

``package main

import "fmt"

func main() { s := []int{2, 3, 5, 7, 11, 13} printSlice(s)

// 截取切片使其长度为 0 s = s[:0] printSlice(s)

// 拓展其长度 s = s[:4] printSlice(s)

// append后再切片 s = append(s, 4) s = s[:6] printSlice(s) } func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) }

len=6 cap=6 [2 3 5 7 11 13] len=0 cap=6 [] len=4 cap=6 [2 3 5 7] len=6 cap=6 [2 3 5 7 4 13]``

这里验证一个问题,在[2 3 5 7]基础上append一个4后,在全容量获取切片,发现最后一个13还在,只是11被4替换了。 这说明append的写入是把slice后边数据逐个覆盖掉。

05 切片copy

用于将内容从一个数组切片复制到另一个数组切片。如果加入的两个数组切片不一样大,就会按其中较小的那个数组切片的元素个数进行复制。

`package main

import "fmt"

func main() { slice1 := []int{1, 2, 3, 4, 5} slice2 := []int{5, 4, 3} slice3 := []int{5, 4, 3}

copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中 printSlice(slice2)

copy(slice1, slice3) // 只会复制slice3的3个元素到slice1的前3个位置 printSlice(slice1) }

func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s) }

len=3 cap=3 [1 2 3] len=5 cap=5 [5 4 3 4 5]

要增加切片的容量必须创建一个新的、更大容量的切片,然后将原有切片的内容复制到新的切片。 整个技术是一些支持动态数组语言的常见实现。下面的例子将切片 s 容量翻倍,先创建一个2倍 容量的新切片 t ,复制 s 的元素到 t ,然后将 t 赋值给 s :

t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0 for i := range s {