golang 数组和切片

栏目: Go · 发布时间: 5年前

内容简介:数组的长度在声明它的时候就必须给定,并且在之后不会再改变。可以说,数组的长度是其类型的一部分。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 函数对其追加元素的时候就不会引起扩容。这只会使紧邻切片窗口右边的(底层数组中的)元素被替换成新的元素。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Beginning ARKit for iPhone and iPad

Beginning ARKit for iPhone and iPad

Wallace Wang / Apress / 2018-11-5 / USD 39.99

Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具