0
点赞
收藏
分享

微信扫一扫

Go语言数组和切片

归零者245号 2022-01-04 阅读 166

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

切片不需要说明长度。

  1. 切片初始化

    // 直接定义一个slice, zero value for slice is nil
    	var s [] int
    
  2. 通过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
举报

相关推荐

0 条评论