内容简介:数组的长度在声明它的时候就必须给定,并且在之后不会再改变。可以说,数组的长度是其类型的一部分。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 函数对其追加元素的时候就不会引起扩容。这只会使紧邻切片窗口右边的(底层数组中的)元素被替换成新的元素。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入应用C++11
祁宇 / 机械工业出版社 / 2015-5 / 79
在StackOverflow的最近一次世界性调查中,C++11在所有的编程语言中排名第二, C++11受到程序员的追捧是毫不意外的,因为它就像C++之父Bjarne Stroustrup说的:它看起来就像一门新的语言。C++11新增加了相当多的现代编程语言的特性,相比C++98/03,它在生产力、安全性、性能和易用性上都有了大幅提高。比如auto和decltype让我们从书写冗长的类型和繁琐的类型......一起来看看 《深入应用C++11》 这本书的介绍吧!