专栏首页学院君的专栏Go 语言基础入门教程 —— 数据类型篇:数组切片的创建和遍历

Go 语言基础入门教程 —— 数据类型篇:数组切片的创建和遍历

前一篇教程里我们已经介绍过数组的一个特点:数组的长度在定义之后无法修改,数组长度是数组类型本身的一部分,是数组的一个内置常量,因此我们无法在数组上做动态的元素增删操作。显然这种数据结构无法完全满足开发者的日常开发需求,尤其是从 PHP 转过来的开发人员(PHP 的数组非常灵活和强大),为此,Go 语言提供了数组切片(slice)来弥补数组的不足,数组切片一个最强大的功能就是支持对元素做动态增删操作,在介绍动态增删元素之前,我们先来了解下数组切片的定义和创建。

数组切片的定义

在 Go 语言中,数组切片是一个新的数据类型,与数组最大的不同在于,切片的类型字面量中只有元素的类型,没有长度:

var slice []string = []string{"a", "b", "c"}

因此它是一个可变长度的、同一类型元素集合,切片的长度可以随着元素数量的增长而增长(不会随着元素数量的减少而减少),不过数组切片从底层管理上来看依然使用数组来管理元素,可以看作是对数组做了一层简单的封装。基于数组,数组切片添加了一系列管理功能,可以随时动态扩充存储空间,下面我们就来看看数组切片的创建和使用。

创建数组切片

创建数组切片的方法主要有三种 —— 基于数组、数组切片和直接创建,下面我们来简要介绍一下这几种方法。

基于数组

数组切片可以基于一个已存在的数组创建。从这个层面来说,数组可以看作是切片的底层数组,而切片则可以看作是数组某个连续片段的引用。数组切片可以只使用数组的一部分元素或者整个数组来创建,甚至可以创建一个比所基于的数组还要大的数组切片:

// 先定义一个数组
months := [...]string{"January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"}

// 基于数组创建数组切片
q2 := months[3:6]    // 第二季度
summer := months[5:8]  // 夏季

fmt.Println(q2)
fmt.Println(summer)  

运行结果为:

[April May June]
[June July August]

Go 语言支持通过 array[first:last] 这样的方式来基于数组生成一个数组切片,而且这个用法还很灵活,比如下面几种用法都是合法的:

基于 months 的所有元素创建数组切片(全年):

all := months[:]

基于 months 的前 6 个元素创建数组切片(上半年):

firsthalf := months[:6]

基于从第 6 个元素开始的所有元素创建数组切片(下半年):

secondhalf := months[6:]

另外,通过这个示例,还可以探讨下数组切片底层的结构,数组切片底层引用了一个数组,由三个部分构成:指针、长度和容量,指针指向数组起始下标,长度对应切片中元素的个数,容量则是切片起始位置到底层数组结尾的位置,切片长度不能超过容量,比如上面的数组切片 q2,其指针指向底层数组 months 下标为 3 的位置,切片长度是3,切片容量是9(从下标3开始到下标11结束,可容纳9个元素),和数组一样,我们可以通过内置函数 lencap 来分别获取数组切片的长度和容量:

fmt.Println(len(q2))   // 3
fmt.Println(cap(q2))   // 9

基于数组切片

类似于数组切片可以基于一个数组创建,数组切片也可以基于另一个数组切片创建:

firsthalf := months[:6]
q1 := firsthalf[:3] // 基于firsthalf的前3个元素构建新数组切片

基于 firsthalf 创建数组切片时,选择的 firsthalf 元素范围可以超过所包含的元素个数,比如 q1 可以基于firsthalf 的前 9 个元素创建:

q1 := firsthalf[:9]

打印结果是:[January February March April May June July August September]

因为 firsthalf 的容量是 12,只要选择的范围不超过 firsthalf 的容量,那么这个创建操作就是合法的。

直接创建

并非一定要事先准备一个数组才能创建数组切片,Go 语言提供的内置函数 make() 可以用于灵活地创建数组切片。下面的例子示范了直接创建数组切片的各种方法:

// 创建一个初始元素个数为 5 的数组切片,元素类型为整型,初始值为 0,容量为 5
mySlice1 := make([]int, 5)

创建一个初始元素个数为 5 的整型数组切片,初始值为 [0 0 0 0 0],并将容量设置为10:

mySlice2 := make([]int, 5, 10)

此外,还可以直接创建并初始化包含 5 个元素的数组切片:

mySlice3 := []int{1, 2, 3, 4, 5}

事实上,使用直接创建的方式来创建数组切片 Go 底层还是会有一个匿名数组被创建出来,然后调用基于数组创建切片的方式返回数组切片,只是上层不需要关心这个匿名数组的操作而已。

元素遍历

操作数组元素的所有方法都适用于数组切片,比如数组切片也可以按下标读写元素,用 len() 函数获取元素个数,并支持使用 range 关键字来快速遍历所有元素。

传统的元素遍历方法如下:

for i := 0; i < len(summer); i++ {
    fmt.Println("summer[", i, "] =", summer[i]) 
}

打印结果如下:

summer[ 0 ] = June
summer[ 1 ] = July
summer[ 2 ] = August

使用 range 关键字可以让遍历代码显得更简洁,range 表达式有两个返回值,第一个是索引,第二个是元素的值:

for i, v := range summer { 
    fmt.Println("summer[", i, "] =", v) 
}

两种方式打印结果完全一致。

下一篇我们将给大家介绍数组切片的一些高级使用,比如动态增减元素、内容复制等。

本文分享自微信公众号 - 学院君的后花园(geekacademy),作者:学院君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-06-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Go 语言基础入门教程 —— 数据类型篇:数组及其使用

    数组是所有语言编程中最常用的数据结构之一,Go 语言也不例外,与 PHP、JavaScript 等弱类型动态语言不同,在 Go 语言中,数组是固定长度的、同一类...

    学院君
  • Go 语言基础入门教程 —— 数据类型篇:基本数据类型之间的转化

    通过前面几篇教程,我们已经陆续介绍完了 Go 语言中的基本数据类型,分别是布尔类型、整型、浮点型、复数类型、字符串和字符类型,和 PHP 一样,Go 语言也支持...

    学院君
  • PHP 数组:索引数组与关联数组

    在静态语言(C、Java、Go)中,数组的定义通常是同一类型数据的连续序列,PHP 的数组从功能角度来说更加强大,可以包含任何数据类型,支持无限扩容,并且将传统...

    学院君
  • 前端测试题: 数组的扩展中,不属于用于数组遍历的函数的是?

    方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可...

    舒克
  • C++小议二维数组

    一、二维数组的介绍 当数组元素具有两个下标时, 该数组称为二维数组。 二维谁可以看做具有行和列的平面数据结构。 二、二维数组的定义 定义二维数组的形式:

    老九学堂-小师弟
  • Go 语言基础入门教程 —— 数据类型篇:数组及其使用

    数组是所有语言编程中最常用的数据结构之一,Go 语言也不例外,与 PHP、JavaScript 等弱类型动态语言不同,在 Go 语言中,数组是固定长度的、同一类...

    学院君
  • 70个NumPy练习:在Python下一举搞定机器学习矩阵运算

    用户1737318
  • Java数组

    数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。

    用户5224393
  • C语言:多维数组

    多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。声明一个 x 行 y 列的二维整型数组,形式如下:

    用户6755376
  • 企业面试题:js编写数组去重方法

    【友情提示:舒克老湿意在为各位准备从事前端工程师岗位的小伙伴提供思路,所有代码仅供参考,切勿背题!!理解问题以及提高自己解决问题的能力最为重要!如果你有更好的解...

    舒克

扫码关注云+社区

领取腾讯云代金券