GO学习笔记三-数组和切片

275 阅读2分钟

summary

  1. Arrays
    • Collection of items with same type
    • Fixed size 定义后长度就不可变了
    • Declaration styles
      • a := [3]int{1, 2, 3}
      • a := [...]int{1, 2, 3}
      • var a [3]int
    • Access via zero-based index 从零开始的索引
      • a := [3]int{1, 3, 5} //a[1] == 3
    • len function returns size of array
    • Copies refer to different underlying data 副本引用不同的底层数据结构,其实就是复制后就是新的地址
    • 数组的长度是数组类型的一个组成部分,因此[3]int和[4]int是两种不同的数组类型
    • 数组的长度必须是常量表达式,因为数组的长度需要在编译阶段确定。
  2. Slices
    • Backed by array 由数组支持
    • Creation styles
      • Slice existing array or slice
      • Literal style eg:a := []int{1, 3, 5}
      • Via make function
        • a := make([]int, 10) // len and cap = 10
        • a := make([]int, 10, 20) // len = 10, cap = 20
      • len function returns length of slice
      • cap function returns length of underlying array
      • append function to add elements to slice
        • May cause expensive copy operation if underlying array is too small
      • Copies refer to same underlying array
    • slice的切片操作s[i:j],其中0 ≤ i≤ j≤ cap(s),用于创建一个新的slice,引用s的从第i个元素开始到第j-1个元素的子序列。新的slice将只有j-i个元素。如果i位置的索引被省略的话将使用0代替,如果j位置的索引被省略的话将使用len(s)代替。

append函数

先看一段代码

var a = []int{1, 2, 3, 4, 5}
fmt.Println(a)
var b = append(a[:2], 1, 2, 3)
fmt.Println(b)
fmt.Println(a)
//output
//[1 2 3 4 5]
//[1 2 1 2 3]
//[1 2 1 2 3]
fmt.Printf("len(b)=%d, cap(b)=%d\n", len(b), cap(b))
b = append(b, 1, 2, 3)
fmt.Printf("len(b)=%d, cap(b)=%d\n", len(b), cap(b))
b = append(b, 1, 2, 3)
fmt.Printf("len(b)=%d, cap(b)=%d\n", len(b), cap(b))
//output
//len(b)=5, cap(b)=5
//len(b)=8, cap(b)=10
//len(b)=11, cap(b)=20

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

The append built-in function appends elements to the end of a slice. If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated. Append returns the updated slice. It is therefore necessary to store the result of append, often in the variable holding the slice itself

该函数会将 elems 追加到slice之后。如果slice有足够的capacity,那么直接追加#这时候也相应的直接改变了slice#。否则,会分配一个新的底层数组, cap 的计算是当前cap*2

反转数组

func reverse1(sl []int) []int {
	var sl2 = make([]int, len(sl))
	for i := 0; i < len(sl); i++ {
		sl2[i] = sl[len(sl) - 1 - i]
	}
	return sl2
}

func reverse2(sl []int) {
	for i, j := 0, len(sl) - 1; i < j; i, j = i+1, j-1 {
		sl[i], sl[j] = sl[j], sl[i]
	}
}