Go语言切片Slice的使用
作者:互联网
1、来源于数组的切片
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //添加了...表示数组
b := a[2:6] //切片
fmt.Println(b) //[3 4 5 6] 左包右不包
}
可以省略开始,可以省略结束,可以省略开始和结束
package main
import "fmt"
func main() {
a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //数组
b := a[2:6] //切片
fmt.Println(b) //[3 4 5 6] 左包右不包
c := a[:6] //可以省略开始
fmt.Println(c) //[1 2 3 4 5 6]
d := a[2:] //可以省略结束
fmt.Println(d) //[3 4 5 6 7 8]
e := a[:] //可以省略开始和结束
fmt.Println(e) //[1 2 3 4 5 6 7 8]
}
2、切片slice是数组的视图
改变切片的元素,底层数组也会改变
package main
import "fmt"
func update(a []int) {
a[0] = 100
a[1] = 1000
}
func main() {
a := [...]int{1, 2, 3, 4, 5, 6, 7, 8} //数组
b := a[2:6] //切片是数组的视图 查看数组的第2到第6个元素
fmt.Println(b) //[3 4 5 6] 左包右不包
src := a[:] //底层数组a的全部视图
fmt.Println(fmt.Sprintf("原始的底层数组全视图是:%d", src))
update(src)
fmt.Println(fmt.Sprintf("改变了切片后的底层数组全视图是:%d", src))
fmt.Println(fmt.Sprintf("原始的底层数组是:%d", a))
}
3、slice可以继续reslice
package main
import "fmt"
func update(a []int) {
a[0] = 100
a[1] = 1000
}
func main() {
a := []int{1, 2, 3, 4, 5, 6, 7, 8} //[]中没有...代表切片
b := a[2:7] //切片可以再次切片,称为reslice
fmt.Println(b) //[3 4 5 6 7]
c := b[3:]
fmt.Println(c) //[6 7]
d := c[:1]
fmt.Println(d) //[6]
}
4、slice会向底层看齐
如果切片时,切片到头了,则会向底层查看一下是否还有可视的值,因为切片是数组的视图,所以最终会视图到最底层的数组,例如
package main
import "fmt"
func main() {
arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
fmt.Println(fmt.Sprintf("底层数组:%d", arr))
s1 := arr[2:6]
fmt.Println(fmt.Sprintf("arr[2:6]:%d", s1))
// s1 是 [3 4 5 6] 如果再对s1取3:5,则会出来什么呢
s2 := s1[3:5]
fmt.Println(fmt.Sprintf("s1[3:5]:%d", s2))
//会出来[6 7] 6是来自于切片s2 而7是来自于底层数组arr
}
可以看出s1都没有s1[4]而s2取出来了7,这是由于视图向下看,看到了底层数组的7
说明:
数组arr是1,2,3,4,5,6,7,8
s1 := arr[2:6] 是取数组的第三个元素,总共取4个元素,就是3,4,5,6,但是s1是知道数组arr还有7,8两个元素,因为s1是数组的视图
s2 := s1[3:5]是取s1的第四个元素,总共去2个元素,第一个元素就是6,但是第二个元素在s2中没有了,如果打印s2[4]则会报错,但是因为是视图,s1是知道后面的元素是7,8,因此第二个元素就可以取到7,如果再取一个元素,那就是可以取到8,如果再取一个,因为底层数组到8便没有了,因此抛出异常
5、切片slice的底层数据结构
说明
①slice由ptr和len以及cap组成
②ptr
是指针,指向切片的第一个元素
③len
是切片的长度,从ptr开始到结束的元素个数,当下标 超过这个长度后会报下标越界的错误
④cap
表示切片的容量,表示共可以存多少个元素,当添加元素后,如果容量不够,会自动扩容
⑤slice可以向后扩展,不可以向前扩展,扩展可以超过len的值,但不能超过底层数组的cap
打印切片的len和cap
package main
import "fmt"
func main() {
arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
fmt.Println(fmt.Sprintf("底层数组:%d", arr))
s1 := arr[2:6]
fmt.Println(fmt.Sprintf("arr[2:6]:%d, len:%d, cap:%d", s1, len(s1), cap(s1)))
// s1 是 [3 4 5 6] 如果再对s1取3:5,则会出来什么呢
s2 := s1[3:5]
fmt.Println(fmt.Sprintf("s1[3:5]:%d, len:%d, cap:%d", s2, len(s2), cap(s2)))
//会出来[6 7] 6是来自于切片s2 而7是来自于底层数组arr
}
6、slice添加元素
使用append添加元素,添加的元素会紧跟在后面,添加后多余cap的数据会被挤出去
append方式作用于底层数组
package main
import "fmt"
func main() {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 6 7]
s1 := arr[2:6]
fmt.Println(fmt.Sprintf("s1:%d", s1)) //[2 3 4 5]
s2 := s1[3:4]
fmt.Println(fmt.Sprintf("s2:%d", s2)) //[5]
s3 := append(s2, 10)
fmt.Println(fmt.Sprintf("s3:%d", s3)) //[5 10]
// 由于s2是[5] append后10直接跟着5后面,把6给直接顶掉了
//因为slice是底层数组的view,即是底层数组的视图,所以append作用于底层数组
//底层中的5后面的数6就被10给替换了
fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 10 7]
s4 := append(s3, 11) //[5 10 11]
fmt.Println(fmt.Sprintf("s4:%d", s4))
//由于s3是[5 10],直接append一个11,因此11直接跟在10后面,原来底层数组10后面是7,因此把7给替换成了11
fmt.Println(fmt.Sprintf("底层数组:%d", arr)) //[0 1 2 3 4 5 10 11]
s5 := append(s4, 12) //[5 10 11 12]
fmt.Println(fmt.Sprintf("s5:%d", s5))
//由于s4是[5 10 11]直接append一个12,因此12直接跟在11后面,但是由于再跟一个12,就超过了底层数组的cap,因此会产生一个新的地址存放新的数据
//如果用debug的方式查看,就能看到产生了新的地址存放新的数组
fmt.Println(fmt.Sprintf("底层数组:%d", arr))
}
debug方式查看新的地址存放新数据
7、slice的几种创建方式
- var定义slice
package main
import "fmt"
func main() {
var s []int//申明切片s,默认是nil
fmt.Println(fmt.Sprintf("var 定义的 slice默认值:%v", s))
for i := 0; i < 100; i++ {
s = append(s, i)//通过append方式添加元素
fmt.Println(fmt.Sprintf("len:%d cap:%d, value:%d", len(s), cap(s), s))
}
//可以看到cap会默认自己扩张
}
- 冒号:定义slice
package main
import "fmt"
func main() {
s := []int{2, 4, 6, 8, 10}
fmt.Println(fmt.Sprintf("len:%d, cap:%d, value:%d", len(s), cap(s), s))
}
- make关键字创建slice
如果想创建某个长度的slice可以使用make函数
例如:我想创建cap为10的slice,但我只知道其中5个
package main
import "fmt"
func main() {
s := make([]int, 5, 10)
s[0] = 10
s[1] = 1
s[2] = 10
s[3] = 1
s[4] = 10
fmt.Println(fmt.Sprintf("len:%d, cap:%d, value:%d", len(s), cap(s), s))
}
- copy关键字创建slice
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 5}
fmt.Println(s)
s1 := []int{0, 0, 0}//[1 2 3 5] [1 2 3]
copy(s1, s)
fmt.Println(s, s1)
}
8、删除slice元素
删除中间的元素
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
fmt.Println(s)
s1 := append(s[:2], s[3:]...)//移除3
fmt.Println(s1)
}
删除首元素
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
fmt.Println(s)
s1 := s[1:]
fmt.Println(s1)
}
删除尾巴元素
package main
import (
"fmt"
)
func main() {
s := []int{1, 2, 3, 4, 5}
fmt.Println(s)
s1 := s[:len(s)-1]
fmt.Println(s1)
}
标签:Slice,fmt,切片,Println,Sprintf,数组,Go,main,s1 来源: https://www.cnblogs.com/rainbow-tan/p/16372568.html