在Go语言中,切片比数组更强大,灵活,方便,并且是轻量级的数据结构。slice是一个可变长度序列,用于存储相同类型的元素,不允许在同一slice中存储不同类型的元素。就像具有索引值和长度的数组一样,但是切片的大小可以调整,切片不像数组那样处于固定大小。在内部,切片和数组相互连接,切片是对基础数组的引用。允许在切片中存储重复元素。切片中的第一个索引位置始终为0,而最后一个索引位置将为(切片的长度– 1)。
切片的声明就像数组一样,但是不包含切片的大小。因此它可以根据需要增长或缩小。
语法:
[]T
或
[]T{}
或
[]T{value1, value2, value3, ...value n}在此,T是元素的类型。例如:
var my_slice[]int
切片包含三个组件:
指针:指针用于指向可通过切片访问的数组的第一个元素。在这里,指向的元素不必是数组的第一个元素。
长度:长度是数组中存在的元素总数。
容量:容量表示可以扩展的最大大小。
让我们借助示例讨论所有这些组件:
//切片
package main
import "fmt"
func main() {
//创建一个数组
arr := [7]string{"这", "是", "Golang", "基础", "教程", "在线", "www.cainiaojc.com"}
//显示数组
fmt.Println("数组:", arr)
//创建切片
myslice := arr[1:6]
//显示切片
fmt.Println("切片:", myslice)
//显示切片的长度
fmt.Printf("切片长度: %d", len(myslice))
//显示切片的容量
fmt.Printf("\n切片容量: %d", cap(myslice))
}输出:
数组: [这 是 Golang 基础 教程 在线 www.cainiaojc.com] 切片: [是 Golang 基础 教程 在线] 切片长度: 5 切片容量: 6
用法解释:在上面的实例中,我们从给定的数组中创建一个切片。这里,片的指针指向索引1,因为片的下界被设置为1,所以它开始访问来自索引1的元素。切片的长度为5,表示切片中元素的总数为5,而切片6的容量表示最多可以存储6个元素。
在Go语言中,可以使用以下方式创建和初始化切片:
使用切片字面量:您可以使用切片字面量创建切片。切片字面量的创建就像数组字面量一样,但是有一个区别,即不允许您在方括号[]中指定切片的大小。如下例所示,该表达式的右侧是切片字面量。
var my_slice_1 = []string{"cainiaojcs", "for", "cainiaojcs"}注意:切记,当您使用字符串文字创建切片时,它首先创建一个数组,然后返回对其的切片引用。
// 使用切片创建切片字面量
package main
import "fmt"
func main() {
//使用var关键字,创建切片
var my_slice_1 = []string{"cainiaojcs", "for", "cainiaojcs"}
fmt.Println("My Slice 1:", my_slice_1)
//创建切片
//使用简写声明
my_slice_2 := []int{12, 45, 67, 56, 43, 34, 45}
fmt.Println("My Slice 2:", my_slice_2)
}输出:
My Slice 1: [cainiaojc$1 for cainiaojcs] My Slice 2: [12 45 67 56 43 34 45]
使用数组:我们已经知道切片是数组的引用,因此您可以根据给定的数组创建切片。要从给定数组创建切片,首先需要指定下限和上限,这意味着slice可以从下限到上限开始获取数组中的元素。它不包括上面从上限开始的元素。如下例所示:
语法:
array_name[low:high]
此语法将返回一个新切片。
注意:下限的默认值为0,上限的默认值为给定数组中存在的元素总数。
//从数组创建切片
package main
import "fmt"
func main() {
//创建一个数组
arr := [4]string{"cainiaojcs", "for", "cainiaojcs", "GFG"}
//从给定数组创建切片
var my_slice_1 = arr[1:2]
my_slice_2 := arr[0:]
my_slice_3 := arr[:2]
my_slice_4 := arr[:]
//显示结果
fmt.Println("我的数组: ", arr)
fmt.Println("My Slice 1: ", my_slice_1)
fmt.Println("My Slice 2: ", my_slice_2)
fmt.Println("My Slice 3: ", my_slice_3)
fmt.Println("My Slice 4: ", my_slice_4)
}输出:
我的数组: [cainiaojc$1 for cainiaojcs GFG] My Slice 1: [for] My Slice 2: [cainiaojc$1 for cainiaojcs GFG] My Slice 3: [cainiaojc$1 for] My Slice 4: [cainiaojc$1 for cainiaojcs GFG]
使用已经存在的切片:也可以从给定的切片创建切片。要从给定切片创建切片,首先需要指定下限和上限,这意味着slice可以从给定切片中从下限到上限开始获取元素。它不包括上面从上限开始的元素。如下例所示:
语法:
slice_name[low:high]
此语法将返回一个新切片。
注意:下限的默认值为0,上限的默认值为给定切片中存在的元素总数。
//从切片创建切片
package main
import "fmt"
func main() {
//创建切片
oRignAl_slice := []int{90, 60, 40, 50, 34, 49, 30}
//从给定的切片创建切片
var my_slice_1 = oRignAl_slice[1:5]
my_slice_2 := oRignAl_slice[0:]
my_slice_3 := oRignAl_slice[:6]
my_slice_4 := oRignAl_slice[:]
my_slice_5 := my_slice_3[2:4]
//显示结果
fmt.Println("原始切片:", oRignAl_slice)
fmt.Println("新切片 1:", my_slice_1)
fmt.Println("新切片 2:", my_slice_2)
fmt.Println("新切片 3:", my_slice_3)
fmt.Println("新切片 4:", my_slice_4)
fmt.Println("新切片 5:", my_slice_5)
}输出:
原始切片: [90 60 40 50 34 49 30] 新切片 1: [60 40 50 34] 新切片 2: [90 60 40 50 34 49 30] 新切片 3: [90 60 40 50 34 49] 新切片 4: [90 60 40 50 34 49 30] 新切片 5: [40 50]
使用make()函数:您还可以使用go库提供的make()函数创建切片。此函数采用三个参数,即类型,长度和容量。在此,容量值是可选的。它为底层数组分配的大小等于给定的容量,并返回一个切片,该切片引用底层数组。通常,make()函数用于创建一个空切片。在这里,空切片是包含空数组引用的那些切片。
语法:
func make([]T, len, cap) []T
//使用make函数
package main
import "fmt"
func main() {
//创建大小为7的数组
//将此数组切成4
//并返回切片的引用
//使用make函数
var my_slice_1 = make([]int, 4, 7)
fmt.Printf("Slice 1 = %v, \nlength = %d, \ncapacity = %d\n",my_slice_1, len(my_slice_1), cap(my_slice_1))
//创建另一个大小为7的数组
//并返回切片的引用
//使用make函数
var my_slice_2 = make([]int, 7)
fmt.Printf("Slice 2 = %v, \nlength = %d, \ncapacity = %d\n",my_slice_2, len(my_slice_2), cap(my_slice_2))
}输出:
Slice 1 = [0 0 0 0], length = 4, capacity = 7 Slice 2 = [0 0 0 0 0 0 0], length = 7, capacity = 7
您可以使用以下方式遍历切片:
使用for循环:这是迭代切片的最简单方法,如以下示例所示:
// for循环迭代切片
package main
import "fmt"
func main() {
//创建切片
myslice := []string{"This", "is", "the", "tutorial", "of", "Go", "language"}
//使用for循环进行迭代
for e := 0; e < len(myslice); e++ {
fmt.Println(myslice[e])
}
}输出:
This is the tutorial of Go language
在for循环中使用范围:允许使用for循环中的范围对切片进行迭代。在for循环中使用range,可以获得索引和元素值,如示例所示:
//在for循环中使用范围的切片
package main
import "fmt"
func main() {
//创建切片
myslice := []string{"This", "is", "the", "tutorial", "of", "Go", "language"}
//迭代切片
//在for循环中使用range
for index, ele := range myslice {
fmt.Printf("Index = %d and element = %s\n", index+3, ele)
}
}输出:
Index = 3 and element = This Index = 4 and element = is Index = 5 and element = the Index = 6 and element = tutorial Index = 7 and element = of Index = 8 and element = Go Index = 9 and element = language
在for循环中使用空白标识符:在for循环范围内,如果您不想获取元素的索引值,则可以使用空格(_)代替索引变量,如以下示例所示:
//在for循环中使用范围的切片而没有索引
package main
import "fmt"
func main() {
//创建切片
myslice := []string{"This", "is", "the", "tutorial", "of", "Go", "language"}
//迭代切片
//在for循环中使用range
//没有索引
for _, ele := range myslice {
fmt.Printf("Element = %s\n", ele)
}
}输出:
Element = This Element = is Element = the Element = tutorial Element = of Element = Go Element = language
零值切片:在Go语言中,允许您创建一个不包含任何元素的零切片。因此,此片的容量和长度为0。nil切片不包含数组引用,如以下示例所示:
package main
import "fmt"
func main() {
// 创建零值切片
var myslice []string
fmt.Printf("Length = %d\n", len(myslice))
fmt.Printf("Capacity = %d ", cap(myslice))
}输出:
Length = 0 Capacity = 0
修改Slice:正如我们已经知道slice是引用类型一样,它可以引用基础数组。因此,如果我们更改切片中的某些元素,则更改也应发生在引用数组中。换句话说,如果您对切片进行了任何更改,则切片也会反映在数组中,如以下示例所示:
//如何修改切片
package main
import "fmt"
func main() {
//创建零值切片
arr := [6]int{55, 66, 77, 88, 99, 22}
slc := arr[0:4]
//修改前
fmt.Println("Original_Array: ", arr)
fmt.Println("Original_Slice: ", slc)
//修改后
slc[0] = 100
slc[1] = 1000
slc[2] = 1000
fmt.Println("\nNew_Array: ", arr)
fmt.Println("New_Slice: ", slc)
}输出:
Original_Array: [55 66 77 88 99 22] Original_Slice: [55 66 77 88] New_Array: [100 1000 1000 88 99 22] New_Slice: [100 1000 1000 88]
切片的比较:在切片中,您只能使用==运算符检查给定切片是否存在。如果尝试在==运算符的帮助下比较两个切片,则会抛出错误,如下例所示:
//判断切片是否为零
package main
import "fmt"
func main() {
//创建切片
s1 := []int{12, 34, 56}
var s2 []int
//如果你尝试运行这个注释
//代码编译器将给出一个错误
/*s3:= []int{23, 45, 66}
fmt.Println(s1==s3)
*/
//检查给定的片是否为nil
fmt.Println(s1 == nil)
fmt.Println(s2 == nil)
}输出:
false true
注意:如果要比较两个切片,请使用循环范围匹配每个元素,或者可以使用DeepEqual函数。
多维切片:多维切片与多维数组一样,只是切片不包含大小。
package main
import "fmt"
func main() {
//创建多维切片
s1 := [][]int{{12, 34},
{56, 47},
{29, 40},
{46, 78},
}
//访问多维切片
fmt.Println("Slice 1 : ", s1)
//创建多维切片
s2 := [][]string{
[]string{"cainiaojcs", "for"},
[]string{"cainiaojcs", "GFG"},
[]string{"gfg", "cainiaojc"},
}
//访问多维切片
fmt.Println("Slice 2 : ", s2)
}输出:
Slice 1 : [[12 34] [56 47] [29 40] [46 78]] Slice 2 : [[cainiaojc$1 for] [cainiaojc$1 GFG] [gfg cainiaojc]]
切片排序:在Go语言中,可以对切片中存在的元素进行排序。 Go语言的标准库提供了sort包,其中包含用于对int,float64和字符串切片进行排序的不同类型的排序方法。 这些函数始终按升序对可用元素进行切片排序。
//切片中存在的元素
package main
import (
"fmt"
"sort"
)
func main() {
//创建切片
slc1 := []string{"Python", "Java", "C#", "Go", "Ruby"}
slc2 := []int{45, 67, 23, 90, 33, 21, 56, 78, 89}
fmt.Println("在排序之前:")
fmt.Println("Slice 1: ", slc1)
fmt.Println("Slice 2: ", slc2)
//切片使用排序函数
sort.Strings(slc1)
sort.Ints(slc2)
fmt.Println("\n排序后:")
fmt.Println("Slice 1: ", slc1)
fmt.Println("Slice 2: ", slc2)
}输出:
排序前: Slice 1: [Python Java C# Go Ruby] Slice 2: [45 67 23 90 33 21 56 78 89] 排序后: Slice 1: [C# Go Java Python Ruby] Slice 2: [21 23 33 45 56 67 78 89 90]