Go语言数组
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
数组声明方法
Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:
var variable_name [SIZE] variable_type
以上为一维数组的定义方式。例如以下定义了数组 balance 长度为 10 类型为 float32:
var balance [10] float32
实例
package main
import "fmt"
func main() {
// 定义一个空数组
var arr1 [5]int
// 使用 := 的方法定义数组必须要指定数组长度
arr2 := [3]int{1, 3, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
fmt.Println(arr1, arr2, arr3)
}
运行结果
[0 0 0 0 0] [1 3 5] [2 4 6 8 10]
多维数组
package main
import "fmt"
func main() {
// 二维数组,四行五列
var grid [4][5] bool
fmt.Println(grid)
}
运行结果
[[false false false false false]
[false false false false false]
[false false false false false]
[false false false false false]]
数组的遍历
package main
import "fmt"
func main() {
arr3 := [...]int{2, 4, 6, 8, 10}
// 遍历数组
for i := 0; i<len(arr3); i++{
fmt.Println(arr3[i])
}
}
运行结果
2
4
6
8
10
使用range
关键字进行数组遍历
package main
import "fmt"
func main() {
arr3 := [...]int{2, 4, 6, 8, 10}
// 通过range关键字进行遍历数组,同时获取值和下标
for i, v := range arr3{
fmt.Println(i, v)
}
}
运行结果
0 2
1 4
2 6
3 8
4 10
package main
import "fmt"
func main() {
// 通过range关键字进行遍历,只取值
for _, v := range arr3{
fmt.Println(v)
}
}
运行结果:
2
4
6
8
10
把数组作为参数时,会使用值传递,拷贝数组
package main
import "fmt"
func printArray(arr [5]int) {
arr[0] = 100
for i, v := range arr{
fmt.Println(i, v)
}
}
func main() {
// 定义一个空数组
var arr1 [5]int
printArray(arr1)
fmt.Println(arr1)
}
运行结果
0 100
1 0
2 0
3 0
4 0
[0 0 0 0 0]
Go语言切片
Go 语言切片是对数组的抽象。
Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go 中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
定义切片
你可以声明一个未指定大小的数组来定义切片:
var identifier []type
切片不需要说明长度。
-
切片初始化
// 直接定义一个slice, zero value for slice is nil var s [] int
-
通过
make
函数// 通过内置函数 make() 初始化切片s,[]int 标识为其元素类型为 int 的切片。 s :=make([]int,len,cap)
切片的截取
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
// 包头不包尾
fmt.Println("arr[2:6]=", arr[2:6])
// 从下标为0个元素开始,到下标为5个元素结束
fmt.Println("arr[:6]=", arr[:6])
// 从下标为2的元素开始,到切片的末端
fmt.Println("arr[2:]=", arr[2:])
// 取全部
fmt.Println("arr[:]=", arr[:])
}
运行结果:
arr[2:6]= [2 3 4 5]
arr[:6]= [0 1 2 3 4 5]
arr[2:]= [2 3 4 5 6 7]
arr[:]= [0 1 2 3 4 5 6 7]
Slice
本身没有数据,是对底层array
的一个view
package main
import "fmt"
func updateSlice(s []int){
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:]
fmt.Println("s1=", s1)
s2 := arr[:]
fmt.Println("s2=", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
}
运行结果
s1= [2 3 4 5 6 7]
s2= [0 1 2 3 4 5 6 7]
After updateSlice(s1)
[100 3 4 5 6 7]
[0 1 100 3 4 5 6 7]
After updateSlice(s2)
[100 1 100 3 4 5 6 7]
[100 1 100 3 4 5 6 7]
切片可以在切片的基础上继续切片
package main
import "fmt"
func updateSlice(s []int){
s[0] = 100
}
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:]
fmt.Println("s1=", s1)
s2 := arr[:]
fmt.Println("s2=", s2)
fmt.Println("After updateSlice(s1)")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
fmt.Println("After updateSlice(s2)")
updateSlice(s2)
fmt.Println(s2)
fmt.Println(arr)
fmt.Println("Reslice")
fmt.Println(s2)
s2 = s2 [:5]
fmt.Println(s2)
s2 = s2 [2:]
fmt.Println(s2)
}
运行结果
s1= [2 3 4 5 6 7]
s2= [0 1 2 3 4 5 6 7]
After updateSlice(s1)
[100 3 4 5 6 7]
[0 1 100 3 4 5 6 7]
After updateSlice(s2)
[100 1 100 3 4 5 6 7]
[100 1 100 3 4 5 6 7]
Reslice
[100 1 100 3 4 5 6 7]
[100 1 100 3 4]
[100 3 4]
切片的扩展
slice
可以向后扩展,不可以向前扩展。
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println("Extending slice")
s1 = arr[2:6]
s2 = s1[3:5]
fmt.Println("s1=", s1)
fmt.Println("s2=", s2)
}
运行结果
Extending slice
s1= [2 3 4 5]
s2= [5 6]
len()
和 cap()
函数
切片是可索引的,并且可以由 len() 方法获取长度。
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
在切片中,s[i]不可以超越len(s)
,向后扩展不可以超越底层数组cap(s)
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println("Extending slice")
s1 = arr[2:6]
s2 = s1[3:5]
fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n",
s1, len(s1), cap(s1))
fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n",
s2, len(s2), cap(s2))
}
运行结果
Extending slice
s1=[2 3 4 5], len(s1)=4, cap(s1)=6
s2=[5 6], len(s2)=2, cap(s2)=3
append()函数
- 向
slice
添加元素时如果超越cap
,系统会重新分配更大的底层数组,原数组如果不使用,会被Go语言的垃圾回收机制回收。 - 由于值传递的关系,必须接受
appdend()
的返回值。
实例:
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println("Extending slice")
s1 = arr[2:6]
s2 = s1[3:5]
fmt.Printf("s1=%v, len(s1)=%d, cap(s1)=%d\n",
s1, len(s1), cap(s1))
fmt.Printf("s2=%v, len(s2)=%d, cap(s2)=%d\n",
s2, len(s2), cap(s2))
s3 := append(s2, 10)
// s4和s5不再是arr的视图
s4 := append(s3, 11)
s5 := append(s4, 12)
fmt.Println("s3, s4, s5 =", s3, s4, s5)
fmt.Println("arr = ", arr)
}
运行结果
Extending slice
s1=[2 3 4 5], len(s1)=4, cap(s1)=6
s2=[5 6], len(s2)=2, cap(s2)=3
s3, s4, s5 = [5 6 10] [5 6 10 11] [5 6 10 11 12]
arr = [0 1 2 3 4 5 6 10]
切片操作
实例:
package main
import "fmt"
func printSlice(s []int){
// 每次以原切片长度的2倍进行扩充
fmt.Printf("%v,len=%d, cap=%d\n",s, len(s), cap(s))
}
func main() {
fmt.Println("Creating slice")
// 直接定义一个slice, zero value for slice is nil
var s [] int
for i :=0; i<100;i++{
printSlice(s)
s = append(s, 2*i+1)
}
fmt.Println(s)
// 切片的创建
s1 := []int{2, 4, 6, 8}
printSlice(s1)
// 切片的创建,使用make,创建一个长度为16的slice
s2 := make([]int,16)
printSlice(s2)
// 长度为10,cap为32
s3 := make([]int, 10, 32)
printSlice(s3)
fmt.Println("Copying slice")
copy(s2, s1)
printSlice(s2)
fmt.Println("Deleting elements from slice")
// 删除下标为3的元素
s2 = append(s2[:3], s2[4:]...)
fmt.Println(s2)
fmt.Println("Popping from front")
front := s2[0]
s2 = s2[1:]
fmt.Println(front)
fmt.Println(s2)
fmt.Println("Popping from back")
tail := s2[len(s2) - 1]
s2 = s2[:len(s2) - 1]
fmt.Println(tail)
printSlice(s2)
}
运行结果
Creating slice
[2 4 6 8],len=4, cap=4
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],len=16, cap=16
[0 0 0 0 0 0 0 0 0 0],len=10, cap=32
Copying slice
[2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0],len=16, cap=16
Deleting elements from slice
[2 4 6 0 0 0 0 0 0 0 0 0 0 0 0]
Popping from front
2
[4 6 0 0 0 0 0 0 0 0 0 0 0 0]
Popping from back
0
[4 6 0 0 0 0 0 0 0 0 0 0 0],len=13, cap=15