Go语言-数组和切片
1 数组的定义
定义数组常规格式是:var 数组名 [元素数量] 元素类型 = {各元素}
,实际使用中,可以有很多灵活的操作。如有下面几种定义数组的方式:
- 只声明不赋值
- 使用语法糖
:=
以省略var
关键字,此时需要对数组进行赋值 - 使用
...
在定义的时候不指定个数,由程序通过所赋值的结果自己计算。定义时候需要赋值!
下面是几种定义方式的实现案例:
package main
import "fmt"
func main() {
var arr1 [5] int
arr2 := [3]int{1,2,3}
arr3 := [...]int{3,2,32,465,64,3}
// 二维数组的定义分别代表行列数
var grid [4][5]int
fmt.Println(arr1,arr2,arr3)
fmt.Println(grid)
}
程序的输出结果是:
说明
数组定义需要在元素类型前面加上[...]
或者[数字]
,需要注意的是,在使用的时候,如果方括号中间不带任何东西,那么他代表的是一个数组的切片,就不是指这个数组了。所以,需要在定义一个含有数组参数的函数时,需要带上方括号内的东西。
[10]int和[20]int是不同的类型
2 数组的遍历
数组的遍历可以采用常规的for - len的形式,不过建议还是使用Go语言中提供的range
方法,该关键字能够直接获取到数组的下标和对应的元素值。例如:
for i, v := range arr3 {
fmt.Println(i, "->", v)
}
程序对应的输出结果是:
当然,可以直接获取下标,另外通过
arr3[i]
的方式获取元素。
说明
需要注意的是:数组也是值传递的。在函数内部修改一个数组,如果不是从地址层面进行了修改。那么脱离了函数之后,不会影响老数组。也就是说,func f(arr [10]int)
会拷贝数组。
Go语言中一般不直接使用数组,而是使用切片。下一节着重介绍切片的概念。
3 切片:slice
所谓切片是指取数组的一小段数组元组子集。slice是对数组的一个view
(视图)。
首先定义一个数组arr:=[...]int{0,1,2,3,4,5,6,7}
,取一个切片s:=arr[2:6]
,s就是一个切片。s的取值是[2,6)
,因此,s这个切片的取值是:[2,3,4,5]
同样的,可以省略切片的
start
或者end
,或者 全部省略代表全部数组元素。
以切片为参数的时候,方括号内部不用加数字。
更新某个数组的切片,是会更新数组内容的。
package main
import "fmt"
func printArray(arr []int){
arr[0]=100
for i,v :=range arr{
fmt.Println(i,"->",v)
}
}
func main() {
var arr1 = [5]int {1,2,3,4,5}
slice:=arr1[:]
fmt.Println("更新之前...")
fmt.Println(arr1)
fmt.Println("======================")
printArray(slice)
fmt.Println("更新之后...")
fmt.Println(arr1)
}
上述程序的输出结果是:
也就是说,切片作为参数实现了数组指针作为参数的作用。但是省却了很多的麻烦写法。
3.1 Slice的上下限和容量
切片中的概念slice中有三个概念:指针,长度和容量
参照上图可知:
- ptr:一个切片的起始内存地址
- len:一个切片的长度:也就是这个切片中的当前元素个数
- cap:一个切片的扩展后的总容量
切片是基于数组的视图,所以,有一定的可见域。如果切片的下界超过了数组的最终容量,只会显示到数组的最后元素完成后就结束。
1. slice可以向后扩展,不可以向前扩展
- s[i] 不可以超越len(s),向后扩展不可以超越底层数组cap(s)。
3.2 向slice中添加元素
- 添加元素的时候如果超越cap,系统会重新分配更大的底层数组
- 由于值传递的关系,必须接收append的返回值
- s = append(s,val)
一种创建切片的方法: 使用系统内置的make
方法。
// 创建一个长度为10的切片,默认值都是元素0
s := make([]int, 10)
// 创建一个长度为10, 容量为32的切片,默认值都是元素0
s := make([]int, 10, 32)