Go 语言入门指南:基础语法和常用特性解析 | 青训营;

84 阅读3分钟

数组

Go语言中,一个数组变量表示整个数组,它不是指向第一个元素的指针(不像 C 语言的数组)。 当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组

切片

切片是数组的引用

切片并不存储任何数据,它只是描述了底层数组中的一段。更改切片的元素会修改其底层数组中对应的元素。与它共享底层数组的切片都会观测到这些修改。

func main() {
	names := [4]string{
		"John",
		"Paul",
		"George",
		"Ringo",
	}
	fmt.Println(names)// [John Paul George Ringo]
        
        // 从数组中截取得到切片
	a := names[0:2] // 截取的是 左闭右开的区间 [0,2)
	b := names[1:3]
	fmt.Println(a, b)// [John Paul] [Paul George]

	b[0] = "XXX"// 修改
  // a,b和底层数组都被修改了
	fmt.Println(a, b)// [John XXX] [XXX George]
	fmt.Println(names)// [John XXX George Ringo]

}

切片既可以从数组或切片中截取(截取不能超出它的容量,索引也不能为负值),也可以直接创建

切片类型的写法是 []T,像是没有指定长度的数组

letters := []string{"a", "b", "c", "d"}

切片可以使用内置函数 make 创建,函数签名为:

func make([]T, len, cap) []T  // len 表示切片长度,cap表示切片底层数组的长度(可选,若不指定则于len相等)

// eg:
s := make([]byte, 5, 5)// 指定cap为5
q := make([]byte, 5)// len(s) = 5    cap(s) = 5

切片的内幕

一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度, 和容量(片段的最大长度)。 切片的零值为 nil 。对于切片的零值, len 和 cap 都将返回0。

sl := make([]byte, 5, 5) // 0 0 0 0 0 
// 此时 len(sl) == 5  cap(sl) == 5

image.png

// 截取
sl = sl[2:4] // 截取自己

image.png

此时 len(sl) == 2 cap(sl) == 3 因为cap是从切片开头到最后算的,且截取操作不可逆,无法再截取到底层数组索引为0和1的块了。

s = s[:cap(s)] // 截取后面全部

image.png

copy and append 函数

copy 函数签名: func copy(dst, src []T) int 表示将src切片的元素复制到dst,返回值是复制的元素个数。

s1 := []int{1, 3, 4, 6}  
s2 := make([]int, 7)  
num := copy(s2, s1)  
fmt.Println(num)// 4

append 函数签名:func append(s []T, x ...T) []Tx...T表示要增加的类型为T的元素列表。 该函数将元素追加到切片尾部, 必要的话会增加切片的容量,最后返回更新的切片:

s1 := []int{1, 3}  // cap(s1) == 2
s1 = append(s1, 9, 0, 90) // 容量不够,增加了容量 cap(s1) == 5  s1 == {1, 3, 9, 0, 90}
  • 注意

切片操作并不会复制底层的数组。整个数组将被保存在内存中,直到它不再被引用。 有时候可能会因为一个小的内存引用导致保存所有的数据。就是说,如果一个切片中有很多数据,其中个别数据被其他变量引用会导致整个切片都存在内存中,占用较大内存,浪费资源。

解决方法是将要用到的数据复制到新的切片中去。

写在最后

刚开始有些不太清楚的地方,自己搞清楚之后记录下来

image.png

over~