Go 基础教程-7-slice
切片Slice
相关概念
其本身并不是数组,它指向底层的数组
作为变长数组的替代方案,可以关联底层数组的局部或全部
为引用类型可以直接创建或从底层数组获取生成
使用len()获取元素个数,cap()获取容量
一般使用make()创建
如果多个slice指向相同底层数组,其中一个的值改变会影响全部
make([]T, len, cap)
其中cap可以省略,则和len的值相同
len表示存数的元素个数,cap表示容量7. 切片的长度不会超过它的容量(否则报错)
切片长度使用汇总
func main(){
a := [10]int{1,2,3,4,5,6,7,8,9,10}
fmt.Println(a)
//从第5个索引开始截取
s1 = a[5:]
s3 = a[5:len(a)]
//从索引0截取,遇到索引为5停下来(不包含索引为5)
s0 = a[:5]
//从第5个开始截取,遇到索引为10停下来(不包含索引10)
s2 = a[5:10]
//取完整数组
s1 = [:]
}
Slice与底层数组的对应关系
实例1:
package main
import "fmt"
func main() {
var s1 []int
fmt.Println(s1)
}
//[]
实例2:
package main
import "fmt"
func main() {
a := [10]int{}
fmt.Println(a)
s1 := a[5:10]//5:10 表示从索引5开始,不包含索引10结尾
fmt.Println(s1)
}
//[0 0 0 0 0 0 0 0 0 0]
//[0 0 0 0]
s1 := a[5:]//5:0 表示从5开始取到0
fmt.Println(s1)
//[0 0 0 0 0 0 0 0 0 0]
//[0 0 0 0 0]
s1 := a[:5]//5:0 表示不包含索引为5
fmt.Println(s1)
实例3:
s1 = make([]int,长度,初始容量)
- 不设置初始容量,默认为指定长度的容量
- 当长度在初始容量内,不需要重新分配内存
- 当长度超过初始容量,会分配给2倍初始容量的内存(分配内存很耗性能)
s1 = make([]int,10,10),容量被占满,如果再给s1增加元素,容量自动翻倍为20,此时s1 = make([]int,11,20)
package main
import "fmt"
func main() {
s1 := make([]int,3,10)
fmt.Println(len(s1),cap(s1))
}
//3 10
//len长度、cap容量
s1 := make([]int,3)
fmt.Println(len(s1),cap(s1))
//3 3
实例4:
package main
import "fmt"
func main() {
//s1 := make([]int,3)
//fmt.Println(len(s1),cap(s1))
a := []byte{'a','b','c','d','e','f','g','h','i','j','k'}
sa := a[2:4]
sb := a[2:5]
sc := a[:]//表示完整的数组
fmt.Println(sa)
fmt.Println(string(sa))
fmt.Println(string(sb))
}
//[99 100]
//cd
//cde
实例5:
Reslice
Reslice时索引以被slice的切片为准
索引不可以超过被slice的切片的容量cap()值
索引越界不会导致底层数组的重新分配而是引发错误
package main
import "fmt"
func main() {
//s1 := make([]int,3)
//fmt.Println(len(s1),cap(s1))
a := []byte{'a','b','c','d','e','f','g','h','i','j','k'}
sa := a[2:4]
fmt.Println(len(sa),cap(sa))
sb := a[2:5]
fmt.Println(sa)
fmt.Println(string(sa))
fmt.Println(string(sb))
}
//2 9
//[99 100]
//cd
//cde
越界
package main
import "fmt"
func main() {
//s1 := make([]int,3)
//fmt.Println(len(s1),cap(s1))
a := []byte{'a','b','c','d','e','f','g','h','i','j','k'}
//c、d
sa := a[2:4]
//3、9 容量为9
//体现:Reslice时索引以被slice的切片为准
fmt.Println(len(sa),cap(sa))
//c、d、e
sb := a[2:5]
fmt.Println(sa)
fmt.Println(string(sa))
fmt.Println(string(sb))
//索引不可以超过被slice的切片的容量cap()值
sc := sa[9:11]
println(string(sc))
}
//2 9
//[99 100]
//cd
//cde
//panic: runtime error: slice bounds out of range
goroutine 1 [running]:
main.main()
/Users/care/go/src/awesomeProject/slice2.go:16 +0x2ba
exit status 2
Append
可以在slice尾部追加元素
可以将一个slice追加在另一个slice尾部
如果最终长度未超过追加到slice的容量则返回原始slice的内存和新的slice
如果超过追加到的slice的容量则将重新分配数组并拷贝原始数据
实例1:
可以在slice尾部追加元素
可以将一个slice追加在另一个slice尾部
如果最终长度未超过追加到slice的容量则返回原始slice的内存和新的slice
package main
import "fmt"
func main() {
s1 := make([]int,3,6)
fmt.Printf("%p\n",s1)
s1 = append(s1,1,2,3)
fmt.Printf("%v %p\n",s1,s1)
}
//0xc00001a090
//[0 0 0 1 2 3] 0xc00001a090
//如果超过追加到的slice的容量则将重新分配数组并拷贝原始数据
func main() {
s1 := make([]int,3,6)
fmt.Printf("%p\n",s1)
s1 = append(s1,1,2,3)
fmt.Printf("%v %p\n",s1,s1)
s1 = append(s1,1,2,3)
fmt.Printf("%v %p\n",s1,s1)
}
//0xc00001a0f0
//[0 0 0 1 2 3] 0xc00001a0f0
//[0 0 0 1 2 3 1 2 3] 0xc000086000
实例2:
slice指向一个底层数组,一个改变,另一个也跟着改变
package main
import "fmt"
func main() {
a:= []int{1,2,3,4,5,6}
s1 := a[2:5]
s2 := a[1:3]
fmt.Println(s1,s2)
s1[0] = 9
fmt.Println(s1,s2)
}
//slice指向一个底层数组,一个改变,另一个也跟着改变
//[3 4 5] [2 3]
//[9 4 5] [2 9]
func main() {
a:= []int{1,2,3,4,5,6}
s1 := a[2:5]
s2 := a[1:3]
fmt.Println(s1,s2)
s2 = append(s2,1,2,3,4,5,6,7,8,9)
s1[0] = 9
fmt.Println(s1,s2)
}
//原先s1和s2底层共同指向数组a,s2数组超过长度重新分配内存,所以改变s1的值,s2不受影响
//[3 4 5] [2 3]
//[9 4 5] [2 3 1 2 3 4 5 6 7 8 9]
Copy
copy(s1,s2) 把s2复制到s1
实例:
package main
import "fmt"
//s2复制到s1
func main() {
s1 := []int{1,2,3,4,5,6}
s2 := []int{7,8,9}
//copy(s1,s2)
fmt.Println(s1)
//把s2复制到s1
//[7 8 9 4 5 6]
}
//s1复制到s2
func main() {
s1 := []int{1,2,3,4,5,6}
s2 := []int{7,8,9}
copy(s2,s1)
fmt.Println(s2)
//把s1复制到s2
//[1 2 3]
}
cpoy一部分
实例:
package main
import "fmt"
func main() {
s1 := []int{1,2,3,4,5,6}
s2 := []int{7,8,9,10,1,1,1,1,1}
copy(s2,s1[1:3])
fmt.Println(s2)
}
//[2 3 9 10 1 1 1 1 1]
copy(s2[2:4],s1[1:3])
fmt.Println(s2)
//[7,8,2,3,1,1,1,1,1]
课堂作业
如何将一个slice指向一个完整的底层数组,而不是底层数组的一部分?
s2 := s1
s2 := s1[:]
本作品采用《CC 协议》,转载必须注明作者和本文链接