数组,切片

数组

创建方式

提起切片,我们必须要先了解数组,数组的类型名是[n]elementType,n代表数组长度,elementType是数组元素类型。数组的定义方式如下:

// var elementName [n]elementType
var array [2]int    // [0 0];声明一个含有两个int类型的数组,因为未初始化,所以元素都为默认值0
array2:=[...]int{1,2,3} // 可以不指定数组长度,但必须指定"...",然后编译器自动根据字面量初始化列表推导数组长度。

数组常见创建方式

arr1:=[3]int{1,2,3} // [1 2 3]
arr2:=[...]int{1,2,3}   // [1 2 3]
arr3:=[3]int{1:1,2:2} // [0 1 2]
arr4:=[...]int{3:3,5:5} // [0 0 0 3 0 5]

数组特点

  • 长度固定,不可以超过长度追加元素

  • 数组是值类型,数组赋值或者作为函数参数都是值拷贝

    a:=[2]int{1,2}
    b:=a
    b[0]=999
    
    fmt.Println("a:",a)   // a: [1 2]
    fmt.Println("b:",b)   // b: [999 2]
    
  • 数组长度是数组类型的组成部分,[1]int和[2]int表示不同的类型

  • 可以根据数组创建切片,切片引用的是原数组,切片的改变会引起原数组的改变

    a:=[2]int{1,2}
    b:=a[:]
    b[0]=999
    fmt.Println("a:",a)   // a: [999 2]
    fmt.Println("b:",b)   // b: [999 2]
    

遍历数组

a:=[2]int{1,2}
// idx是索引,v是值
for idx,v:=range a{
   fmt.Println(idx,v)
}
for i:=0;i<len(a);i++{
   fmt.Println(i,a[i])
}

切片

因为数组的长度固定,而且是值拷贝,所以限制了数组的使用场景。此时切片(slice)应运而生,它是一种变长数组,它是一种引用类型(map、channel也是引用类型)。

slice的底层如下:

type slice struct {
    array unsafe.Pointer    // 指向底层数组的指针
    len   int                           // 切片的元素数量
    cap   int                           // 底层数组容量
}

创建方式

  • 由数组创建:array[s:e],array是数组名,s是起始索引,e是终止索引,array[s:e]包括s索引下的数据,但不包括e索引下的数据(相当于左闭右开[s,e)),也就是说第一个元素的索引是s,最后一个元素的索引是e-1,该切片的长度为e-s

    var array = [3]int{1,2,3}
    a1:=array[:]  // [1 2 3],如果不指定起始或者终止索引的话,起始索引默认为0,终止索引默认为len(array)
    a2:=array[1:2]    // [2]
    

    同样方式也可以通过切片创造切片

    s:=[]int{1,2,3}
    b:=s[1:2] //[2]
    
  • 由内置函数make创建

    通过make创建的切片的元素初始值都被默认初始化为元素类型的零值

    arr1:=make([]int,5) // [0 0 0 0 0] len=5,cap=5,所有元素都被默认初始化为0
    
    arr2:=make([]int,5,10) // [0 0 0 0 0] len=5,cap=10,所有元素都被默认初始化为0
    
  • 由字面量初始化

    arr:=[]int{1,2,3} // [1 2 3] len=3 cap=3
    

常见操作

s:=[]int{1,2}
fmt.Println(len(s)) // len=2,返回切片长度

fmt.Println(cap(s)) // cap=2,返回切片容量

s=append(s,3)               // 向s追加元素;切片元素:[1,2,3];len=3,cap=4,切片长度超过原来的容量,自动扩容,容量扩大为原来的两倍

s1:=[]int{4,5}
s=append(s,s1...)   // 向s追加切片
fmt.Println(s)  // [1 2 3 4 5]

s=append(s,7,8) // 向切片追加多个元素
fmt.Println(s)  // [1 2 3 4 5 7 8]

c:=[]int{1,2,3}
b:=make([]int,2)    // [0 0]
copy(b,c)   //只会复制长度较小的,第一个参数是目的切片,第二个参数是源切片
fmt.Println(b) // [1 2]

c1:=[]int{1,2,3}
b1:=make([]int,5)   // [0 0 0 0 0]
copy(b1,c1) 
fmt.Println(b1) // [1 2 3 0 0]

Tips:

  1. 当切片的长度超过容量cap的时候,切片会进行扩容,cap直接扩大为原来的2倍。

  2. append函数定义如下,第一个参数表示向哪个切片追加元素,后面的是可变参数,可以添加多个参数,也可以添加一个切片,当第二个参数是切片时,需要在切片后面添加三个点来表示引用切片中所有元素"..."

    注意:可变参数可以是单个元素,也可以是一个切片…,但不能两者同时出现。

func append(slice []Type, elems ...Type) []Type
    s:=[]int{1,2}
            
    s1:=[]int{4,5}
    
    // s=append(s,1,s1...) // 报错

    // s=append(s,s1...,1)  // 报错

字符串和切片相互转换

str:="深夜幽魂"
a:=[]byte(str)  // [230 183 177 229 164 156 229 185 189 233 173 130]
b:=[]rune(str)  // [28145 22812 24189 39746]

c:=[]byte{230,183,177,229,164,156,229,185,189,233,173,130}
fmt.Println(string(c))  // 深夜幽魂
d:=[]rune{28145,22812,24189,39746}
fmt.Println(string(d))  // 深夜幽魂

Tips:字符串转切片的时候需要注意,尤其当字符串内容很大的时候,因为每一次都要复制内容

刁钻难点

  1. 通过var b []int创建切片,该切片底层array指针不指向任何数组(也就是array的值为nil),len、cap都是0;但通过a:=[]int{}这种方式创建的切片,虽然len、cap也都是0,但是底层array是开辟了空间的,不为nil
a:=[]int{}
var b []int
fmt.Println(a,a==nil,len(a),cap(a)) // [] false 0 0
fmt.Println(b,b==nil,len(b),cap(b)) // [] true 0 0
  1. 通过array[s:e]创建切片的时候,其实还可以这样array[s:e:c],c的最大值是数组的长度或者切片的容量的最大值。e-s是该切片的长度,c-s是该切片的容量

    a:=[]int{1,2}
    b:=a[0:1:2]
    fmt.Println(b,len(b),cap(b)) // [1] 1 2
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容