go 语言的切片并不是数组或数组指针,它通过内部指针和相关属性引用数组片段,以实现变长的功能,大多数情况下都需要使用到切片来处理元素动态修改的问题,Go 语言的切片类似于 python 的列表,都是实现元素的动态扩展,下面是 go 语言切片的相关基础(声明具体长度的是数组,没有声明具体长度的为切片):
① 创建切片,可以通过数组或者 make 函数来创建对应的切片,使用make函数创建切片的时候可以声明切片的长度,这样后面就可以 copy 函数将一个切片中的元素拷贝到另外一个切片;
② 操作切片,可以通过索引对切片中的元素进行修改,通过 append 函数向切片末尾添加元素,使用copy函数对切片进行拷贝,通过 copy 函数可以将一个切片中的元素拷贝到另外一个切片,以长度较短的切片为准,拷贝到另外一个切片之后会覆盖掉另外一个切片对应长度的所有元素;通过索引来操作有点类似于 python 中的切片;
③ 切片遍历,类似于数组的遍历,可以使用range(Go语言 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、链表(channel)或集合(map)的元素;在数组和切片中它返回元素的索引值, 在集合中返回 key-value 对的 key 值)来遍历;也可以使用索引遍历;
④ 字符串和切片操作,string 字符串的底层是一个 byte 数组所以也可以使用切片操作,而且字符串是不可以修改的,需要将字符串变为byte数组才可以进行修改,最终再用 string 修改回字符串即可;
⑤ 切片中两个冒号的理解,一般的切片为a[1:5]这样的形式,表示切片的内容为从索引为 1 到 4 的元素,a[:3:5] 表示切片的内容为索引为 0 到 2 的元素,并且最大扩充项 cap 设置为 5;
⑥ 动态添加二维切片每一维的内容,我们可以声明一个二维切片,一开始每一维都是空的切片(或者第二维为空),可以使用 append 方法将另外切片的内容添加到二维切片对应位置上;
其实 go 语言的切片可以看成是与 python 的列表差不多强大的动态数据结构,属于数组的变长扩展,各有自己的优点,但是我感觉 python的 list 列表是一种非常强大的数据结构,可以动态修改列表中的元素,列表中任何一个位置的元素都可以插入,删除元素,所以可以充当栈和队列,所以动态操作元素是很强大的,而 go 语言则可以通过 slice 切片,使用 append 进行动态添加元素,但是 append 方法只能够在切片的末尾执行添加元素的操作,这就有点不太方便了;切片操作经常会使用 append 方法,例如往一个切片的末尾添加一个元素或者添加另外一个切片的所有元素,使用 append 方法不会修改原切片这一点很重要,很多情况下我们不希望修改原切片,所以一般我们会声明一个空的 slice 切片然后使用 append 来添加元素。很多时候我们都是利用切片来动态修改元素,可以与 python 的列表进行比较,都是动态操作元素,下面是与切片有关的代码:
package main
import (
"fmt"
)
func main() {
//声明切片, 切片不用声明具体的长度
var a []int
fmt.Println(a)
b := []int{}
fmt.Println(b)
// c为一个长度为5的int类型数组
c := [5]int{2, 3, 5, 6, 8}
// 从数组c切片, 与python的切片是类似的
c1 := c[0:len(c)]
fmt.Println(c1)
fmt.Println("输出对应引用类型变量的地址: ")
// 使用%p输出地址
fmt.Printf("%p\n", &c)
// 输出c1的地址
fmt.Printf("%p\n", &c1)
// 数组切片
var arr = [10]int{1, 2, 4, 6, 8, 9, 12, 45}
// arr1为arr中所有元素的值
var arr1 = arr[:]
fmt.Println(arr1)
arr2 := arr[2:6]
fmt.Println(arr2)
// 切片拷贝
fmt.Println("切片拷贝: ")
s4 := []int{1, 2, 3, 4, 5}
s5 := make([]int, 5)
// copy函数复制的时候以较小的长度为准, copy函数返回的是复制的数目
copy(s5, s4)
fmt.Println(s5)
s5[0] = -1
fmt.Println("copy方法修改切片元素的影响: ")
fmt.Println(s4, s5)
fmt.Println("append方法操作切片")
var arr3 = []int{}
// 通过append内置函数向切片添加一个元素
arr4 := append(arr3, 21)
fmt.Println(arr4)
arr5 := []int{10, 11, 12, 13, 14}
arr6 := []int{}
// 一个切片添加另外一个切片的所有元素这个时候append之后的那个切片对其修改不会影响到之前的那个切片
// 需要注意的是一个切片使用append方法添加另外一个切片的所有元素需要在原切片后面添加...
arr6 = append(arr6, arr5...)
fmt.Println("使用append方法未修改切片元素为: ")
fmt.Println(arr5, arr6)
// 对切片的元素进行修改
arr6[1] = -1
fmt.Println("使用append方法对切片修改之后的: ")
fmt.Println(arr5, arr6)
// 通过make函数来创建切片, make函数的第三个参数为cap
fmt.Println("使用make函创建切片: ")
var slice1 []int = make([]int, 10)
var slice2 = make([]int, 5)
var slice3 = make([]int, 10, 15)
s := make([]int, 2, 8)
s[1] = 10
slice2[0] = 89
fmt.Println(slice1)
fmt.Println(slice2)
fmt.Println(slice3)
t := append(s, slice2...)
fmt.Println(t)
fmt.Println(s)
// 切片遍历
fmt.Println("切片遍历: ")
data := [...]int{1, 2, 3, 4, 5, 6, 8, 10}
data1 := data[:]
// 使用range来遍历
for index, value := range data1 {
fmt.Printf("%v %v\n", index, value)
}
fmt.Println("字符串和切片: ")
// string底层本身就是一个byte数组, 因为也可以进行切片操作
str := "good morning!"
str2 := str[0:5]
fmt.Printf(str2)
fmt.Println()
// 字符串本身是不可以改变的, 如果需要改变需要执行下面的操作
str3 := []byte(str)
str3[0] = 'G'
str = string(str3)
fmt.Println(str)
fmt.Println("切片中两个冒号的理解: ")
// go语言切片两个冒号的理解
d1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 一般的切片如下面的形式: 切片的内容从第5位开始到第7位的元素, 长度为3
d2 := d1[5:8]
fmt.Println(d2, len(d2), cap(d2))
// 切片的内容为从第0位到第4位的元素, 长度为5, 最大扩充项cap设置为8
d3 := d1[:5:8]
fmt.Println(d3, len(d3), cap(d3))
fmt.Println("动态添加二维切片中每一维的内容: ")
d := [][]int{}
// 往二维切片中添加空的切片, 添加完成之后二维切片中有五个一维的空切片
for i := 0; i < 5; i++ {
d = append(d, []int{})
}
fmt.Println(d)
// 声明一个二维的切片, 一开始每一维是一个空的切片, 后面才可以往对应位置使用append添加对应长度的切片
slice := [][]int{{}, {}, {}}
sli1 := []int{1, 2, 3}
slice[0] = append(slice[0], sli1...)
sli2 := []int{4, 5}
slice[1] = append(slice[1], sli2...)
sli3 := []int{7, 8, 9, 10}
slice[2] = append(slice[2], sli3...)
fmt.Println(slice)
}
声明对应大小的二维切片:
package main
import "fmt"
func main() {
// 1. 第一种方法
row := 5
col := 5
arr := make([][]int, row)
for i := range arr {
arr[i] = make([]int, col)
}
fmt.Println(arr)
// 2. 第二种方法
var arr2 [][]int
for i := 0; i < row; i++ {
t := make([]int, col)
arr2 = append(arr2, t)
}
fmt.Println(arr2)
}