《The anatomy of Slices in Go》学习笔记
《The anatomy of Functions in Go》学习笔记
切片与数组
切片 VS 数组的定义
- 切片是一个用来存储相同类型元素的容器,切片的长度不是固定的
- 数组是一个用来存储相同类型元素的容器,数组的长度是固定的
切片与数组的表示
切片
var s []int
数组
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}
_
var a [3]int = [3]int{1, 2, 3}var a = [3]int{1, 2, 3}a := [3]int{1, 2, 3}
多行初始化值
最后一个元素必须以逗号结束
var a = [3]string {"WHO","AM","I",}
自动声明数组的长度
var a = [...]string {"WHO","AM","I",}
计算数组的长度
len()
_
比较数组的异同
- 数组的长度必须相同
- 数组对应位置上的元素必须相同
遍历数组
package mainimport "fmt"func main() {a := [...]int{1,3,5,7,9}for index, value := range a {fmt.Printf("a[%d] is %d\n", index, value)}}
切片
指定数组的元素作为切片的值
[:]
切片的长度和容量
_len() 和 cap()
_
- 切片是一种结构体
type slice struct {zerothElement *type // 切片引用数组第一个元素的指针len int // 切片的长度cap int // 切片的容量}
由于切片仅仅是数组的引用,因此对切片的修改将会导致数组的值被修改
**
向切片中添加元素以及复制切片
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函数用来创建指定类型的空切片
实战技巧
… 解构切片
package mainimport "fmt"func main() {s1 := make([]int, 0, 10)s2 := []int{1,3,5,7}s1 = append(s1, s2...)}
删除切片的元素
package mainimport "fmt"func main() {s := []int{1,2,3,4,5,6,7,8,9}s = append(s[:2], s[3:]...)fmt.Printf("slice value is %v\n", s)}
内存优化
切片引用的是数组,如果数组非常大,而且切片仅仅引用数组中小部分元素,因此只要切片在使用,对应的数组就不能得到释放,可以通过make函数创建空切片,并将数组中需要的元素通过切片copy到刚刚创建的切片上
**
package mainimport "fmt"func changeValue() []string {arr := [10]string{"ANHUI","ZHEJIANG","GUANGZHOU","CHONGQINF","DALIAN","NINGXIA","LIAONING","SHENZHEN","HUERHAOTE","KUNMING",}newSlice := make([]string, 3)copy(newSlice, arr[:3])return newSlice}func main() {s := changeValue()fmt.Printf("new slice value is %v\n", s)}
