Go 语⾔提供了数组类型的数据结构。数组是具有相同唯⼀类型的⼀组已编号且⻓度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者⾃定义类型。数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第⼀个元素索引为 0,第⼆个索引为 1,以此类推。
示例:定义一个数组:
- package main
-
- import "fmt"
-
- func main() {
- var arr1 [5] int
- fmt.Println("vim-go")
- fmt.Println(arr1)
- }
执行结果
在go语言里面如果定义一个变量没有赋值会自动生成一个初始值,数组的初始值为0
- [root@localhost src]# go run example7.go
- vim-go
- [0 0 0 0 0]
两种定义变量的区别
用 var 定义变量可以不用赋初始值
使用 a := 的方法定义必须有初始值
示例:定义数组,给数组赋值
- package main
-
- import "fmt"
-
- func main() {
- var arr1 [5] int
- fmt.Println("vim-go")
- fmt.Println(arr1)
- arr2 := [5]int{0,1,2,3,4}
- fmt.Println(arr2)
- arr2[0]=100
- arr2[1]=555
- arr2[4]=99
- fmt.Println(arr2)
- }
示例:使用for循环获取数组的值
- package main
-
- import "fmt"
-
- func main() {
- var arr1 [5] int
- fmt.Println("vim-go")
- for i:=0;i<len(arr1);i++ {
- arr1[i] = i
- }
- fmt.Println(arr1)
- }
执行结果
- [root@localhost src]# go run for.go
- vim-go
- [0 1 2 3 4]
数组的遍历
示例:使用range遍历数组
- package main
-
- import "fmt"
-
- func main() {
- arr2 := [5]int{0,1,2,3,4}
- arr2[0]=100
- arr2[1]=555
- arr2[4]=99
- fmt.Println(arr2)
-
- // 下标,值
- for i,item := range arr2{
- fmt.Println(i,item)
- }
- }
- [root@localhost src]# go run example7.go
- [100 555 2 3 99]
- 0 100
- 1 555
- 2 2
- 3 3
- 4 99
示例:遍历但是只取 item值
可以使用下划线 _ 来定义一个不输出的变量
- package main
-
- import "fmt"
-
- func main() {
- //var arr1 [5] int
- //fmt.Println("vim-go")
- //fmt.Println(arr1)
- arr2 := [5]int{0,1,2,3,4}
- //fmt.Println(arr2)
- arr2[0]=100
- arr2[1]=555
- arr2[4]=99
- fmt.Println(arr2)
-
- // 下标,值
- for i,item := range arr2{
- fmt.Println(i,item)
- }
- // 如何遍历但是只取item?
- for _,item := range arr2{
- fmt.Println(item)
- }
- }
- [root@localhost src]# go run example7.go
- [100 555 2 3 99]
- 0 100
- 1 555
- 2 2
- 3 3
- 4 99
- 100
- 555
- 2
- 3
- 99
定义二维数组
- var arr3 [2][3] int
- arr3[0][1] = 100
- fmt.Println(arr3)
[[0 100 0] [0 0 0]]
什么是切片
Go 语⾔切⽚是对数组的抽象。Go 数组的⻓度不可改变,在特定场景中这样的集合就不太适⽤,Go 中提供了⼀种灵活,功能强悍的内置类型切⽚("动态数组"),与数组相⽐切⽚的 ⻓度是不固定 的,可以追加元素,在追加时可能使切⽚的容量增⼤ 。
示例:切片的定义
- package main
-
- import "fmt"
-
- func main() {
- arr2 :=[5]int{100,500,2,3,99}
- var slice1 []int
- fmt.Println(slice1)
- var slice2 []int = make([]int,5)
- fmt.Println(slice2)
- slice3 := make([]int, 5)
- fmt.Println(slice3)
-
- // 通过对数组进行切片,初始化数据
- slice4 := arr2[0:2]
- fmt.Println(slice4)
- slice5 := slice4
- fmt.Println(slice5)
- slice6 := arr2
- fmt.Println(slice6)
- }
- [root@localhost src]# go run slice.go
- []
- [0 0 0 0 0]
- [0 0 0 0 0]
- [100 500]
- [100 500]
- [100 500 2 3 99]
切⽚是可索引的,并且可以由 len() ⽅法获取⻓度。切⽚提供了计算容量的⽅法 cap() 可以测量切⽚最⻓可以达到多少。
- import "fmt"
-
- func main() {
- arr2 :=[5]int{100,500,2,3,99}
- var slice1 []int
- fmt.Println(slice1)
- var slice2 []int = make([]int,5)
- fmt.Println(slice2)
- slice3 := make([]int, 5)
- fmt.Println(slice3)
-
- // 通过对数组进行切片,初始化数据
- slice4 := arr2[0:2]
- fmt.Println(slice4)
- slice5 := slice4
- fmt.Println(slice5)
- slice6 := arr2
- fmt.Println(slice6)
- fmt.Println("**************************")
- //len cap
- fmt.Println(len(slice3),cap(slice3))
- fmt.Println(len(arr2),cap(arr2))
-
-
- }
- [root@localhost src]# go run slice.go
- []
- [0 0 0 0 0]
- [0 0 0 0 0]
- [100 500]
- [100 500]
- [100 500 2 3 99]
- **************************
- 5 5
- 5 5
如果想增加切⽚的容量,我们必须创建⼀个新的更⼤的切⽚并把原分⽚的内容都拷⻉过来。下⾯的代码描述了从拷⻉切⽚的 copy ⽅法和向切⽚追加新元素的 append ⽅法。
示例:使用append方法添加新元素,slice4里面原本只有两个元素,新增两个数600,700
- package main
-
- import "fmt"
-
- func main() {
- arr2 :=[5]int{100,500,2,3,99}
- var slice1 []int
- fmt.Println(slice1)
- var slice2 []int = make([]int,5)
- fmt.Println(slice2)
- slice3 := make([]int, 5)
- fmt.Println(slice3)
-
- // 通过对数组进行切片,初始化数据
- slice4 := arr2[0:2]
- fmt.Println(slice4)
- slice5 := slice4
- fmt.Println(slice5)
- slice6 := arr2
- fmt.Println(slice6)
- fmt.Println("**************************")
- //len cap
- fmt.Println(len(slice3),cap(slice3))
- fmt.Println(len(arr2),cap(arr2))
-
- // append
- slice4 = append(slice4,600,700)
- fmt.Println(slice4)
-
-
- }
- [root@localhost src]# go run slice.go
- []
- [0 0 0 0 0]
- [0 0 0 0 0]
- [100 500]
- [100 500]
- [100 500 2 3 99]
- **************************
- 5 5
- 5 5
- [100 500 600 700]
数组的容量和⻓度是⼀样的。cap() 函数和 len() 函数均输出数组的容量(即⻓度)
数组是 值类型 ,将⼀个数组赋值给另⼀个数组时,传递的是⼀份拷⻉。切⽚是 引⽤类型 ,切⽚包装的数组称为该切⽚的底层数组。看下⾯的例⼦:
- //a是⼀个数组,注意数组是⼀个固定⻓度的,初始化时候必须要指定⻓度,不指定⻓度的话就是切⽚了
- a := [3]int{1, 2, 3}
- //b是数组,是a的⼀份拷⻉
- b := a
- //c是切⽚,是引⽤类型,底层数组是a
- c := a[:]
- for i := 0; i < len(a); i++ {
- a[i] = a[i] + 1
- }
- //改变a的值后,b是a的拷⻉,b不变,c是引⽤,c的值改变
- fmt.Println(a) //[2,3,4]
- fmt.Println(b) //[1 2 3]
- fmt.Println(c) //[2,3,4]
数组拷贝和切片拷贝
- // 数组的拷贝
- arr4 := [3]int{1,2,3}
- arr5 := arr4
- fmt.Println(arr4, arr5)
- fmt.Println(&arr4[0], &arr5[0])
-
- //切片的拷贝
- //没有指定长度就是切片
- slice7 := []int{1,2,3}
- slice8 := slice7
- fmt.Println(slice7,slice8)
- fmt.Println(&slice7[0],&slice8[0])
-
- arr4[0] = 100
- slice7[0] = 100
- fmt.Println(arr4,slice7)
- [1 2 3] [1 2 3]
- 0xc0000140f0 0xc000014108
- [1 2 3] [1 2 3]
- 0xc000014150 0xc000014150
- [100 2 3] [100 2 3]
数组和切片的区别
切片
引用(地址相同)
函数中 -- 修改值会影响外部函数
数据拷贝 -- 拷贝引用
相同唯一类型
长度不固定
数组
相同唯一类型
长度固定
连续的数据