前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言——再论slice切片

Go语言——再论slice切片

作者头像
李海彬
发布2018-03-21 10:43:34
7320
发布2018-03-21 10:43:34
举报
文章被收录于专栏:Golang语言社区

Slice是长度可变的元素序列(数组不可变),每个元素都有相同的类型。slice类型写作[]T,其中T代表slice中的元素类型;slice和数组写法很像,只是没有指定长度。

  数组和slice之间的联系非常紧密。slice是非常轻量的数据结构,它是引用类型,指向底层的一个数组,该数组被称之为slice的底层数组,slice可以访问底层数组的某个子序列,也可以访问整个数组。一个slice由三个部分组成:指针、长度、容量,指针指向了slice中第一个元素对应的底层数组元素的地址,因为slice未必是从数组第一个元素开始,因此slice中的第一个元素未必是数组中的第一个元素。长度对应slice中的元素数目,长度是不能超过容量的;容量一般是从slice中第一个元素对应底层数组中的开始位置,到底层数组的结尾的长度。内置函数len和cap分别返回一个slice的长度和容量。

  多个slice可以共享底层的数组,甚至它们引用的底层数组部分可以重叠。图4.1表示了一个数组,它的元素是每个月份的字符串名,还有两个slice,它们重叠引用了底层数组。数组定义:

  months := [...]string{1: "January", /* ... */, 12: "December"}

  这里一月份是months[1],十二月是months[12]。通常来说,数组第一元素索引从0开始,但是月份一般是从1月开始到12月,因此在声明数组时,我们跳过了第0个元素,这里,第0个元素会被默认初始化为""(空字符串)。

  下面介绍切片操作s[i:j],这里0 ≤ i≤ j≤ cap(s),该操作会创建一个新的slice,引用s中从第i个元素到第j-1个元素的字序列,新的slice有j-i个元素。如果省略下标i:s[:j],实际上代表s[0:j];如果省略下标j:s[i:],代表s[0:len(s)]。因此months[1:13]操作将引用全部月份,和months[1:]操作等价。months[:]则是引用整个数组。下面分别表示第二个季度和北方的夏天:

  Q2 := months[4:7]

  summer := months[6:9]

  fmt.Println(Q2) // ["April" "May" "June"]

  fmt.Println(summer) // ["June" "July" "August"]

  两个slice有重叠部分:六月份,下面是一个包含相同月份的测试(性能不高):

  for _, s := range summer {

  for _, q := range Q2 {

  if s == q {

  fmt.Printf("%s appears in both\n", s)

  }

  }

  }

  如果slice操作的下标超过cap(s)将导致panic,如果超过len(s)则意味着扩展slice(不能超过cap(s)),因为新slice的长度会变大:

  fmt.Println(summer[:20]) // panic: out of range

  endlessSummer := summer[:5] // 在容量允许内扩展summer

  fmt.Println(endlessSummer) // "[June July August September October]"

  另外,字符串的slice操作和[]byte的slice操作是很相似的。它们都表现为x[m:n],并且都返回原始序列的子序列,底层数组也都是原始的序列,因此slice操作是常量级别的时间复杂度。若x[m:n]的目标是字符串,则生成一个子串;若目标是[]byte,则生成新的[]byte。

  因为slice引用包含了指向底层数组的指针,因此向函数传递slice后,函数可以在内部对slice的底层数组进行更改。换而言之,复制slice就是为底层数组创建一个新的引用,代价是非常低的(其实就是复制一个含有三个字段的struct)。下面的reverse函数对[]int类型的slice进行就地反转(无内存分配),它可以用于任意长度的slice:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Golang语言社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档