这一节,咱们来讨论更多关于Slice
的用法。golang
nil
切片与空切片nil
切片var s []int
fmt.Println(s == nil) // 输出 true
fmt.Println(len(s),cap(s)) // 输出:0 0
复制代码
上面这段代码声明了一个nil
切片s
,其实,切片的零值就是nil
。为何?经过上一节咱们知道,由于切片就是一个数组的引用。切片的类型在初始化时已经确认,就是[]Type
,上面的代码就声明了[]int
类型的nil
切片s
。nil
切片的指向底层数组的指针为nil
。数组
如何声明空切片?有两种方式:架构
// 一、使用 make 建立空的整型切片
s := make([]int, 0)
// 二、使用切片字面量建立空的整型切片
s := []int{}
fmt.Println(s) // 输出:[]
fmt.Println(len(s),cap(s)) // 输出:0 0
复制代码
经过上面代码能够得出,与nil
切片同样,空切片的长度和容量也都是0,说明切片底层的数组大小为0,是一个空数组(没有分配任何的存储空间)。app
无论是使用
nil
切片仍是空切片,对其调用内置函数append
、len
和cap
的效果都是同样的。函数
copy
函数Go提供了内置函数copy
,能够讲一个切片复制到另外一个切片。函数原型:post
func copy(dst, src []Type) int 复制代码
dst
是目标切片,src
是源切片,函数返回二者长度的最小值。学习
var s1 []int
s2 := []int{1, 2, 3}
s3 := []int{4, 5, 6, 7}
s4 := []int{1, 2, 3}
// 一、
n1 := copy(s1, s2)
fmt.Printf("n1=%d, s1=%v, s2=%v\n", n1, s1, s2)
fmt.Println("s1 == nil", s1 == nil)
// 二、
n2 := copy(s2, s3)
fmt.Printf("n2=%d, s2=%v, s3=%v\n", n2, s2, s3)
// 三、
n3 := copy(s3, s4)
fmt.Printf("n3=%d, s3=%v, s4=%v\n", n3, s3, s4)
复制代码
输出:ui
n1=0, s1=[], s2=[1 2 3]
s1 == nil true
n2=3, s2=[4 5 6], s3=[4 5 6 7]
n3=3, s3=[1 2 3 7], s4=[1 2 3]
复制代码
上面代码生声明了nil
切片s1
和三个非空切片s2
、s3
和s4
。从第一块代码块能够看到,由于s1
是nil
切片,执行完copy
操做以后,s1
依然仍是nil
。这有别于append
函数:spa
var s1 []int
s2 := []int{1, 2, 3}
s1 = append(s1, s2...)
fmt.Println(s1) // 输出:[1 2 3]
复制代码
第二段代码:因为s2
的长度是3,s3
的长度是4,因此执行copy
操做只会从s3
复制3个元素至s2
。copy
只会复制,不会追加。 第三段代码也是一样的道理。.net
切片在函数间以值的方式传递。因为切片的尺寸很小(在 64 位架构的机器上,一个切片须要 24 字节的内存:指针字段、长度和容量字段各须要 8 字节),在函数间复制和传递切片成本也很低。切片发生复制时,底层数组不会被复制,数组大小也不会有影响。
func main() {
s := []int{0, 1, 2, 3, 4, 5}
fmt.Printf("%p\n", &s)
modify(s)
fmt.Println(s)
}
func modify(s []int) {
fmt.Printf("%p\n", &s)
s[1] = 10
}
复制代码
输出:
0xc000086020
0xc000086040
[0 10 2 3 4 5]
复制代码
咱们能够看到,原切片地址和传递以后的切片的地址是不同的,说明发生了复制;在函数modify
中修改了切片一个值,原切片的值也随之改变了,说明这两个切片是共享底层数组的。 在函数间传递切片很是高效,并且不须要传递指针和处理复杂的语法,只须要复制切片,按本身的业务修改数据,最后传递回一个新的切片副本便可,这也是为何函数间使用切片传参,而不是数组传参的缘由。
Go没有提供删除切片元素的函数,然而,咱们可使用一些“黑科技”达到这样的目的。
s := []int{1, 2, 3, 4, 5, 6}
s = append(s[:2], s[3:]...) // 删除索引为2的元素
fmt.Println(s)
复制代码
输出:
[1 2 4 5 6]
复制代码
经过这两节详解,相信你已经掌握了Slice
,建议你们要多多练习!
原创文章,若需转载请注明出处!
欢迎扫码关注公众号「Golang来啦」或者移步 seekload.net ,查看更多精彩文章。
公众号「Golang来啦」给你准备了一份神秘学习大礼包,后台回复【电子书】领取!