go的学习记录(二)--- 数组与数组切片

haust_wang · · 2801 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在go语言的学习中,少不了接触的就是数组和数组切片,并且这两者的使用也是非常频繁的。因此如果不能进行很好的理解,或许很容易犯错。那么在go中,数组和数组切片都有什么特点,又是怎么声明赋值的,如何使用的呢,下面我就自己的理解总结一下,个人总结可能不全或者有错,望指点。

一、数组和数组切片的特点

数组是什么就不用多说了,作为开发者,这是经常会用到的东西,相信大家都有自己的理解。现在先总结一下数组的特点

1. 数组的长度在定义之后就不可被更改

2. 数组声明时的长度必须为常量或常量表达式,即可以在编译器确定长度,分配内存

3. 数组的下标从0开始,最后一个元素的下标为(长度-1),即在go中可以写为 len(arr)-1

4. go语言的数组是值类型,在作为参数传递时会做数组的复制操作。因此作为参数传递的时候,被修改的内容不影响原来的数组内容,只影响传入函数内的副本

数组切片:是go提供的一种新型的数据类型,它在go语言中的使用有C或C++中的指针的功效。但由于它又不同于指针,所以没有C或C++中语言的指针操作方式。数组切片的底层是通过数组实现,很容易联想到C++的vector。

1. 与数组不同,数组切片的长度是可变的,即可以动态分配内存空间。但在每次新分配空间的时候,即会对当前的元素进行一次复制

2. go语言提供了内置函数copy用于将内容从一个数组切片复制到另外一个数组切片,但如果两个数组切片的长度不一样,则会按照较小的数组切片的个数进行复制。

3. 数组切片与数组一样,其下标从0开始,最后一个元素的下标为(长度-1),即在go中可以写为 len(arr)-1

4. go语言提供cap()内置函数可以获得数组切片分配的空间大小,该值的返回可能与len()返回的大小不同

5. 数组切片提供创建时指定长度和预留存储空间。在知道数组切片最终能用到的长度时,可以避免切片扩容所引发的内存的申请释放与复制。

6. 数组切片作为参数传递时,不会出现内存的复制操作,在函数中如果修改了传入的切片的参数,可以直接修改原数组切片的内容。

二、数组与数组切片的使用

(一) 声明与创建

数组的定义初始化比较简单,如下:

1. var arr [10]int //声明长度为10,类型为int的数组。也可以声明多维数组,如:var twod [10][100]int。也可以定义复杂类型数组,如:var st_arr [100]struct {x, y int }

arr[1] = 1 //根据索引赋值

2. arr := [5]int{1,2,3,4,5} //声明并初始化数组

3. var arr [5]int = [5]int{1,2,3,4,5} //定义并初始化数组

数组切片的定义与初始化,如下:

1. 基于数组创建

arr := [10]int{1,2,3,4,5}

var slc1 []int = arr[:] //基于数组全部元素创建切片

var slc2 []int = arr[:5] //基于前五个元素创建切片

var slc3 []int = arr[5:] //基于从第五个元素创建切片

var slc4 []int = arr[2:8] //基于从第二个到第八个元素创建切片

以上几种创建切片的方式,都是基于一种创建规则:基于arr[first:last]这种方式创建数组切片

2. 直接创建

slice1 := make([]int, 5) //创建一个初始元素个数为5的数组切片,元素初始值为0

slice2 := make([]int, 5, 10) //创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间

slice3 := []int{1, 2, 3, 4, 5} //直接创建并初始化包含5个元素的数组切片

3. 基于数组切片创建数组切片

基于数组切片创建数组切片和基于数组创建切片基本相同。但新创建的切片元素个数可以超过旧切片所包含的元素个数,该操作要求新创建切片的元素个数不超过旧切片的容量个数。如:

slice1 :=  make([]int, 5, 10)

slice2 := slice1[:6]


(二)遍历元素

在go中,无论是数组还是数组切片,都提供了两种相同的遍历方式:

1. 使用传统的for遍历:

for i := 0; i < len(arr); i++ {

fmt.Println("arr[",i,"] is ", arr[i])

}

2. 使用range关键字:

for i, v := range arr {

fmt.Println("arr[",i,"] is ", v)

}


(三) 长度获取

对于数组和数组切片,go语言提供了内置函数len(),使用方式len(arr),返回当前数组或数组切片的长度。对于数组切片,go语言提供内置函数cap()获取数组切片的容量

(四)添加元素

对于数组定长,因此没有添加元素的功能。但数组切片因为动态内存的问题,可以提供追加元素。在go语言中提供了内置函数append作为数组切片的元素追加。有以下两种使用方式:

1. 直接追加元素:

slice1 := []int{1,2,3,4}

slice1 = append(slice1, 5, 6, 7) // append的第一个参数是基于的数组切片。第二个参数是不定参数,可以追加多个元素

2. 数组切片追加数组切片:

slice1 := []int{1,2,3,4}

slice2 := []int{5,6,7,8}

slice1 := append(slice1, slice2…) //这里要特别注意的是:在第二个数组切片后面需要加三个点,否则会编译错误。主要原因是append第二个参数起都是待追加的元素,而加上三个点的作用就是把slice2的元素按照元素内容列表传入,而不是以切片作为参数传入。


(五)作为参数传递

1. 数组作为参数

func sort(arr [10] int) {

...

}

该函数的调用要如下:

arr1 := [10]int{8,6,5,4,7,3,9,1,2,10}

arr2 := [5]int{4,2,3,5,1}

slice1 := []int{8,6,5,4,7,3,9,1,2,10}

sort(arr) //编译正常,但由于数组穿参属于值传参,在传参的时候会进行数组复制,因此只修改了sort内部的arr的值,未修改arr1的实际元素值内容

sort(arr2) //编译错误,对于go而言,[10]int 和[5]int 是两种不同的数据类型

sort(&arr) //编译错误,对于C或C++而言,函数参数定义为int arr[10]这种实际是定义了数组的指针传入。但go语言中,数组指针和数组是两种完全不同的类型

sort(slice1) //编译错误,同样是因为类型不同

2. 数组切片作为参数

func sort(arr []int) {

...

}

arr1 := [10]int{8,6,5,4,7,3,9,1,2,10}

slice1 := []int{8,6,5,4,7,3,9,1,2,10}

sort(arr) //编译错误,类型不同

sort(slice1) //编译正确,且在sort中对于slice的修改会直接修改到原始的slice。


有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:haust_wang

查看原文:go的学习记录(二)--- 数组与数组切片

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2801 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传