文档章节

数组(Array)和切片(Slice)

烈冰
 烈冰
发布于 2012/11/06 20:25
字数 870
阅读 2593
收藏 1

一个切片是一个数组片段的描述。它包含了指向数组的指针、片段的长度和容量(片段的最大长度)

Array和Slice的区别

  • Array是值类型,固定长度,大小是类型的一部分,当一个数组变量被赋值或者被传递的时候,实际上会复制整个数组。而Slice在新元素加入的时候可以增加长度(增长到容量的上限)

  • slice 一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度和容量(底层数组的长度)。 slice内部结构

定义数组:

<!-- lang: cpp -->
var a [32]byte
var b [5] struct { x, y int32 } //记录类型的数组
var c [1000]*float64 //数组元素是指向浮点型的指针
var d [3][5]int //二维数组
var e [2][2][2]float64  // 三维数组,跟这个一样 [2]([2]([2]float64))

//也可以直接赋值,无需指定数据长度,
//变量声明中的...相当于指定了数组的长度
var p [6]int = [...]int{2, 3, 5, 7, 11, 13}
var p = [...]int{2, 3, 5, 7, 11, 13} 
p := [...]int{2, 3, 5, 7, 11, 13}
//上面定义的p相当于类型[6]int

定义Slice:

<!-- lang: cpp -->
//与数组的声明类似,只不过少了三点...
var p = []int{2, 3, 5, 7, 11, 13}
p := []int{2, 3, 5, 7, 11, 13} 
//使用s[lo:hi]进行切片,这种操作会返回一个新的指向数组的指针,而不会复制数组
//s[lo:hi]表示从 lo 到 hi-1 的 slice 元素
x := p[1:4] //引用数组的一部分
x := p[:3] //从0开始,截取到p[2]
x := p[4:] //截取到数组结尾,即len(p)

//使用make函数创建slice
a := make([]int, 5)  // len(a)=5
b := make([]int, 0, 5) // len(b)=0, cap(b)=5

slice 可以通过“重新切片”来扩容(增长到容量上限):

<!-- lang: cpp -->
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4

如果要动态增加slice的容量,则需要新建一个slice并把旧slice的数据复制过去

<!-- lang: cpp -->
//把s扩容两倍
t := make([]byte, len(s), (cap(s)+1)*2)//加1是为了防止cap(s)==0这种情况
copy(t, s) //使用内建函数copy复制slice
s = t

内建函数append,可以在slice后面添加一个元素或另一个slice,当超出slice的容量上限时会再创建一个更大的数组,并把原slice的值复制到新数组

<!-- lang: cpp -->
a := make([]int, 1)// a == []int{0}
a = append(a, 1, 2, 3)//自动扩容 a == []int{0, 1, 2, 3}

//添加另一个slice
a := []string{"John", "Paul"}
b := []string{"George", "Ringo", "Pete"}
a = append(a, b...) // 相当于 "append(a, b[0], b[1], b[2])"

slice 的零值是 nil,一个 nil 的 slice 的长度和容量是 0

<!-- lang: cpp -->
var z []int //定义一个空的指针,z==nil,len(z)=0, cap(z)=0
z = make([]byte, 5, 5)//分配内存 z == []byte{0, 0, 0, 0, 0}    

关于内存回收

当数组没被引用时,该数组的内存会被回收,因此使用slice时必须注意是否需要保留整个数组。例如,数组有一万个元素,但slice只引用了其中10个,并且后续的处理也只需要这10个,这就会导致额外的9990元素都保留在内存里。解决方法是把这10个元素复制到一个新的slice里,并把旧slice置为nil

参考资料:

Slices使用和内幕

© 著作权归作者所有

共有 人打赏支持
烈冰
粉丝 49
博文 36
码字总数 8397
作品 1
佛山
架构师
加载中

评论(3)

_凤求凰_
_凤求凰_

引用来自“烈冰”的评论

引用来自“范庆辉”的评论

注意排班啊。。。好好学习go...

在客户端看起来是很乱

洗洗睡吧。。。
烈冰
烈冰

引用来自“范庆辉”的评论

注意排班啊。。。好好学习go...

在客户端看起来是很乱
_凤求凰_
_凤求凰_
注意排班啊。。。好好学习go...
Go基础编程:复合类型—切片slice

1. 概述 数组的长度在定义之后无法再次修改;数组是值类型,每次传递都将产生一份副本。显然这种数据结构无法完全满足开发者的真实需求。Go语言提供了数组切片(slice)来弥补数组的不足。 ...

tennysonsky
2017/12/13
0
0
Go语言学习笔记(三)数组 & 切片 & map

加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 数组 Arrays 数组是同一种数据类型的固定长度的序列。 数组是值类型,因此改变副本的值,不会改变本身的值; 当作为方法的入...

xumaojun
03/12
0
0
golang: 常用数据类型底层结构分析

虽然golang是用C实现的,并且被称为下一代的C语言,但是golang跟C的差别还是很大的。它定义了一套很丰富的数据类型及数据结构,这些类型和结构或者是直接映射为C的数据类型,或者是用C struc...

陈亦
2014/01/29
0
9
Go 语言初级教程之六[基本类型]

基本类型 像C语言一样,Go提供了一系列的基本类型,常见的布尔,整数和浮点数类型都具备。它有一个Unicode的字符串类型 和数组类型。同时该语言还引入了两 种新的类型:slice 和map。 数组和...

刘赤龙
2010/06/08
0
0
GoLang笔记-数组和切片,本质是就是长度不可变的可变的区别

数组 Arrays 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值。在初始化后长度是固定的,无法修改其长度。当作为方法的入参传入时将复制一份...

桃子红了呐
2017/11/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《Netkiller Java 手札》· 二进制文件操作大全

本文节选自《Netkiller Java 手札》 Netkiller Java 手札 Mr. Neo Chan, 陈景峯(BG7NYT) 中国广东省深圳市望海路半岛城邦三期 518067 +86 13113668890 <netkiller@msn.com> $Id: book.xml 6......

netkiller-
27分钟前
1
0
Fiddler Debugger post请求

常用的两种: 第一种默认的 对应URL为www 的要用请求头为:Content-Type: application/x-www-form-urlencoded 请求参数为 :param1=1234¶m2=12345 注:有些接口是指定用这种的第二方式并不...

轻量级赤影
34分钟前
2
0
如何搭建母婴亲子类知识社区

近期社交领域融资动作频繁,海尔高管、海尔医疗有限公司总裁管礼庆创办的母婴知识分享社区平台Alwayslove于上月获得700万天使轮融资。 Alwayslove是一个母婴知识分享社区平台,采用UGC模式,...

ThinkSNS账号
36分钟前
1
0
Android 自定义构建类型 BuildType

最近接触到自定义构建类型 BuildType,发现这一块有些地方稍不注意的话会被绕进去浪费点时间,既然我这边已经花费时间了,如果正好你也需要接触到 BuildType,也许接下来分享的 tips 可能会帮...

猴亮屏
37分钟前
1
0
美团点评基于 Flink 的实时数仓建设实践

引言 近些年,企业对数据服务实时化服务的需求日益增多。本文整理了常见实时数据组件的性能特点和适用场景,介绍了美团如何通过 Flink 引擎构建实时数据仓库,从而提供高效、稳健的实时数据服...

美团技术团队
40分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部