《The anatomy of Slices in Go》学习笔记
《The anatomy of Functions in Go》学习笔记

切片与数组

切片 VS 数组的定义

  • 切片是一个用来存储相同类型元素的容器,切片的长度不是固定的
  • 数组是一个用来存储相同类型元素的容器,数组的长度是固定的

切片与数组的表示

  • 切片

    1. var s []int
  • 数组

    1. var s [5]int

切片与数组的zero值

  • 切片的zero值是nil
  • 数组的zero值是元素类型的默认值,如 var s [5]int 的默认值是[0,0,0,0,0]

数组与切片作为函数的参数值

  • 数组作为函数的参数值传递仅仅是数组的拷贝
  • 切片作为函数的参数值传递的是切片的引用

数组

初始化值

var a [n]T = [n]T{V1,V2,…,Vn}
_

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

多行初始化值

最后一个元素必须以逗号结束

  1. var a = [3]string {
  2. "WHO",
  3. "AM",
  4. "I",
  5. }

自动声明数组的长度

  1. var a = [...]string {
  2. "WHO",
  3. "AM",
  4. "I",
  5. }

计算数组的长度

len()
_
比较数组的异同

  • 数组的长度必须相同
  • 数组对应位置上的元素必须相同

遍历数组

  1. package main
  2. import "fmt"
  3. func main() {
  4. a := [...]int{1,3,5,7,9}
  5. for index, value := range a {
  6. fmt.Printf("a[%d] is %d\n", index, value)
  7. }
  8. }

切片

指定数组的元素作为切片的值

[:]

切片的长度和容量
_len() 和 cap()

_

  • 切片是一种结构体
    1. type slice struct {
    2. zerothElement *type // 切片引用数组第一个元素的指针
    3. len int // 切片的长度
    4. cap int // 切片的容量
    5. }

由于切片仅仅是数组的引用,因此对切片的修改将会导致数组的值被修改
**

向切片中添加元素以及复制切片

append 函数 (golang内置)

func append(slice []Type, elems …Type) []Type

  • 如果将append函数的结果赋值给新的切片,原切片不会发生任何变化
  • 若添加元素得到切片的length小于被添加切片的capacity,被添加切片对应数组的相应位置上元素将会发生变化
  • 若添加元素得到切片的length大于被添加切片的capacity,被添加切片对应数组不会发生变化

以上两三点的主要区别在于当添加后切片的length大于capacity后,切片底层数组不能容下新添加的元素,因此会创建新的数组作为切片的底层数组。这样原切片对应的数组不会发生变化

copy 函数 (golang内置)

func copy(dst []Type, src []Type) int

注意:如果dst对应的切片是nil切片,copy函数不能生效

nil切片 VS 空切片

  • nil切片指仅仅定义切片并没有引用任一数组
  • 空切片指切片引用的数组为空

make函数 (golang内置)

s := make([]type, len, cap)
make函数用来创建指定类型的空切片

实战技巧

… 解构切片

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

删除切片的元素

  1. package main
  2. import "fmt"
  3. func main() {
  4. s := []int{1,2,3,4,5,6,7,8,9}
  5. s = append(s[:2], s[3:]...)
  6. fmt.Printf("slice value is %v\n", s)
  7. }

内存优化

切片引用的是数组,如果数组非常大,而且切片仅仅引用数组中小部分元素,因此只要切片在使用,对应的数组就不能得到释放,可以通过make函数创建空切片,并将数组中需要的元素通过切片copy到刚刚创建的切片上
**

  1. package main
  2. import "fmt"
  3. func changeValue() []string {
  4. arr := [10]string{
  5. "ANHUI",
  6. "ZHEJIANG",
  7. "GUANGZHOU",
  8. "CHONGQINF",
  9. "DALIAN",
  10. "NINGXIA",
  11. "LIAONING",
  12. "SHENZHEN",
  13. "HUERHAOTE",
  14. "KUNMING",
  15. }
  16. newSlice := make([]string, 3)
  17. copy(newSlice, arr[:3])
  18. return newSlice
  19. }
  20. func main() {
  21. s := changeValue()
  22. fmt.Printf("new slice value is %v\n", s)
  23. }