向Slice中添加元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package main
import "fmt"
func main() { arr := [...]string{"a", "b", "c", "d", "e", "f", "g", "h"} s := arr[2:6] ss := append(s, "xx") sss := append(ss, "yy") ssss := append(sss, "zz") fmt.Println("s", s) fmt.Println("ss", ss) fmt.Println("sss", sss) fmt.Println("ssss", ssss) fmt.Println("arr", arr) }
|
执行结果:
1 2 3 4 5
| s [c d e f] ss [c d e f xx] sss [c d e f xx yy] ssss [c d e f xx yy zz] arr [a b c d e f xx yy]
|
从执行结果中可以看出, 向Slice中append元素后, 会覆盖掉底层Array的值, 会覆盖掉索引为ptr+len(Slice)
的值. 当Slice append后, 超出了cap的长度, 底层Array中已经没有多余的值可以给他覆盖后, 这时, 新的Slice其实已经不再是老的Array的view了, Go语言会在内部创建一个新的Array, 把老数据拷贝过去, 且新的Array的长度会设置的更长一些. 上面的Demo中, ssss已经不再是原始Array的view
当添加元素时, 如果超越了cap, 系统会重新分配更大的底层数组, 原来的Array如果没有被任何对象使用, 将被垃圾回收机制回收
由于Go语言是值传递, 在append后, 必须接收其返回值. 原因是在append操作后, Slice的len肯定会变化, 如果超过了Array长度, cap的值也会变化, 所以需要我们使用新的Slice对象去接收新的返回值
创建Slice
上一篇文章的介绍中, 全篇都使用了Array去创建Slice, 我们可以直接创建Slice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package main
import "fmt"
func printSliceInfo(s []int) { fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) }
func main() { var s []int
for i:=0; i<=59; i++ { printSliceInfo(s) s = append(s, i) } fmt.Println(s) }
|
执行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| len=0 cap=0 len=1 cap=1 len=2 cap=2 len=3 cap=4 len=4 cap=4 len=5 cap=8 len=6 cap=8 len=7 cap=8 len=8 cap=8 len=9 cap=16 len=10 cap=16 len=11 cap=16 len=12 cap=16 len=13 cap=16 len=14 cap=16 len=15 cap=16 len=16 cap=16 len=17 cap=32 len=18 cap=32 len=19 cap=32 len=20 cap=32 len=21 cap=32 len=22 cap=32 len=23 cap=32 len=24 cap=32 len=25 cap=32 len=26 cap=32 len=27 cap=32 len=28 cap=32 len=29 cap=32 len=30 cap=32 len=31 cap=32 len=32 cap=32 len=33 cap=64 len=34 cap=64 len=35 cap=64 len=36 cap=64 len=37 cap=64 len=38 cap=64 len=39 cap=64 len=40 cap=64 len=41 cap=64 len=42 cap=64 len=43 cap=64 len=44 cap=64 len=45 cap=64 len=46 cap=64 len=47 cap=64 len=48 cap=64 len=49 cap=64 len=50 cap=64 len=51 cap=64 len=52 cap=64 len=53 cap=64 len=54 cap=64 len=55 cap=64 len=56 cap=64 len=57 cap=64 len=58 cap=64 len=59 cap=64 [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59]
|
从上面的执行结果可以看出, Go语言会根据使用情况自动去扩展Slice的len以及cap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package main
import "fmt"
func printSliceInfo(s []string) { fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) }
func main() { s := []string{"a", "b", "c"} printSliceInfo(s)
ss := make([]string, 16, 32) printSliceInfo(ss) }
|
执行结果:
1 2
| len=3 cap=3 len=16 cap=32
|
拷贝Slice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import "fmt"
func printSliceInfo(s []int) { fmt.Printf("len=%d cap=%d\n", len(s), cap(s)) }
func main() { s := []int{2015, 5, 9} printSliceInfo(s) fmt.Println("s", s)
ss := make([]int, 4, 8) printSliceInfo(ss) fmt.Println("ss", ss)
copy(ss, s) fmt.Println("ss", ss) }
|
执行结果:
1 2 3 4 5
| len=3 cap=3 s [2015 5 9] len=4 cap=8 ss [0 0 0 0] ss [2015 5 9 0]
|
删除Slice中的元素
对于Slice的删除功能, Go语言没有提供直接的操作语句, 但是可以通过Reslice来实现
需求: 删除Slice中的第3个元素 [12, 34, 56, 78, 90, 89, 72]
思路: 使用Reslice, s[:3] + s[4:] 取得的就是删除原切片第三个元素的数据, 但Go语言也没有提供Slice相加的功能, 只能通过append函数来实现, append(s[:3], s[4:]), 问题又来了, append的源码中要求第二参数必须是可变参数, 也就是一个值一个值的写在后面 func append(slice []Type, elems ...Type) []Type
Go语言中提供了相关的语法, 来解决s[4:]变成可变参数的问题
1 2 3 4 5 6 7 8 9 10 11
| package main
import "fmt"
func main() { s := []int{12, 34, 56, 78, 90, 89, 72} fmt.Println(s)
ss := append(s[:3], s[4:]...) fmt.Println(ss) }
|
执行结果:
1 2
| [12 34 56 78 90 89 72] [12 34 56 90 89 72]
|
删除头尾
删头
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package main
import "fmt"
func main() { s := []int{12, 34, 56, 78, 90, 89, 72} fmt.Println(s)
fmt.Println("Poping from front") front := s[0] ss := s[1:] fmt.Println("取出的头部元素为", front) fmt.Println("取出头部元素后的Slice为", ss) }
|
执行结果:
1 2 3 4
| [12 34 56 78 90 89 72] Poping from front 取出的头部元素为 12 取出头部元素后的Slice为 [34 56 78 90 89 72]
|
删尾
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package main
import "fmt"
func main() { s := []int{12, 34, 56, 78, 90, 89, 72} fmt.Println(s)
fmt.Println("Poping from front") tail := s[len(s)-1] ss := s[:len(s)-1] fmt.Println("取出的尾部元素为", tail) fmt.Println("取出尾部元素后的Slice为", ss) }
|
执行结果:
1 2 3 4
| [12 34 56 78 90 89 72] Poping from front 取出的尾部元素为 72 取出尾部元素后的Slice为 [12 34 56 78 90 89]
|