Golang笔记(一):数组与切片

数组

  • 创建方式:
    以创建 int 类型数组为例
var array1 [3]int // 元素会被自动初始化为0值 => {0, 0, 0}
array2 := [3]int{1} // 位提供初始化的元素被初始化为零值 => {1, 0, 0}
arary3 := [3]int{1, 2: 3} // 指定索引2的元素初始化值为3 => {1, 0, 3}
array4 := [...]int{1, 2, 3} // 不直接指定长度,编译器会根据元素个数给定长度 => {1, 2, 3}
array5 := [...]int{1, 2: 3} // 指定索引 2 的元素初始化值为3,会影响该数组长度 => {1, 0, 3}
  • 复合型数组:
    复合型数组可以省略类型化标签
type Student struct {
    name string 
    age    int 
}
studentArray := [...]Student {
    {"studentA", 18}, // 省略结构体标签
    {"studentB", 20}
}
  • 多维数组
    注意: 1. 多维数组仅允许第一维使用 ...
    2. 内置函数 len 和 cap 都只返回第一维数组的长度

  • 比较
    如果元素支持 == 比较,那么该数组也支持此操作

切片

切片本身是个只读对象,其工作机制累死数组指针的一种包装。可以基于数组或数组指针创建切片,以开始和结束索引位置确定引用的数组片段。不支持反向索引,世纪范围是一个右半开区间。属性 cap 表示切片所引用数组片段的真是长度,len 用于限定可读的写元素数量。另外,数组必须 addressable,否则会引发错误。
与数组区别:

  1. 切片创建不需要提前声明长度;而数组需要声明,操作数组索引大于该数组长度,会产生越界的异常。
  2. 切片可以通过 make([]int, 3, 5) 方式创建,第一个参数为类型,第二个参数为长度(len),第三个参数为容量(cap)
  3. 切片的长度(len)和 容量(cap)两个属性不一定相等;而数组的两个属性一定相等。切片底层是数组的一部分或者全部, cap 值为从切片引用该底层数组开头部分到该底层数组结尾的长度,而 len 值为该切片引用的底层数组部分的长度。
  4. 切片是引用类型,而数组是值类型。说白了就是切片传递的是引用,只要对任意一个地方修改原切片值也会改变;而数组是值类型,每次传递相当于重新分配内存创建了一个新的数组,各个之间相互独立不影响。
  5. 切片不支持比较操作,即使元素类型支持也不行,仅可以判断您是否是 nil
  • 创建方式:
sliceA := make([]int, 2, 5)  // len = 2 cap = 5 => {0, 0}
sliceB := make([]int2, 2]) // len = 2 cap = 5 => {0, 0}
sliceC := []int{1, 2, 3, 5: 30} // len = 6 cap = 6 => {1, 2, 3, 0, 0, 30}

注意:
下面两种声明方式,前者只是定义了一个 []int 类型变量,并未执行初始化操作;而后者则用初始化表达式完成了全部创建过程。

var sliceA []int // sliceA == nil true
sliceB := []int{} // sliceB == nil false
  • 优势
  1. 很显然,切片只是很小的结构体对象,用来代替数组传参可以避免复制开销
  2. make 函数允许在运行期动态制定数组长度,绕开了数组类型必须使用编译期常量的限制。

然而,并非所有时候都适合使用切片代替数组,因为切片底层数组可能会在堆上分配内存, 而且小数组在栈上拷贝的消耗也未必就比 make 代价大。

  • append
    向切片尾部添加数据(slice[len]),返回新的切片对象(如果超过 cap 限制,则为心切片独享重新分配内存和数组,所以要返回新的切片对象)。向 nil 切片追加数据时,会为其分配底层数组内存。
slice := make([]int, 0, 5) // {}
sliceA := append(slice, 10) // {10,}
sliceB := append(sliceB, 20, 30) // {10, 20, 30}
sliceC := append(sliceB, 100, 200, 300) // {10, 20, 30, 100, 200, 300} => 超出 cap, 新切片的地址已经变了

注意:

  • 是超出切片 cap 限制,而非超出底层数组长度限制,因为 cap 可小于数组长度。
  • 新分配数组长度是原 cap 的 2 倍,而非原数组的 2 倍(并非总是 2 倍,对于较大的切片,会尝试扩容 1/4,以节约内存)
  • 因为存在重新分配底层数组的缘故,建议预留足够空间,避免多次分配复制的内存开销
  • copy
    在两个切片对象间复制数据,允许指向同一底层数组,允许目标区间重叠。最终所复制长度以较短的切片长度(len)为准。
slice := []int{1, 2, 3, 4, 5}
sliceA := slice[:] // {1, 2, 3, 4, 5}
sliceB := slice[1:3] // {2, 3}
n:= copy(sliceA, sliceB) //sliceA:{2 3 3 4 5} sliceB:{3, 3} n: 2

注意

  • 如果切片长时间引用大数组中很小的片段,建议新建独立切片,复制出所需数据,以便于原数组内存被及时回收。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容