7.1 数组

数组是一个定长的序列,大小不能增加。
数组内的元素都是同类型的,类型可以任意。
数组长度也是类型的一部分,所以[5]int和[6]int是以不同的类型。
数组的长度必须在声明的时候就给出,如果不知道,则用[…]int,编译器会自动根据元素判断。
数组长度最大为2G。
数组是值类型。所以传递给函数时是值拷贝。
声明:var arr [5]int
在内存中,数组的元素是整型值,所以每个元素的初始值为0。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. arr := [5]int{1, 2, 3, 4}
  7. var arr2 [5]int
  8. arr2 = [5]int{1, 2, 3}
  9. var arr3 = [2][3]int{ //多维数组
  10. {1, 2, 3},
  11. {4, 5, 6},
  12. }
  13. fmt.Println(arr) //[1 2 3 4 0]
  14. fmt.Println(arr2) //[1 2 3 0 0]
  15. fmt.Println(arr3) //[[1 2 3] [4 5 6]]
  16. }

7.2 切片

切片可以看作是不定长的数组,大小可以改变。
切片可以从数组中得到,可以是整个数组,也可以是数组的子集。
切片是引用类型
切片是不定长的,所以在声明时不需要指定大小。
可以使用len()函数计算切片长度,使用cap()函数获取切片容量。它等于切片长度+数组除切片之外的长度。
声明:var sli []int
切片其实是对数组的引用,在声明切片的时候,底层是有一个数组的,因为切片是引用类型,没数组它引用谁的呢?对切片的操作,就是对底层的那个数组操作。
所以,如果想要对一个数组进行操作,那么就要声明一个该数组的切片,切片是引用类型,切片的改变会使得数组的改变。

  1. package main
  2. import "fmt"
  3. func main() {
  4. arr := [5]int{1, 2, 3, 4} //数组arr
  5. sli := arr[1:] //切片[2,3,4]
  6. alterarr(sli)
  7. fmt.Println(arr) //原数组被更改为[1,3,3,4]
  8. }
  9. func alterarr(a []int) {
  10. a[0] = 3 //把切片的第一个元素2改为3
  11. }

如果想要声明固定的长度和容量的切片,需要make()函数:

  1. arr := make([]int, 5, 10) //声明一个长度为5,容量为10的切片

切片也能切字符串,但是字符串是纯粹不可改变的,所以不能像数组那么利用切片改值。如果要修改字符串,可以先将字符串转为字节数组,修改完再从字节数组转回字符串:

  1. package main
  2. import "fmt"
  3. func main() {
  4. s := "aaaaaaa"
  5. sb := []byte(s) //转为字节数组
  6. sb[0] = 'A' //修改字节,注意这里不能用双引号
  7. ss := string(sb) //转回字符串
  8. fmt.Println(ss) //Aaaaaaa
  9. }

切片之间可以使用copy函数。
切片追加元素可以使用append()函数,甚至可以追加切片。

  1. package main
  2. import "fmt"
  3. func main() {
  4. sli1 := []int{1, 2, 3}
  5. sli2 := make([]int, 10)
  6. _ = copy(sli2, sli1) //复制切片
  7. fmt.Println(sli2) //[1 2 3 0 0 0 0 0 0 0]
  8. sli2 = append(sli2, 9) //追加元素
  9. fmt.Println(sli2) //[1 2 3 0 0 0 0 0 0 0 9]
  10. }

遗憾,Go没有删除切片元素的函数,只能利用切片的性质性质自己改。
切片的排序可以使用sort()函数。

7.3 new()和make()的区别

  • 相同:
    • 均在堆上分配内存。
  • 不同:
    • new(T):为每个新的类型 T 分配一片内存,初始化为 0 并且返回类型为 *T 的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体;它相当于 &T{}。
    • make():返回一个类型为 T 的初始值,它只适用于 3 种内建的引用类型:切片、map 和 channel。

换言之,new() 函数分配内存,make() 函数初始化。