热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Golang中的Slice与数组及区别详解

数组是一种具有固定长度的基本数据结构,在golang中与C语言一样数组一旦创建了它的长度就不允许改变,数组的空余位置用0填补,不允许数组越界。今天小编通过实例代码操作给大家详细介绍lang中的Slice与数组的相关知识,一起看看吧

在golang中有数组和Slice两种数据结构,Slice是基于数组的实现,是长度动态不固定的数据结构,本质上是一个对数组字序列的引用,提供了对数组的轻量级访问。那么我们今天就给大家详细介绍下Golang中的Slice与数组,

1.Golang中的数组

    数组是一种具有固定长度的基本数据结构,在golang中与C语言一样数组一旦创建了它的长度就不允许改变,数组的空余位置用0填补,不允许数组越界。

     数组的一些基本操作:

     1.创建数组:

func main() {
 var arr1 = [...]int{1,2,3,4} //[...]默认为元素的数量即为数组的长度
 fmt.Println(len(arr1)) //4
 arr1[4] = 5 //panic 数组越界
 fmt.Println(arr1)
 var arr2 = [10]int{1,2,3,4}
 fmt.Println(arr2) //[1 2 3 4 0 0 0 0 0 0]
}

  2.数组是值拷贝传递:

func main() {
 var arr = [10]int{4,5,7,11,8,9}
 fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,0]
 //验证数组是值拷贝传递
 AddOne(arr)
 fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,0]
}
func AddOne(arr [10]int){
 arr[9] = 999999
 fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,999999]
}

2.Golang中的切片(slice) 

     1.首先看看slice的源码结构:

type slice struct {
 array unsafe.Pointer
 len int
 cap int
}

  slice是一个特殊的引用类型,但是它自身也是个结构体

       属性len表示可用元素数量,读写操作不能超过这个限制,不然就会panic

       属性cap表示最大扩张容量,当然这个扩张容量也不是无限的扩张,它是受到了底层数组array的长度限制,超出了底层array的长度就会panic

     2.slice的创建:

func main() {
  var arr = [...]int{0,1,2,3,4,5,6}
  slice1 := arr[1:4:5] //{low:high:max} 最多再扩张一个元素
  //max超出 len(arr)
  //slice2 := arr[1:4:7] //panic
  fmt.Println(slice1) //[1,2,3]
  slice3 := slice1[1:3:4] //[2,3] 大于4会panic
  fmt.Println(slice3)
}

 上面代码中创建了一个长度为7的数组arr,同时创建一个基于数组arr的切片slice1,切片引用了数组的index=1到index=3之间的元素,同时也允许切片最大扩张1个元素大小的空间。如果这个扩张空间大于7那么程序就会panic。最后创建了一个基于slice1延申的一个切片slice2,它引用了切片的index=1到index=3之间的元素,由于slice1最大扩容1个元素,因此slice2也最多扩容一个元素,超过了会panic。

    创建基于底层数组的slice,其cap取值在: len<=cap<=len(arr)之间

    创建基于一个切片的slice,其cap取值在: len(slice1)<=cap<=cap(slice1)之间

   3.slice使用make创建

func main() {
  var slice = make([]int,3,5) //len=3,cap=5
  fmt.Println(slice)  //[0,0,0]
  slice2:=slice[:5]  //slice实现了对slice的扩容,切片长度变为5
  fmt.Println(slice2) //[0,0,0,0,0]
}

   4.切片作为参数传递

func main() {
  var slice = make([]int,3,5) //len=3,cap=5
  fmt.Println(slice)  //[0,0,0]
  slice2:=slice[:5]  //slice实现了对slice的扩容,切片长度变为5
  fmt.Println(slice2) //[0,0,0,0,0]
  slice[0] = 999  //这里slice和slice的index=0位置都是999 因为他们引用的底层数组的index=0位置都是999
  fmt.Println(slice)
  fmt.Println(slice2)
  AddOne(slice) //[8888,0,0]
  fmt.Println(slice) //[8888,0,0]
  fmt.Println(slice2) //[8888,0,0,0]
}
func AddOne(s []int){
 s[0] = 8888
 fmt.Println(s)
}

  因为切片是个引用类型,所以它作为参数传递给函数,函数操作的实质是底层数组

3.Golang中的切片追加append()

func main() {
  var arr = [...]int{1,2,3,4}
  fmt.Println(arr) //[1,2,3,4]
  slice := arr[:]
  fmt.Println(slice) //[1,2,3,4]
  slice = append(slice,[]int{5,6,7}...) //此时slice的引用地址已经发生改变了,它引用的底层数组再也不是arr了,而是一个新的数组newarr[1,2,3,4,5,6,7]
  fmt.Println(slice) //[1,2,3,4,5,6,7]
  //验证slice引用的地址已经发生改变
  slice[0] = 666
  fmt.Println(arr) //[1,2,3,4]
  fmt.Println(slice) //[666,2,3,4,5,6,7]
}

  这里由于slice进行追加的元素超出了原来数组的大小,因此go内部会帮我们创建一个新的底层数组,而slice的引用地址不再是arr了,变成了新创建的数组。

       还有一种情况就是当slice进行追加的时候没有超出原来数组的大小的时候,其引用地址没有发生改变。

func main() {
  var arr = [6]int{1,2,3,4}
  fmt.Println(arr) //[1,2,3,4,0,0]
  slice := arr[:4]
  fmt.Println(slice) //[1,2,3,4]
  slice = append(slice,5)
  fmt.Println(arr) //[1,2,3,4,5,0]
  fmt.Println(slice) //[1,2,3,4,5]
}

4.总结

    (1)go是有数组的,只是平时用切片比较多。数组大小一旦创建就不能改变,数组长度大于元素个数的时候会用0补位,这跟其他语言是相通的。

     (2)切片slice可以看作是对数组的一切操作,它是一个引用数据类型,其数据结构包括底层数组的地址,以及元素可操作长度len或可扩容长度cap。

     (3)要想突破slice的扩容cap限制进行无限扩容就需要使用append()函数进行操作。如果append追加的元素后slice的总长度不超过底层数组的总长度,那么slice引用的地址不会发生改变,反之引用地址会           变成新的数组的地址。

     (4)slice是一个抽象的概念,它存在的意义在于方便对一个顺序结构进行一些方便操作,例如查找,排序,追加等等,这个类似于python的list。

下面看下golang 数组和slice 的区别

golang 数组和切片的区别

数组: 长度不可变,初始化的时候声明长度

slice 长度可变

var a [32] int

var b [3][5] int

a和b的类型不一样

slice 创建的时候可以不指定长度。

总结

到此这篇关于Golang中的Slice与数组及区别详解的文章就介绍到这了,更多相关golang slice 数据内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • Iamtryingtocreateanarrayofstructinstanceslikethis:我试图创建一个这样的struct实例数组:letinstallers: ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文介绍了使用Python解析C语言结构体的方法,包括定义基本类型和结构体类型的字典,并提供了一个示例代码,展示了如何解析C语言结构体。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Java编程实现邻接矩阵表示稠密图的方法及实现类介绍
    本文介绍了Java编程如何实现邻接矩阵表示稠密图的方法,通过一个名为AMWGraph.java的类来构造邻接矩阵表示的图,并提供了插入结点、插入边、获取邻接结点等功能。通过使用二维数组来表示结点之间的关系,并通过元素的值来表示权值的大小,实现了稠密图的表示和操作。对于对稠密图的表示和操作感兴趣的读者可以参考本文。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
author-avatar
dasda
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有