golang 数组和切片

数组类型的值(以下简称数组)的长度是固定的,而切片类型的值(以下简称切片)是可变长的。

 数组的长度在声明它的时候就必须给定,并且在之后不会再改变。可以说,数组的长度是其类型的一部分。

golang数组的四种声明方法
第一种

// var <数组名称> [<数组长度>]<数组元素>
var arra [2]int
arr[0]=1
arrp1[=2

第二种

// var <数组名称> = [<数组长度>]<数组元素>{元素1,元素2,...}
var arr = [2]int{1,2}
//或者
arr := [2]int{1,2}

第三种

// var <数组名称>[<数组长度>]<数组元素>=[...]<元素类型>{元素1,元素2,...}
var arr =[...]int{1,2}
//或者
arr :=[...]int {1,2}

第四种

// var <数组名称>[<数组长度>]<数组元素>=[...]<元素类型>{索引1:元素1,索引2:元素2,...}
var arr = [...]int{1:1,0:2}
// 或者
arr := [...]int{1:1,0:2}

 切片的长度可以自动地随着其中元素数量的增长而增长,但不会随着元素数量的减少而减少。

golang切片的3种声明方法
①定义一个切片,然后让切片去引用一个已经创建好的数组

var arr [5]int = [...]int{1,2,3,4,5}
var slice = arr [1:3]

②通过make来创建切片

// var 切片名 []type = make([], len, [cap]);参数说明:type是数据类型、len是大小、cap是切片容量(容量必须>=长度)

通过make方式创建切片可以指定切片大小和容量
如果没有给切片的各个元素赋值,那么就会使用默认值(int、float=>0, strint=>"", bool=>false)
荣国make方式创建的切片对应的数组是由make底层维护,对外不可见,也就是只能通过slice访问各个元素

 var slice []float64 = make([]float64, 5, 10)

③定义一个切片,直接就指定具体数组,使用原理类似于make的方式

 var slice []string = []string{"zhangsan", "lisi", "wangwu"}

 我们其实可以把切片看做是对数组的一层简单的封装,因为在每个切片的底层数据结构中,一定会包含一个数组。后者可以被叫做前者的底层数组,而前者也可以被看作是对后者的某个连续片段的引用。

 也正因为如此,Go语言的切片类型属于引用类型,同属引用类型的还有后面会讲到的字典类型、通道类型、函数类型等;而Go语言的数组类型则属于值类型,同属值类型的有基础数据类型以及结构体类型。

 注意,Go语言里不存在像java等编程语言中那种令人困惑的“传值或传引用”问题。在Go语言中,我们判断所谓的“传值”或者“传引用”只要看北传递的值的类型就好了。如果传递的值是引用类型的,那么就是“传引用”。如果传递的值是值类型的,那么就是“传值”。从传递成本的角度讲,引用类型的值往往要比值类型的值低很多。

怎样正确估算切片的长度和容量?

package main
import "fmt"
func main(){
    // 示例1
    s1 :=make([]int,5)
    fmt.println("The length of s1: %d\n",len(s1))
    fmt.println("The capacity of s1:%d\n",cap(s1))
    fmt.println("The value of s1: %d\n",s1)
    s2 := make([]int,5,8)
    fmt.println("The length of s2:%d\n",len(s2))
    fmt.println("The capacity of s2:%d\n",cap(s2))
    fmt.println("The value of s2: %d\n",s2)
}

首先,内建函数make声明了一个[]int类型的变量s1。我传给make函数的第二个参数是5,从而指明了该切片的长度。再用几乎相同的方式声明了切片s2,只不过多传了一个参数8以指明该切片的容量。

切片s1和s2的容量分别是5和8。

原因:当我们用make函数初始化切片时,如果不指名其容量,那么它就会和长度一致。如果在初始化时指明了容量,那么切片的实际容量也就是它了。这也正是s2的容量是8的原因。


s3: = []int{1,2,3,4,5,6,7,8}
s4  := s3[3:6]

s4的长度为3,容量为5

原因:由于s4是通过在s3上施加切片操作得来的,所以s3的底层数组就是s4的底层数组。又因为,在底层数组不变的情况下,切片代表的窗口可以向右扩展,直至其底层数组的末尾。所以,s4的容量就是其底层数组的长度8减去上述切片表达式中的那个起始索引3,即5。

注意:切片带边的窗口是无法向左扩展的也就是说,我们永远无法透过s4看到s4左边的那3个元素。
最后,随便提一下把切片的窗口向右扩展到最大的方法。对于s4来说,切片表达式s4[0:cap(s4)]就可以做到。该表达式的结果(即一个新的切片)会是[]int{4,5,6,7,8},其长度和容量都是5。

知识扩展

1.切片如何扩容?

一旦一个切片无法容纳更多的元素,Go于洋就会想办法扩容。但它并不会改变原来的切片,而是生成一个容量更大的切片,然后将把原有元素和新元素一并拷贝到新切片中。
在一般的情况下,你可以简单地认为新切片的容量将是原切片容量的2倍。
但是,当原切片的长度大于或等于1024时,Go语言会将以原容量的1.25倍作为新容量的基准。
新容量基准会被调整(不断与1.25相乘),直到结果不小于原长度与要追加的元素数量之和(以下简称新长度)。最终,新容量往往会比新长度要大一些,当然,相等也是可能得。

2.切片的底层数组什么时候会被替换?
确切地说,一个切片的底层数组永远不会被替换。虽然在扩容的时候Go语言一定会生成新的底层数组,但是它同时生成了新的切片。它是把新的切片作为了新底层数组的窗口,而没有对原切片及其底层数组做任何改动。

在无须扩容时,append函数返回的是指向原底层数组的切片,而在需要扩容时,append函数返回的是指向新底层数组的新切片。

所以,严格来说,“扩容”这个词用来这里虽然形象但并不适合。

顺便说一下,只要新长度不会超过切片的原容量,那么使用append函数对其追加元素的时候就不会引起扩容。这只会使紧邻切片窗口右边的(底层数组中的)元素被替换成新的元素。

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

推荐阅读更多精彩内容

  • 数组 数组在go语言中为值类型 数组之间可以用= =或!=比较,但是数组长度也是类型的一部分,因此不同长度的数组为...
    Link_Biao阅读 7,429评论 0 0
  • 线性结构是计算机最常用的数据结构之一。无论是数组(arrary)还是链表(list),在编程中不可或缺。golan...
    _二少爷阅读 6,599评论 5 13
  • 数组Go语言中的数组是定长的同一类型数据的集合,数组索引是从0开始的。数组有以下几种创建方式 以下是一些特殊数组 ...
    小杰的快乐时光阅读 1,681评论 0 0
  • 一拖二的日子让我这个平时不做饭的妈妈倒没觉得在生活中有多大考验,我做得简单也好,出去吃也好,孩子们都很配合。大宝从...
    喻青阅读 670评论 0 0
  • 人生有三样东西一去不返:时间、言辞和机会;三样东西足以毁掉一个人:怒火、骄傲和不宽恕;三样东西永不应放弃:平和、诚...
    xcy无名阅读 309评论 0 0