一、切片定义
定义切片
var identifier []type
切片不需要说明长度。 或使用make()函数来创建切片:
var slice1 []type = make([]type, len)
也可以简写为
slice1 := make([]type, len)
make([]T, length, capacity)
空切片:一个切片在未初始化之前默认为 nil,长度为 0
package main
import "fmt"
func main() {
var numbers []int
printSlice(numbers)
if(numbers == nil){
fmt.Printf("切片是空的")
}
}
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
完整代码:
package main
import "fmt"
func main() {
//第一种::声明slice1是一个切片,并且初始化,默认值是1,2,3,长度是3
//slice1 := []int{1, 2, 3}
//第二种::声明一个slice1是一个切片,但是并没有给slice分配空间
//var slice1 []int
//这个时候如果写slice1【0】=1,就会报错,因为还没有给slice1分配空间
//slice1[0] = 1,错误是:"runtime error: index out of range [0] with length 0"
//通过make开辟空间
//slice1 = make([]int, 3) //开辟三个容量,此时默认值是0
//slice1[1] = 1000
//第三种::声明一个slice1是一个切片,同时给slice分配3个空间,初始化为0
//var slice1[]int=make([]int, 3)
//或者用通过:=推导出slice是一个切片
slice1 := make([]int, 3)
//fmt.Printf("len = %d,slice = %v\n", len(slice1), slice1) //"%v表示打印所有信息"
//判断一个slice是否为0
if slice1 == nil {
fmt.Println("slice是一个空切片")//第十行会是一个空切片
} else {
fmt.Println("slice不是一个空切片")//20行的可不是空切片
}
}
make(1,2,3):1.表示类型,2.表示长度,3.表示容量
二、切片追加
使用append进行追加,代码如下
package main
import "fmt"
func main() {
var numbers = make([]int, 3, 5) //len=3,cap=5
fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
//想numbers追加一个元素1,len=4,cap=5
numbers = append(numbers, 1)
fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
numbers = append(numbers, 2)
//向一个满容cap的slice追加元素
numbers = append(numbers, 3)
fmt.Printf("len=%d,cap=%d,slice=%v\n", len(numbers), cap(numbers), numbers)
//cap会扩大两倍
}
注意:当cap(容量)满了的时候再去追加,cap会自动变成原来的两倍。 总结,如下图
三、切片截取
s := arr[startIndex:endIndex]
将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片(前闭后开),长度为endIndex-startIndex
s := arr[startIndex:]
缺省endIndex时将表示一直到arr的最后一个元素
s := arr[:endIndex]
缺省startIndex时将表示从arr的第一个元素开始
截取很简单的,直接看代码吧
package main
import "fmt"
func main() {
s := []int{1, 2, 3} //len=3,cap=3
s1 := s[0:2] //从索引下标0开始,左闭右开,也就是说截取index=0和1两个元素。即截取1,2
fmt.Println(s1) //【1 2】
//注意此时改变了s1的第一个值,s的值也会改变,因为他俩指定的同一块内存地址
s1[0] = 100
fmt.Println(s)
fmt.Println(s1)
//如果想不改变s的值,那么可以用copy进行拷贝
s2 := make([]int, 3)
copy(s2, s) //将s中的值拷贝给s2
s2[0] = 100
//fmt.Println(s) //[1 2 3]
fmt.Println(s2) //[100 2 3]
}
当然我还演示了,如何在截取之后改变截取的值而不改变原切片的值
四、切片修改
slice没有自己的任何数据。它只是底层数组的一个表示。对slice所做的任何修改都将反映在底层数组中。
示例代码:
package main
import (
"fmt"
)
func main() {
darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
dslice := darr[2:5]
fmt.Println("array before",darr)
for i := range dslice {
dslice[i]++
}
fmt.Println("array after",darr)
}
运行结果:
array before [57 89 90 82 100 78 67 69 59]
array after [57 89 91 83 101 78 67 69 59]
当多个片共享相同的底层数组时,每个元素所做的更改将在数组中反映出来。
示例代码:
package main
import (
"fmt"
)
func main() {
numa := [3]int{78, 79 ,80}
nums1 := numa[:] //creates a slice which contains all elements of the array
nums2 := numa[:]
fmt.Println("array before change 1",numa)
nums1[0] = 100
fmt.Println("array after modification to slice nums1", numa)
nums2[1] = 101
fmt.Println("array after modification to slice nums2", numa)
}
运行结果:
array before change 1 [78 79 80]
array after modification to slice nums1 [100 79 80]
array after modification to slice nums2 [100 101 80]
总结:
切片Slice:
1.每一个切片引用了一个底层数组
2.切片本身不存储任何数据,都是这个底层数组存储,所以修改切片也就是修改这个数组中的数据
3.当向切片中添加数据时,如果没有超过容量,直接添加,如果超过容量,自动扩容(成倍增长)
4.切片一旦扩容,就是重新指向一个新的底层数组