Go(Golang) 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。

Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。

现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。

在国内外,已经有很多大厂开始大规模使用Golang开发其云计算相关产品,比如Google、AWS、Cloudflare、阿里巴巴等。

而Go开发人员的全球平均薪资也是相当高。在美国,使用Go语言的开发者平均年薪为$ 136K。

在2019年Stack Overflow开发者调查中,Go是全球收入第三的语言。

因此,还没有开始学习Go的朋友,不妨来看看我今天推荐的教程《Go 语言实现常见数据结构》。

通过使用 Golang 实现常见的数据结构,加深大家对 Golang 的理解,并且可以强化大家的数据结构基本功。

先让我们一起来看看《Go 语言实现常见数据结构》节选吧,本节教程主要教大家学习Golang的数组与切片

教程节选:

实验1 数组与切片

实验介绍

从本实现开始我们将进入到 Golang 的学习之旅,Golang 的许多初学者都会对数组 (Array) 与切片 (Slice) 感到困惑。

他们虽然同属于集合类的类型,但是用起来却十分不同。在本节实验中,你将学习到数组与切片到底是哪里不同,这里也是 Golang 面试中的一个常考知识点。

知识点

  • 数组的数据类型
  • 数组的创建
  • 数组的遍历
  • Golang 数组与切片的区别
  • 切片的扩容规律

Golang 数组基本操作

这一节开始,我们将学习 Golang 数组与切片的常用方法以及他们在具体面试中的常考知识点。

数组的声明

Golang 中一个数组的声明方式主要有以下几种。

package mainfunc main() {// 第一种,在初始化时只声明数组长度,不声明数组内容var arr1 [5]int// 第二种,知道数据很多,不想自己写长度的时候可以用这种方式// 声明之后由编译器自己推算数组长度arr2 :=  [...]int{1,3,5,7,9}// 第三种,声明的时候长度和初值一起声明arr3 := [3]int{2,4,6}// 二维数组的声明,其意义是三行五列var Block [3][5]int
}

这里值得一提的是 Golang 中的数组的初始值如果你不做声明的话默认是全部有初值的。 比如 arr1 这个数组虽然只声明了长度为 5,但是 Go 的编译器也会把这 5 个元素全都初始化为 0。而对于 bool 值类型的数组,如果不做赋值操作,则初始值全为 false。在接下来的数组遍历中我们会实际的验证它。

数组的遍历

我们先在实验楼在线实验环境中新建新建一个名叫 array 的文件夹。如下图所示,先点击 File,然后点击 New Folder 创建名为 array 的文件夹。

然后我们右键点击 array 文件夹,选择 New File,创建一个叫 main.go 的文件,如下图所示。

Go 的数组遍历主要有以下两种方式。首先键入以下代码:

package mainimport "fmt"func main() {// 第一种,在初始化时只声明数组长度,不声明数组内容var arr1 [5]int// 第二种,知道数据很多,不想自己写长度的时候可以用这种方式// 声明之后由编译器自己推算数组长度//arr2 :=  [...]int{1,3,5,7,9}第三种,声明的时候长度和初值一起声明//arr3 := [3]int{2,4,6}二维数组的声明,其意义是三行五列var Block [3][5]bool// 第一种for i := 0 ; i<len(arr1); i++{fmt.Printf("%d\n",arr1[i])}// 第二种for index, value := range arr1 {fmt.Printf("索引:%d, 值: %d\n",index,value)}// 以第二种方式遍历二维数组,只取值,也就是取出一个数组for _,v := range Block {// 再对这个数组取值for _,value := range v {fmt.Printf("%v ",value)}fmt.Printf("\n")}}

接下来,在终端执行:

cd array
go run main.go

结果如下:

其中 Go 语言官方更加提倡的是第二种以 range 的方式进行遍历,这样写会让代码更加优雅,而且绝对不会越界。

那么,如果我只想要数组里的 index 不想要 value 时怎么 range 呢?

答案其实很简单,i := range arr 就可以了。如果你只想要 value 不想要索引的时候就可以这样写 _, value := range arr, 注意这里的下划线不能省略。

封装一个数组打印函数

现在咱们封装一个用来打印数组的函数并对其进行测试,代码如下:

func PrintArr(arr [5]int) {// 第二种for index, value := range arr {fmt.Printf("索引:%d, 值: %d\n",index,value)}
}

我们分别将 arr1,2,3 传入打印,先猜测一下会发生什么结果呢?

package mainimport "fmt"func main() {// 第一种,在初始化时只声明数组长度,不声明数组内容var arr1 [5]int// 第二种,知道数据很多,不想自己写长度的时候可以用这种方式// 声明之后由编译器自己推算数组长度arr2 :=  [...]int{1,3,5,7,9}第三种,声明的时候长度和初值一起声明arr3 := [3]int{2,4,6}PrintArr(arr1)PrintArr(arr2)PrintArr(arr3)
}func PrintArr(arr [5]int) {// 第二种for index, value := range arr {fmt.Printf("索引:%d, 值: %d\n",index,value)}
}

结果是程序在打印 arr3 时抛出了如下异常。

这个就要牵扯出一个概念了,Go 语言中数组是值类型。也就是说[3]int,和[5]int 在 go 中会认为是两个不同的数据类型。

同样地,你在 PrintArr 中改变数组中的值也不会改变原数组的值。

到了这里你肯定觉得 go 的数组太难用了,又要数据类型统一又要长度统一才能传递。确实是这样的,在 go 中我们一般不直接使用数组。而是使用我们今天的主角,切片。

Golang 切片的基本操作

一般而言,Go 语言的切片比数组更加灵活,强大而且方便。数组是按值传递的(即是传递的副本),而切片是引用类型,传递切片的成本非常小,而且是不定长的。

而且数组是定长的,而切片可以调整长度。创建切片的语法如下:

  • make([ ]Type, length, capacity)
  • make([ ]Type, length)
  • [ ]Type{}
  • [ ]Type{value1, value2, …, valueN}

内置函数 make() 用于创建切片、映射和通道。当用于创建一个切片时,它会创建一个隐藏的初始化为零值的数组,然后返回一个引用该隐藏数组的切片。

该隐藏的数组与 Go 语言中的所有数组一样,都是固定长度,如果使用第一种语法创建,那么其长度为切片的容量 capacity ;如果是第二种语法,那么其长度记为切片的长度 length 。一个切片的容量即为隐藏数组的长度,而其长度则为不超过该容量的任意值。另外可以通过内置的函数 append() 来增加切片的容量。

我们来执行一下下面的程序:

package mainimport "fmt"func main() {slice := make([]int,0)for i := 0 ;i < 10; i++ {// 动态的对切片进行扩容slice = append(slice, i)}fmt.Println(slice)// 调用PrintArrPrintArr(slice)// 看看是否切片的第一个元素改变了?fmt.Println(slice)
}func PrintArr(arr []int) {arr[0] = 100for index, value := range arr {fmt.Printf("索引:%d, 值: %d\n",index,value)}
}

执行结果:

执行之后我们会发现 slice[0] 的值确实被改变了。因为切片是引用传递,也就是直接把切片在内存中的地址传递过去。

这样我们在其他函数中对其进行修改也会影响原来的切片的数据。这样做的好处是传引用因为不用把原数据拷贝一份,所以对系统的开销比较小。

切片的切割

切片最大的特色就是可以灵活的进行切分,比如下面的例子。

package mainimport "fmt"func main() {slice := make([]int,0)for i := 0 ;i < 10; i++ {slice = append(slice, i)}fmt.Println(slice)s2 := slice[2:4]fmt.Println(s2)
}

执行结果:

这里的 2 可被称为起始索引,4 可被称为结束索引。那么 s2 的长度就是 4 减去 2,即 2。因此可以说,s2 中的索引从 0 到 1 指向的元素对应的是 slice 及其底层数组中索引从 2 到 3 的那 2 个元素。

到这里我们就可以推出 [n:m] 的意思是取区间 [n,m) 的数据赋值给新的切片。

关于数组与切片两道常见面试题

  • Golang 切片的扩容规则。

一旦一个切片无法容纳更多的元素,Go 语言就会想办法扩容。但它并不会改变原来的切片,而是会生成一个容量更大的切片,然后将把原有的元素和新元素一并拷贝到新切片中。在一般的情况下,你可以简单地认为新切片的容量将会是原切片容量的 2 倍。 但是,当原切片的长度大于或等于 1024 时,Go 语言将会以原容量的 1.25 倍作为新容量的基准。因为继续再乘以 2 的话切片容量增加的太快,很容易产生大量的浪费无意义的空间。 不过,如果我们一次追加的元素过多,以至于使新长度比原容量的 2 倍还要大,那么新容量就会以新长度为基准。比如你现在的切片长度为 10,现在一下往里面添加了 30 个元素,那么 Golang 会直接创建一个新的长度为 40 的底层数组,然后把所有的数据拷贝进去。

  • Golang 切片的底层数组在什么情况下会改变?

其实这里的典型回答应该是永远不会改变。因为当切片需要扩容时,新的切片诞生的同时也会创建出新的底层数组,它只是把原数组的数据拷贝了进来,并未对其做任何的修改。

一道思考题

现在我们已经学习了如何对数组进行“扩容”,那么你能否使用“扩容”的方式,把原切片进行缩容呢?请尝试写出代码,或查阅相关资料。

篇幅有限,暂时发布以上内容。

之后还有“栈与栈的应用”“队列与循环队列”等内容可以学习,感兴趣的朋友可以在《Go 语言实现常见数据结构》,学习之后的内容。

Go语言入门指南,带你轻松学Go相关推荐

  1. 《C语言入门指南》合集版,学习c语言有这一篇就够了?

    前言: <C语言入门指南>,全文分为3篇,共计34248字,此为合集版,适用初学者入门C语言,非初学者也可以通过本文复习C语言相关知识点,强化记忆!十三肝7天才弄完,贼累了,发布这篇笔记也 ...

  2. python语言编程基础-Python语言入门详解!快速学成Python!

    原标题:Python语言入门详解!快速学成Python! 很多技能是被职场所需要的,但很可惜... 这些技能在大学中并学习不到. 大学和职场现实存在的横沟对大部分同学来说难以跨越或碰得头破血流... ...

  3. python语言入门-Python语言入门详解!快速学成Python!

    原标题:Python语言入门详解!快速学成Python! 很多技能是被职场所需要的,但很可惜... 这些技能在大学中并学习不到. 大学和职场现实存在的横沟对大部分同学来说难以跨越或碰得头破血流... ...

  4. 【Go语言入门指南】零基础入门 go 语言 | Golang 入门指南

    文章目录 写在前面 全部练习项目都在github这个仓库中`https://github.com/CocaineCong/Golang-Learning` 1. [第一轮]基础部分 1.1 教程 1. ...

  5. python语言入门m-Python语言入门详解!快速学成Python!

    今日主题 "Python语言入门详解" 近两年来,Python语言借着数据科学和人工智能的"东风"成为了最流行的编程语言--街头巷尾人们口口相传.同时,Pyth ...

  6. (一)R语言入门指南——数据分析的第一步

    注:本博客旨在分享个人学习心得,有不规范之处请多多包涵! 目录 R语言 数值与逻辑运算符 变量类型与赋值 逻辑判定与循环 结束语 R语言 简单来说,R语言是一个免费开源.数据分析和可视化功能强大的编程 ...

  7. python3小游戏源代码_Python入门塔防小游戏,开发步骤和源码,带你轻松学python...

    在上一篇文章中,我介绍了有关python入门塔防小游戏的一些功能,下面我继续讲解有关这个小游戏的大致开发步骤. 开发工具还是: Python版本:3.6.4 相关的模块有:pygame模块,以及一些p ...

  8. python开发教程视频教程_金牌大神讲师Alex带你学Python 153节课带你轻松学透Python开发视频教程_IT教程网...

    (1)\第一章:目录中文件数:29个 ├─01课程介绍(一).mp4 ├─02课程介绍(二)-Python与其他语言的区别.mp4 ├─03课程介绍(三)-Python生态圈.mp4 ├─04课程介绍 ...

  9. python编程入门指南怎么样-如果想学python怎么入门?

    python入门相对容易对可以干很多事,是一门方便的工具语言. 在学习python之前,肯定都自己了解过这门语言,也知道python有很多学习方向.比如数据采集方向(爬虫),或者是Web开发方向,也可 ...

最新文章

  1. dubbo学习之-常用功能
  2. 回答跨专业考研者的几点疑问(计算机考研)
  3. root cause of error messagw for a mixed usage of 01 and 03
  4. CentOS 7安装redis及php扩展
  5. div 超出高度滚动条,超出宽度点点点
  6. MATLAB电压不平衡,电力系统不对称故障计算的Matlab算法程序
  7. mysql sum 对应_ASK MySQL查询SUM不同的表
  8. 5999卖999!是噱头还是颠覆
  9. mysql源码解读——MVCC
  10. Android10 mockLocation 模拟定位
  11. 视频传输协议总结、码率
  12. android自定义抽屉布局,自定义Drawer,抽屉布局
  13. 深圳市计算机素质测试答案,广东 : 2019年深圳计算机专业素质测试真题
  14. 知识库管理系统——项目
  15. vs 搭建团队项目服务器,tfs中如何创建团队项目及如何操作团队项目
  16. jQuery中的siblings()
  17. python爬取百度使用kw关键字爬取时出现,百度安全验证,解决方法
  18. python生成一个四位数字的随机数
  19. 前端实现炫酷动感时钟特效
  20. java通过poi读取excel中的日期类型

热门文章

  1. tail -f 不断刷新
  2. linux下mysql开启远程访问权限及防火墙开放3306端口(mysql开放host访问权限)
  3. 设置SecureCRT配色和解决乱码问题
  4. helloworld讲解cocos2d-x的编程思路与要点
  5. 黑马程序员之单例模式学习
  6. 关于如何正确地在android项目中添加第三方jar包
  7. 记录使用 Cake 进行构建并制作 nuget 包
  8. python爬虫之基于scrapy_redis的分布式爬虫
  9. Linux中相关知识(atexit(),fork(),粘滞位)
  10. 用二维数组实现矩阵转置