美文网首页IT@程序员猿媛Go程序员
Go语言之初识切片和数组

Go语言之初识切片和数组

作者: 有财君 | 来源:发表于2019-05-09 23:37 被阅读0次

1. 数组

学Go语言之前我已经多年没有看过数组了,唯一和数组打交道也是用Java的ArrayList,虽然底层是用数组实现的,但是全部的接口都是List的。

数组一度被我认为是一种落后的数据结构了,在我用Python写数据库小工具的时候也是喜欢用list的,我甚至不知道Python是否支持数组。

数组,在C语言中简直就是个魔鬼,因为数组和指针那么的浑然天成...

不过学习Go,很多资料都会着重的讲述数组,这是因为数组是切片和映射的基础数据结构,是很重要的东西。

数组,在Go语言中是一种长度固定的数据类型,而且在内存中是连续分配的,检索速度也是很快的。

//最初学习C语言的时候,数组总是这样声明
var array [5]int

//还有这种声明方式
var array = [5]int{1,2,3,4,5}

//Go语言还能自动推断
array := [5]int{1,2,3,4,5}

//当然我不想数有多少个元素
array =: [...]int{1,2,3,4,5}

这几种都是Array常见的声明方式。如果没有初始化赋值,数组每一个元素都会被初始化为其类型的0值,在这个例子里,第一种声明方式就会变成下图这样:

数组的初始化

多像一只毛毛虫啊。Go还支持一种新奇的初始化方式:

//这种方式指定了几个index的值,其余的都是其类型的0值
array := [5]int{1, 10, 2:20}

Go数组的使用和C这种语言也没有什么区别,index也是从0开始。

2. 切片

用惯了ArrayList之后,感觉这种固定长度的数组就是不爽,很多时候我需要写一个循环,把循环的到的结果写入到List里,这个时候是绝对不能用固定长度数据结构的。

还好Go语言有切片这个数据结构。可以通过make函数或者字面量的形式创建切片,这两种方式都没有问题:

//创建一个长度和容量为5的切片
s1 := make([]int, 5)

//创建一个长度为5,容量为8的切片
s2 := make([]int, 5, 8)

这里引入了一个概念,切片的容量和长度。这是什么东西其实还要从底层的实现说起,刚才说了,数组是切片的底层数据结构:

切片的内部实现

其实,执行make函数创建一个长度为5,容量为8的切片就是做了这样一件事情,即创建了一个长度为8的数组,并且将指针指向了这个数组。

还要说明一点,如果创建了一个长度为5,容量为8的切片,那么直接打印这个切片,得到的一定是五个零:

package main

import "fmt"

func main() {
    // 示例 1。
    s1 := make([]int, 5, 8)
    fmt.Println(s1)
}

切片的操作也和数组一样,一切操作基于index,且index从0开始。

好玩的一点是,切片也是可以切分的:

package main

import "fmt"

func main() {
    // 示例 1。
    s1 := []int{1,2,3,4,5,6,7,8}
    s2 := s1[3: 6]
    //猜猜这里会输出什么?
    fmt.Println(s2)
    fmt.Println(cap(s2))
    fmt.Println(len(s2))
}

s1[4:7]代表着从index=3的地方开始切分,一直切刀index=6-1的地方,结果就是{4, 5, 6}。那么很明显,这个新的切片长度一定是3,但是容量呢?

容量是5。

这还是要从底层说起:

切片切分

虽然截取的是绿色的框,但是因为底层的数组实现,其实还是一个数组,因此,计算容量的时候,要把截取窗口右侧的元素也算上。

总结一个定理:

如果对底层数组是k的切片进行[i: j]的切分,其长度是j-i,其容量是k-i。

这个例子里,长度是7-4即3,容量是8-3即5。

切片既然长度是不定的,那么这个容量还有什么用处呢?

回忆一下Java的ArrayList就知道了,ArrayList底层也是使用数组实现,且初始化的时候会直接分配一个初始化长度的数组,当这个数组被填满的时候(这个时候可以认为容量不足),就会新分配一个数组。

切片也不例外,这么好的策略是放之四海而皆准的。当底层数组容量不够的时候,系统会分配给切片一个新的底层数组。这里有一个增长因子的概念,当切片元素超过1000个,则每次增加25%的容量。

3. 小结

用Python写小工具的时候,类型一直是个问题,有时候数据结构太多也是个问题,比如元组,列表,字典。有点乱花渐欲迷人眼的感觉。Go常用切片,数组和映射,相对简单很多,还能通过struct自己构建类型。

逐渐有了一种把原来写的Python数据库小工具改写成Go的冲动。毕竟Go是可以直接打包成可执行文件的,不需要考虑依赖,这对于没有办法连网的环境,是很可贵的。

参考:

《Go IN ACTION》

相关文章

  • Go语言切片

    // //Go语言切片 // /* // go语言切片是对数组的抽象 // Go 数组的长度不可改变,在特定场景中...

  • Go语言第3天 - 常用数据类型

    以下内容部分参考自Go语言基础数据类型Go语言中的数组切片:特立独行的可变数组Go语言数据类型-数组Go标准容器之...

  • 七、Go切片

    七、Go语言切片(Slice) Go 语言切片是对数组的抽象。 Go 数组的长度不可改变,在特定场景中这样的集合就...

  • Go 切片和数组

    数组 go创建数组和 c 语言类似,有如下两种方式: 切片 切片声明和数组类似,只是没有传递长度 创建二维切片,并...

  • go语言 数组和切片

    新手对于数组和切片要如何区分,概念比较模糊,看看下面的说明就懂了 记住,如果在[]运算符里指定了一个值,那么创建的...

  • Go语言数组和切片

    数组 数组概念 数组就是用于保存一组相同类型的数据 定义格式 操作数组的格式 数组的初始化 (赋值) 先定义再初...

  • Go语言数组和切片

    此处数组只讲Go语言中和C语言不一样的地方 格式不同:Go语言定义数组的格式:var ages [3]int 定义...

  • Go语言-数组和切片

    1 数组的定义 定义数组常规格式是:var 数组名 [元素数量] 元素类型 = {各元素},实际使用中,可以有很多...

  • Go语言--数组和切片

    一.数组1)定义: 2)初始化 二.切片1)定义: 2)初始化: 三.区别 数组是固定大小; 切片可以扩容 四.举...

  • 《golang高级编程》-读书笔记

    《Go语言高级编程》 作者 柴树杉 曹春晖 1.3 数组、字符串和切片 Go语言拷贝字符串,只是复制了底层字节数组...

网友评论

    本文标题:Go语言之初识切片和数组

    本文链接:https://www.haomeiwen.com/subject/gudnoqtx.html