Published 2020-05-25

Go - 数组、切片

在 Go 语言中,数组和切片是常见的数据类型。它们都可以用来存储一组有序的数据,但它们在底层实现和使用方式上有所不同。

数组 (Array)

数组是一种固定大小的数据结构,它由一系列具有相同类型的元素组成,这些元素在内存中是连续存储的。数组的大小在定义时就确定,不能修改。在 Go 语言中,数组的定义方式如下:

var a [5]int // 定义一个长度为 5 的整型数组

在数组中访问和修改元素可以使用索引操作符 [],索引从 0 开始。例如,要访问数组中的第一个元素,可以使用 a[0]。

下面是一个简单的示例,演示如何使用数组:

package main
 
import "fmt"
 
func main() {
    var a [5]int
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    a[4] = 5
 
    fmt.Println("Array:", a) // 输出整个数组
 
    fmt.Println("Length:", len(a)) // 输出数组的长度
 
    fmt.Println("First element:", a[0]) // 输出数组的第一个元素
 
    fmt.Println("Last element:", a[len(a)-1]) // 输出数组的最后一个元素
}

输出结果如下:

Array: [1 2 3 4 5]
Length: 5
First element: 1
Last element: 5

需要注意的是,当将数组传递给函数时,将传递整个数组的副本而不是指向原始数组的指针。这意味着,在函数中对数组的修改不会影响原始数组的值。

切片 (Slices)

切片是一种动态大小的数据结构,它是基于数组实现的。切片可以看作是一个指向数组的指针,它包含一个指向数组的指针、长度和容量。切片的长度表示它当前包含的元素数量,而容量表示它可以包含的元素数量,容量可以在运行时动态扩展。在 Go 语言中,可以使用以下方式来创建切片:

a := []int{1, 2, 3, 4, 5} // 使用字面量创建切片
 
b := make([]int, 5) // 使用 make 函数创建长度为 5 的整型切片

可以使用索引操作符 [] 访问和修改切片中的元素。可以使用 append 函数向切片中添加新元素。以下是一个简单的示例:

package main
 
import "fmt"
 
func main() {
    a := []int{1, 2, 3, 4, 5}
 
    fmt.Println("Slice:", a) // 输出整个切片
 
    fmt.Println("Length:", len(a)) // 输出切片的长度
 
    fmt.Println("Capacity:", cap(a)) // 输出切片的容量
 
    fmt.Println("First element:", a[0]) // 输出切片的第一个元素
 
    fmt.Println("Last element:", a[len(a)-1]) // 输出切片的最后一个元素
 
    a = append(a, 6) // 向切片中添加一个元素
 
    fmt.Println("Slice after append:", a) // 输出添加元素后的切片
}
 

输出结果如下:

Slice: [1 2 3 4 5]
Length: 5
Capacity: 5
First element: 1
Last element: 5
Slice after append: [1 2 3 4 5 6]

需要注意的是,当将切片传递给函数时,将传递一个指向底层数组的指针。这意味着,在函数中对切片的修改将影响原始切片的值。

另外,切片还有一个重要的特性,就是可以使用切片表达式从一个已有的切片中获取一个新的切片。切片表达式的语法如下:

a[low:high]

其中,low 和 high 分别表示新切片的第一个和最后一个元素的索引(不包含最后一个元素)。以下是一个示例:

package main
 
import "fmt"
 
func main() {
    a := []int{1, 2, 3, 4, 5}
 
    b := a[1:3] // 获取 a[1] 到 a[2](不包含 a[3])的切片
 
    fmt.Println("Slice:", b) // 输出新的切片
}

输出结果如下:

Slice: [2 3]

需要注意的是,切片表达式返回的是一个新的切片,它共享原始切片的底层数组。这意味着,在新切片和原始切片中修改元素将影响到彼此。因此,在使用切片表达式时需要格外小心。