在本教程中,我们将讨论 Go 切片数据类型,它属于复合类型的引用数据类型。在这里,您将了解 Golang 中切片到底是什么,它们在 Golang 中的定义和声明语法,以及 Golang 中使用的复制、追加、移动函数等。
切片是一种引用类型数据结构,表示现有或底层数组中相同类型元素序列的一部分。切片指的是现有数组的一部分或一个片段。与数组一样,切片不拥有自己的数据,它只提供对数组中特定数据/元素片段的引用。
让我们通过一个简单的数组表示法来更轻松地理解切片概念。

上图显示了一个数组“A”,索引为 0、1、2...9。每个数组索引存储一些字符串类型的元素。例如,索引为 0 的数组 A[0] 包含“LET”,A[1] 包含“US”等...(为了更好地理解数组,请参考数组教程)。
现在让我们了解切片如何与数组协同工作。数组 A 将被分成两个切片。A 的两个切片 Slice 1 和 Slice 2 构成底层数组的子集。

切片的声明与数组类似。与数组相比,唯一的例外是切片的大小不需要预先指定。
例如,切片声明中的方括号 [ ] 保持为空,而在数组的情况下,方括号内指定了一些值,如 [5]、[7] 来初始化数组大小。根据切片的要求,切片的大小会相应地扩展和压缩。
语法
空方括号 [ ],后跟数组教程中讨论的任何声明类型。
[ ] arrDec
Or
[ ] arrDec{ }
Or
[ ] arrDec{value1, value 2, value 3 …………..value m}
在上述语法中,arrDec 表示所选数组声明的类型。

package main
import "fmt"
func main() {
// Creating a slice
// using the var keyword
var slice1 = []string{"learn", "e", "tutorials"}
fmt.Println(" Slice 1:", slice1)
// Creating a slice
//using shorthand declaration
slice2 := []int{ 67, 67,56,98, 43 }
fmt.Println(" Slice 2:", slice2)
}
输出
Slice 1: [learn e tutorials] Slice 2: [67 67 56 98 43]
Golang 中的 make 函数会创建一个新的切片。它是一个内置函数。
语法
make([]arrDec, len, cap) []arrDec
package main
import "fmt"
func main() {
// Creating slice using make function
A := make([]string, 5)
//initially empty
fmt.Println("array A is: ", A)
//assigning values to slice array
A[0] = "Golang"
A[1] = "in"
A[2] = "learn"
A[3] = "e"
A[4] = "tutorials"
fmt.Println("slice created using make(): ", A)
}
输出
array A is: [ ] slice created using make(): [Golang in learn e tutorials]
解释:
package main
import "fmt"
func main() {
// Creating an array
A:= [10]string{"Let", "us", "learn", "Go",
"programming", "language", "with","learn ","e","tutorials"}
// Display array
fmt.Println("Array A:", A)
// Creating a slice
slice1:= A[2:6] // start from index 2 till 5
slice2 :=A[:2] //start from index 0 till 1 excludes index 2
slice3 := A[7:] //start from 7 till ending index
slice4 := A[:]
// Display slice
fmt.Println("Slice 1 is :", slice1)
fmt.Println("Slice 2 is :", slice2)
fmt.Println("Slice 3 is :", slice3)
fmt.Println("Slice 4 is :", slice4)
}
输出
Output Array A: [Let us learn Go programming language with learn e tutorials] Slice 1 is : [learn Go programming language] Slice 2 is : [Let us] Slice 3 is : [learn e tutorials] Slice 4 is : [Let us learn Go programming language with learn e tutorials]
切片内部结构是构成切片的组件。切片在内部表示为指向数组的指针,以及其长度和容量。我们知道切片是数组的一个片段,具有这三个组件,因此可以用以下语法概括。
type Slice struct {
array unsafe.Pointer
cap int
len int
}
指针指向数组中切片的初始元素。在给定示例中,切片 1 包含元素
[“LEARN”,” GO”,” PROGRAMMING”,” LANGUAGE]

这里初始或起始元素是索引为 2 的 learn,所以指针指向该位置。因此指针设置为 2。
切片的长度是切片中元素的数量。len()函数用于确定切片的长度。在下面给定的切片1中,从开头算起共有4个元素。因此长度设置为4。
切片1 ---- > [“LEARN’ “Go”,” PROGRAMMING” “LANGUAGE “]
len(slice1) 返回切片 1 中存在的元素数量,即 len(slice1) 调用返回值为 4。
切片的容量是底层数组中元素的最大数量。切片中的 `cap()` 函数用于确定切片的容量。在下面的示例中,从 slice1 元素的开头开始计数,直到底层数组的末尾。

因此,从切片 1 索引的开头到数组的末尾位置计数,表示上述切片的容量,它返回一个整数值 8。它可以表示为 **cap(slice) = 8**。
下图描述了切片 1 的内部组件,其中指针指向数组地址 2,片段长度为 4,切片 1 的容量为 8,因为切片 1 是数组 A 的一个片段,实际大小为 10(0,1,2.....9 索引),其中从 2 到 5 的索引形成切片 1 的片段,连同从 6 到 9 的剩余索引共同构成总容量,即容量等于 8。(与上面讨论的示例相关)

让我们使用 Golang 来理解上面讨论的 len() 和 cap() 函数。我们讨论的相同描述在下面的 Go 程序中进行了编码。
package main
import "fmt"
func main() {
// Creating an array
A:= [10]string{"Let", "us", "learn", "Go",
"programming", "language", "with","learn ","e","tutorials"}
// Display array
fmt.Println("Array:", A)
// Creating a slice
slice1:= arr[2:6] //slicing array
// Display slice
fmt.Println("Slice 1 is :", slice1)
// Display length of the slice
fmt.Printf("Length of the slice 1: %d", len(slice1))
// Display the capacity of the slice
fmt.Printf("\nCapacity of the slice 1: %d", cap(slice1))
}
输出
Output Array A: [Let us learn Go programming language with learn e tutorials] Slice 1 is : [learn Go programming language] Length of the slice 1: 4 Capacity of the slice 1: 8
Append () 函数是切片中的一个内置函数,用于向切片追加元素。
另外,append () 允许扩展切片的大小。
package main
import "fmt"
func main() {
// slice creation using make()
A := make([]string, 3)
//dispplays initial slice values
fmt.Printf("slice:%v; len: %d; cap: %d \n", A, len(A), cap(A))
fmt.Println("---------------------------")
//performs appending values to slice A
A = append(A, "Go")
A = append(A, "Lang")
A = append(A, "in")
A = append(A, "learn", "e", "tutorials")
//display slice after insertion
fmt.Printf("slice: %v; len: %d; cap: %d \n", A, len(A), cap(A))
}
输出
slice:[ ]; len: 3; cap: 3 --------------------------- slice: [ Go Lang in learn e tutorials]; len: 9; cap: 12
Copy() 函数是一个内置函数,允许将元素从一个切片(源切片)复制到另一个切片(目标切片)。
package main
import "fmt"
func main() {
// slice creation using make()
A := []string {"Go", "lang"}
B :=make([]string,len(A))
//displays initial slice values
fmt.Printf("Initial slice A:%v; len: %d; cap: %d \n", A, len(A), cap(A))
fmt.Println("---------------------------")
copy1 := copy(B,A)
//display slice after COPYING
fmt.Printf("%d elements copied\n", copy1)
fmt.Printf("slice after copying to B: %v; len: %d; cap: %d \n", B, len(B), cap(B))
}
输出
Initial slice A:[Go lang]; len: 2; cap: 2 --------------------------- 2 elements copied slice after copying to B: [Go lang]; len: 2; cap: 2
在上面的程序中,使用 copy() 函数将切片 A 中的复制切片声明为字符串类型的切片 B。
在切片中,for 循环用于迭代切片元素。
package main
import "fmt"
func main() {
tutorial := []string{"Go", "Programming", "language", "in", "learn", "e","tutorials"}
for a, tutorial := range tutorial {
fmt.Println(a, tutorial)
}
}
输出
0 Go 1 Programming 2 language 3 in 4 learn 5 e 6 tutorials
| 序号 | 数组 | 切片 |
|---|---|---|
| 1 | 数组存储相同类型的元素序列 | 切片不存储任何数据 |
| 2 | 数组大小固定 | 切片灵活可调整大小 |
| 3 | 数组在 Go 中使用较少 | 切片在 Go 中最常用 |
| 4 | 数组副本指向不同的底层数据 | 切片副本指向相同的底层数据 |