1、数组(Arrays)
1.1、数组基础
在Go中,数组是一组相同类型元素的集合。让我们看一个简单的例子:
go
package main
import "fmt"
func main() {
// 定义一个包含5个整数的数组
var numbers [5]int
// 初始化数组元素
for i := 0; i < 5; i++ {
numbers[i] = i * 2
}
// 打印数组元素
fmt.Println(numbers)
}
1.2、多维数组
Go支持多维数组,这是一个数组的数组。一个简单的二维数组示例:
go
package main
import "fmt"
func main() {
// 定义一个2x3的二维数组
var matrix [2][3]int
// 初始化二维数组元素
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
matrix[i][j] = i + j
}
}
// 打印二维数组
fmt.Println(matrix)
}
2、切片(Slices)
2.1、切片基础
切片是对数组的抽象,是一种更灵活的数据结构。让我们看一个简单的切片示例:
go
package main
import "fmt"
func main() {
// 创建一个切片
numbers := []int{1, 2, 3, 4, 5}
// 打印切片元素
fmt.Println(numbers)
}
2.2、创建切片的几种方式
下面的示例是创建切片的一些常见方式。根据不同的场景和需求,选择适合你情况的方式。
go
package main
import "testing"
// 直接初始化切片
func TestSliceCreate1(t *testing.T) {
slice := []int{1, 2, 3, 4}
t.Log(slice)
}
// 使用 make 函数创建切片,指定长度和容量
func TestSliceCreate2(t *testing.T) {
slice1 := make([]int, 3, 5) // 长度为3,容量为5
t.Log(slice1)
slice2 := make([]int, 5) // 长度和容量都是5
t.Log(slice2)
}
// 通过切片表达式,可以从数组或切片中创建一个新的切片
func TestSliceCreate3(t *testing.T) {
arr := [4]int{1, 2, 3, 4}
slice := arr[1:4]
t.Log(arr)
t.Log(slice)
}
// 使用`append`函数可以向切片动态添加元素
func TestSliceCreate4(t *testing.T) {
slice1 := []int{1, 2, 3, 4}
slice2 := append(slice1, 5, 6, 7)
t.Log(slice1)
t.Log(slice2)
}
// 通过使用`copy`函数,你可以从一个切片中复制元素到另一个切片,从而创建一个新的切片
func TestSliceCreate5(t *testing.T) {
slice1 := []int{1, 2, 3, 4}
slice2 := make([]int, len(slice1))
copy(slice2, slice1)
t.Log(slice2)
}
// 可以使用`[:]`操作符从数组或切片中创建一个新的切片
func TestSliceCreate6(t *testing.T) {
arr := [4]int{1, 2, 3, 4}
slice := arr[:]
t.Log(slice)
}
3、操作数组和切片的内置函数有哪些
3.1、切片相关内置函数
- make函数:
用于创建切片,可以指定切片的长度和容量。
go
slice := make([]int, 3, 5) // 创建长度为3,容量为5的切片
- append函数: 用于在切片末尾追加元素,可以同时追加多个元素。
go
slice := []int{1, 2, 3}
slice = append(slice, 4, 5, 6)
- copy函数:
用于将源切片的元素复制到目标切片,返回复制的元素个数。
go
slice1 := []int{1, 2, 3}
slice2 := make([]int, len(slice1))
copy(slice2, slice1)
- len函数:
返回切片的长度,表示切片中元素的个数。
go
slice := []int{1, 2, 3, 4, 5}
length := len(slice) // 返回5
- cap函数:
返回切片的容量,表示切片中可以存储的最大元素个数。
go
slice := make([]int, 3, 5)
capacity := cap(slice) // 返回5
3.2、数组相关内置函数
- len函数:
返回数组的长度,表示数组中元素的个数。
go
go
arr := [5]int{1, 2, 3, 4, 5}
length := len(arr) // 返回5
注意: 由于数组是固定长度的,没有动态增长的能力,因此没有像切片那样的append函数。
4、切片的动态调整和底层数组的关系是什么
切片是基于数组的一种抽象。切片包含三个关键属性:指向底层数组的指针、切片的长度和切片的容量。
- 指向底层数组的指针: 切片本身并不存储数据,而是通过指针引用底层数组的一部分。这意味着对切片的操作实际上是对底层数组的操作。
- 切片的长度: 表示切片中的元素数量。它可以动态增长,但不能超过底层数组的容量。
- 切片的容量: 表示切片最多可以容纳的元素数量,包括从切片的开始位置到底层数组的末尾的元素。容量的增长也受到底层数组容量的限制。
动态调整的过程:
- 初始创建: 当使用切片表达式或
make
函数创建一个切片时,它会指向底层数组的全部元素。 - 追加元素: 当使用
append
函数向切片追加元素时,如果切片的长度小于底层数组的容量,直接在底层数组上添加元素。如果长度超过了容量,Go会创建一个新的底层数组,并将原有的元素复制到新数组中,然后在新数组上添加元素。 - 切片的长度和容量: 切片的长度会根据追加的元素动态增长,而容量取决于底层数组的容量。容量的增长也是动态的,但不能超过底层数组的容量。
这种机制使得切片能够在不需要手动管理内存的情况下动态增长,同时避免了过多的数组复制。由于切片是对底层数组的引用,任何对切片的修改都会影响到底层数组,反之,也是这样。
需要注意的是,当多个切片共享同一个底层数组时,对其中一个切片的修改会影响到其他切片,因为它们共享相同的内存空间。这是在使用切片时需要注意的一点。