天天看点

Go语言学习笔记——数组与切片(四)

数组(定长数组)

同一数据类型的固定长度的序列。

声明

var 数组名 [数组长度]元素数据类型
           
  • 数组长度必须是常量,且是类型的组成部分。
  • 数组定义后长度不能变。
  • 数组的类型为

    [数组长度]元素数据类型

    ,长度也是数组类型的一部分。
  • 数组赋值为值拷贝。

初始化

一维数组

声明一个有5个整型变量的数组,默认值都是0

[0 0 0 0 0]

声明一个有5个整型变量的数组,对前几个元素赋值,未赋值的元素为0

//全局变量
var arr1 [5]int = [5]int{1, 2, 3}
//局部变量
arr1 := [5]int{1, 2, 3}
           
[1 2 3 0 0]

声明一个有5个整型变量的数组,对前所有元素赋值

//全局变量
var arr2 [5]int = [5]int{1, 2, 3, 4, 5}
           
[1 2 3 4 5]

声明一个数组,通过初始化长度和值确定数组类型(元素数据类型和长度)。

//全局变量
var arr3 = [5]int{1, 2, 3, 4, 5}
//局部变量
arr3 := [5]int{1, 2, 3, 4, 5}
           
[1 2 3 4 5]

声明一个数组,通过初始化值确定数组长度(元素数据类型和长度)。

//全局变量
var arr4 = [...]int{1, 2, 3, 4, 5, 6}
//局部变量
arr4 := [...]int{1, 2, 3, 4, 5, 6}
           
[1 2 3 4 5 6]

声明一个数组,对指定位置的值赋值。

//全局变量
var arr5 = [5]int{3: 3, 4: 4}
//局部变量
arr5 := [5]int{3: 3, 4: 4}
           
[0 0 0 3 4]
多维数组

定义一个全零数组

[[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]]

定义一个多维数组并赋值

// 全局变量
var arr11 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
var arr12 [2][3]int = [2][3]int{{1, 2, 3}, {7, 8, 9}}
// 局部变量
arr11 := [...][3]int{{1, 2, 3}, {7, 8, 9}}
arr12 := [2][3]int{{1, 2, 3}, {7, 8, 9}}
           

[[1 2 3] [7 8 9]]

[[1 2 3] [7 8 9]]

定义一个多维数组并对指定位置的值赋值

// 全局变量
var arr21 [2][3]int = [...][3]int{1: {1: 2}}
var arr22 [2][3]int = [2][3]int{1: {1: 2}}
// 局部变量
arr21 := [...][3]int{1: {1: 2}}
arr22 := [2][3]int{1: {1: 2}}
           

[[0 0 0] [0 2 0]]

[[0 0 0] [0 2 0]]

访问数组元素

通过下标访问

arr0 := [8]int{1, 2, 3, 4}
v1 := arr0[2]
fmt.Println(v1)
           
3
arr00 := [...][3]int{{1, 2, 3}, {4}}
fmt.Println(arr00)
v2 := arr00[1][0]
fmt.Println(v2)
           

[[1 2 3] [4 0 0]]

4

数组的切片

//定义一个数组
arr := [...]int{1, 2, 3, 7, 2, 6, 8, 9, 4}
slice1 := arr[:]
slice2 := arr[2:]
slice3 := arr[:5]
slice4 := arr[2:5]
           

[1 2 3 7 2 6 8 9 4]

[1 2 3 7 2 6 8 9 4]

[3 7 2 6 8 9 4]

[1 2 3 7 2]

[3 7 2]

获取数组长度

内置函数

len()

cap()

都返回数组长度 (元素数量)。

arr11 := [...][3]int{{1, 2, 3}, {7, 8, 9}}
// 获取长度
fmt.Println(len(arr11))
// 获取容量
fmt.Println(cap(arr11))
           

2

2

遍历数组

一维数组

[1 2 3 4 5 6]

法一:

for i := range arr0 {
	fmt.Print(arr0[i])
}
           
123456

法二:

for i := 0; i < len(arr0); i++ {
	fmt.Print(arr0[i])
}
           
123456

多维数组

法一:

for k1, v1 := range arr00 {
	for k2, v2 := range v1 {
		fmt.Printf("(%d,%d)=%d ", k1, k2, v2)
	}
	fmt.Println()
}
           

(0,0)=1 (0,1)=2 (0,2)=3 (0,3)=0

(1,0)=4 (1,1)=5 (1,2)=6 (1,3)=7

(2,0)=8 (2,1)=9 (2,2)=0 (2,3)=0

法二:

for i := 0; i < len(arr00); i++ {
	for j := 0; j < len(arr00[i]); j++ {
		fmt.Printf("(%d,%d)=%d ", i, j, arr00[i][j])
	}
	fmt.Println()
}
           

(0,0)=1 (0,1)=2 (0,2)=3 (0,3)=0

(1,0)=4 (1,1)=5 (1,2)=6 (1,3)=7

(2,0)=8 (2,1)=9 (2,2)=0 (2,3)=0

切片(变长数组)

切片是数组的一个引用,但它并不是数组或数组指针。

  • 切片是引用类型。
  • 切片的长度可变。
  • 切片的底层是数组。
  • 可以使用切片进行数组的值拷贝,从而解决性能问题。

声明

var 切片名 []元素数据类型
           
  • 切片不需要说明长度。
  • 使用

    make()

    函数来创建切片时,切片容量可以省略。
  • 切片容量省略时,切片容量=切片长度
  • 切片容量 ≥ 切片长度,切片长度 ≤ 切片容量。
  • 当切片的底层数组不足以容纳所有给定值时,它就会分配一个更大的数组,切片会指向这个新分配的数组。

切片初始化

零切片声明,零值为

nil

var slice0 []int

// 不推荐
slice0 := []int{}
           
[]

使用

make()

函数初始化切片,默认赋0值

slice1 := make([]int, 5)
fmt.Println(slice1)
slice2 := make([]int, 5, 10)
fmt.Println(slice2)
           

[0 0 0 0 0]

[0 0 0 0 0]

初始化并赋值

slice3 := []int{1, 2, 3}
fmt.Println(slice3)
           

利用数组赋值

//定义一个数组
arr := [5]int{1, 2, 3, 7}
//定义一个切片
slice4 := make([]int, 5, 10)
//将数组赋值给切片(前闭后开区间)
slice4 = arr[0:5]
fmt.Println(slice4)
           
[1 2 3 7 0]

获取切片长度和容量

// 获取长度
fmt.Println(len(slice))
// 获取容量
fmt.Println(cap(slice))
           

切片截取

通过设置上限和下限截取切片(前闭后开区间)

//相当于[0:len(slice)]
slice1 := slice[:]

//相当于[2:len(slice)]
slice2 := slice[2:]

//相当于[0:5]
slice3 := slice[:5]

slice4 := slice[2:5]
           

追加元素

//定义一个切片
sliceA := make([]int, 2, 4)
           
[0 0]

追加单个元素

[0 0 1]

追加多个元素

[0 0 1 2 3 4]

切片拷贝

可以解决数组拷贝造成的性能问题。

//定义一个新的切片
sliceB := make([]int, 10, 20)
//把sliceA的值复制到sliceB
copy(sliceB, sliceA)
fmt.Println(sliceB)
           
[0 0 1 2 3 4 0 0 0 0]

遍历

参考数组的遍历方式