[Go 入门] 第五章 数组、切片和映射

Go 入门系列参考于互联网资料与 人民邮电出版社 《Go 语言入门经典》 与 《Effective Go》,编写目的在于学习交流,如有侵权,请联系删除

通过本文将学习到Go语言编程中常用的3中数据结构, 本文内容:

使用数组

数组是一个数据集合,在编程中它通常按逻辑对数据进行分组。数组也是基本的编程构件,常用储存一系列用数字做索引的数据

在Go语言中,要创建数组,可声明一个数组变量,并指定其长度和数据类型

var cheeses [2]string

解读如下:

  • 使用关键字var声明一个名为cheeses的变量
  • 将一个长度为2的数组赋给这个变量
  • 这个数组的类型为字符串

声明变量后,就可以将字符串赋给数组的元素了

1
2
cheeses[0] = "test1"
cheeses[1] = "test2"

索引从0开始,如果需要打印所有元素,可以使用变量名本身

使用切片

在Go语言中,数组是一个重要的构件,但使用切片的情况更多。切片是底层数组中的一个连续片段,通过它您可以访问该数组中一系列带编号的元素。因此,切片能够让您顺序访问数组的特定部分

为何使用切片而不使用数组呢?

在 Go 语言中,使用数组存在一定的局限性,采用前面数组的cheeses表明方式,无法在数组中添加元素。然而切片比数组灵活,可以添加和删除元素,还可以复制切片中的元素,可将切片视为轻量级的数组包装器。既保留了数组的完整性,又比数组使用起来更容易

要声明一个长度为2的空切片:
var cheeses = make([]string, 2)

解读如下:

  • 使用关键字var声明一个名为cheeses的白能量
  • 在等号右边,使用Go内置函数make创建一个切片,其中第一个参数为数据类型,而第二个参数为长度
  • 将切片赋给变量cheeses

创建切片后,可以像数组赋值一样赋值给切片:

1
2
cheeses[0] = "test1"
cheeses[1] = "test2"

在切片中添加元素

Go 语言提供了内置函数append,能够增大切片的长度

1
2
cheeses := append(cheeses, "test3")
fmt.Println(cheeses[2])

append会在必要时调整切片的长度,同时append是一个不定参数函数,可以在末尾添加很多值

cheeses := append(cheeses, "test2", "test3", "test4")

从切片中删除元素

要从切片中删除元素,也可以使用append,下面是删除索引2处的元素:
cheeses = append(cheeses[:2], cheeses[2+1:]...)
通过在删除元素前后检查切片cheeses的长度,可知已经正确地的调整了该切片的长度,另外元素的排列顺序没有发生任何变化

append删除元素的方法拓展:

1
2
3
4
5
6
7
8
func main() {
var test = make([]string, 2)
test[0] = "test1"
test[1] = "test2"
test = append(test, "test3", "test4", "test5")
test = append(test[:1], test[3:]...)
fmt.Println(test)
}

使用append(变量[:索引], 变量[要保留的起始索引:]...)

如需要删除索引1的元素,并保留索引3以后的元素,则上述代码输出

[test1 test4 test5]

若改成

1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

func main() {
var test = make([]string, 2)
test[0] = "test1"
test[1] = "test2"
test = append(test, "test3", "test4", "test5")
test = append(test[:2])
fmt.Println(test)
}

则会删除索引2以后所有的元素,输出

[test1 test2]

复制切片中的元素

要复制切片的全部或者部分元素,可使用内置函数copy。在复制切片前,必须再声明一个类型与该切片相同的切片

1
2
3
4
5
6
7
8
func main() {
var cheeses = make([]string, 3)
cheeses[0] = "test1"
cheeses[1] = "test2"
var smellyCheeses = make([]string, 2)
copy(smellyCheeses, cheeses)
fmt.Println(smellyCheeses)
}

函数copy在新切片中创建元素的副本,因此修改一个切片中的元素不会影响到另一个切片。还可将单个元素或者特定范围的元素复制到新切片中,下面的示例复制索引1处的元素

1
copy(smellyCHeeses, cheeses[1:])

使用映射

数组和切片是可通过索引值访问的元素集合,而映射是通过键来访问的无需元素编组。在其他语言中,映射也被称为关联数组、字典或散列

创建一个空映射

var players = make(map[string]int)

解读如下:

  • 关键字 var 声明一个名为players的变量
  • 在等号右边,使用Go语言内置函数make创建了一个映射,其键的类型为字符串,而值的类型为整数
  • 将这个空映射赋给了变量players

添加键-值:

1
2
players["cook"] = 32
players["buck"] = 27

可在映射中动态地添加元素,而无须调整映射的长度。这是 Go 语言更像 Ruby 和 Python等动态语言,而不像 C 语言的方面

从映射中删除元素

要删除映射中的元素,可以使用内置函数delete

delete(players, "cook")

问题列表

  • 该使用数组还是切片?

    除非必须使用数组。否则请使用切片,切片能轻松的添/删元素,还无须处理内存分配问题

  • 没有从切片中删除元素的内置函数吗?

    不能将delete用于切片,没有专门用于从切片中删除元素的函数,但可以使用append完成,还能创建子切片

  • 需要指定映射的长度吗?

    不需要,使用内置函数make创建时,可以使用第二个参数,但这个参数只是容量提示,而非硬性规定。映射可根据要储存的元素数量自动增大,因此没有必要指定