文档章节

数组(Array)和切片(Slice)

烈冰
 烈冰
发布于 2012/11/06 20:25
字数 954
阅读 4.4K
收藏 1

精选30+云产品,助力企业轻松上云!>>>

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

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使用和内幕

上一篇: Map
下一篇: Go的基本类型
烈冰

烈冰

粉丝 54
博文 39
码字总数 8933
作品 1
佛山
架构师
私信 提问
加载中
此博客有 3 条评论,请先登录后再查看。
Go slice实现原理剖析

前言 Slice又称动态数组,依托数组实现,可以方便的进行扩容、传递等,实际使用中比数组更灵活。 正因为灵活,如果不了解其内部实现机制,有可能遭遇莫名的异常现象。Slice的实现原理很简单,...

恋恋美食
2018/10/30
1.4K
8
Go基础编程:复合类型—切片slice

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

tennysonsky
2017/12/13
0
0
详解go语言的array和slice

一般go的slice动态扩容 小于1024是2倍 大于1024是1.25倍 本篇会详细讲解go语言中的array和slice,和平时开发中使用时需要注意的地方,以免入坑。 Go语言中array是一组定长的同类型数据集合,...

mickelfeng
2018/03/21
0
0
Go语言的array,slice及map

array类型 var myarray [10]int //定义数组变量,此时myarray所有元素被初始化为0 myarray=[10]int{0,1,2,3,4,5,6,7} //初始化,此时必须为[10]int,之后myarray[8]=myarray[9]=0 也可以将以...

acmfly
2012/11/16
207
1
golang 小知识-持续更新中

Golang 中的指针 - Pointer Go 的原生数据类型可以分为基本类型和高级类型,基本类型主要包含 string, bool, int 及 float 系列,高级类型包含 struct,array/slice,map,chan, func 。 ...

osc_ht9rr956
2018/05/19
2
0

没有更多内容

加载失败,请刷新页面

加载更多

唐山5.1级地震 百度人工智能技术帮上忙:成都减灾所提前30秒让北京、天津市民收到预警

本文作者:y****n 7月12日6时38分在河北唐山市古冶区发生5.1级地震,成都高新减灾研究所与应急管理部门联合建成的大陆地震预警网成功预警该地震,给唐山市提前3秒预警,给天津市提前33秒预警...

百度开发者中心
昨天
30
0
如何使用PHP发送POST请求? - How do I send a POST request with PHP?

问题: Actually I want to read the contents that come after the search query, when it is done. 实际上,我想阅读搜索查询之后的内容,完成之后。 The problem is that the URL only a......

javail
今天
14
0
如何从Java读取文件夹中的所有文件? - How to read all files in a folder from Java?

问题: 如何通过Java读取文件夹中的所有文件? 解决方案: 参考一: https://stackoom.com/question/7jt2/如何从Java读取文件夹中的所有文件 参考二: https://oldbug.net/q/7jt2/How-to-rea...

富含淀粉
今天
25
0
主机“ xxx.xx.xxx.xxx”不允许连接到该MySQL服务器

问题: This should be dead simple, but I cannot get it to work for the life of me. 这本来应该很简单,但是我无法让它在我的一生中发挥作用。 I'm just trying to connect remotely to......

技术盛宴
今天
18
0
OSChina 周二乱弹 —— 附近居民接连失踪,你们有什么头绪吗

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《伤离别(原版)》- 黄霑 手机党少年们想听歌,请使劲儿戳(这里) @巴拉迪维 :睡...

小小编辑
今天
48
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部