[GO]切片的使用-4
切片可以理解为动态的数组,可以按需求自动增长或者是缩小,无疑比数组更加灵活多变,首先看下图。
上图中,有3个字段,分别是指向底层数组的指针、切片访问的元素的长度和切片允许增长的元素个数(即容量)。如果当后面的表示0的格子满了,底层的数组就会更换。
切片的创建
1.使用内置的make函数创建
使用make时,需要指定切片的类型、长度与容量大小。package mainimport (
“fmt”
)func main() {
//长度和容量都为5
s1 := make([]int, 5)
fmt.Println(s1)
//长度为3,容量为5
s2 := make([]int, 3, 5)
fmt.Println(s2)}
[0 0 0 0 0]
[0 0 0]
2.容量小于长度将会报错。
package mainimport (
“fmt”
)func main() {
//长度和容量都为5
s1 := make([]int, 5, 3)
fmt.Println(s1)
//长度为3,容量为5}
len larger than cap in make([]int)
3.通过初始化赋值的方式创建切片
这种方式创建,初始的长度与容量会根据初始化提供的元素个数确定,即时满容的。内置函数 len() 和 cap() 可以直接获得切片的长度和容量属性。package mainimport (
“fmt”
)func main() {
s1 := []string{“haha”, “hehe”, “oo”}
fmt.Println(s1, len(s1), cap(s1))
}
[haha hehe oo] 3 3
4.使用索引声明切片
01,02字符串分别初始化第4和3个元素。package mainimport (
“fmt”
)func main() {
s1 := []string{4: “01”, 3: “02”}
fmt.Println(s1, len(s1), cap(s1))
}
[ 02 01] 5 5
nil与空切片
在声明时不做任何的初始化,即创建一个nil切片。package mainimport (
“fmt”
)func main() {
// nil切片
var s1 []int
fmt.Println(s1, len(s1), cap(s1))
//空切片
var s2 []int = make([]int, 0)
fmt.Println(s2, len(s2), cap(s2))
//空切片
s3 := []int{}
fmt.Println(s3, len(s3), cap(s3))
}
[] 0 0
[] 0 0
[] 0 0
切片的使用
1.赋值
如同对数组的索引指向的元素赋值一样。package mainimport (
“fmt”
)func main() {
s1 := []int{1, 2, 3, 4, 5} s1[2] = 11 s1[3] = 99 fmt.Println(s1, len(s1), cap(s1))
}
[1 2 11 99 5] 5 5
2.使用切片来创建切片
package mainimport (
“fmt”
)func main() {
s1 := []int{1, 2, 3, 4, 5} s2 := s1[1:3] fmt.Println(s1, len(s1), cap(s1)) fmt.Println(s2, len(s2), cap(s2))
}
[1 2 3 4 5] 5 5
[2 3] 2 4
当我们有了两个切片,实际上它们共享了同一段底层数组,如图。对于s1我们能知道它的全部容量,但是之后s2就是中间到切片末尾的长度。
起始值和结束值都是可选的。
package main import ( "fmt" ) func main() { s1 := []int{1, 2, 3, 4, 5} s2 := s1[1:] s3 := s1[:3] s4 := s1[:] fmt.Println(s1, len(s1), cap(s1)) fmt.Println(s2, len(s2), cap(s2)) fmt.Println(s3, len(s3), cap(s3)) fmt.Println(s4, len(s4), cap(s4)) } ---------- [1 2 3 4 5] 5 5 [2 3 4 5] 4 4 [1 2 3] 3 5 [1 2 3 4 5] 5 5
3.长度和容量的计算
对于底层数组容量是k的切片s1[i:j]来说长度:j-i
容量:k-i
举例:容量是5的切片s1[1:3]长度:3-1=2
容量:5-1=4
切片增长
1.append向切片增加元素
package mainimport (
“fmt”
)func main() {
s1 := []int{1, 2, 3, 4, 5} //长度为2,容量为4 s2 := s1[1:3] s2 = append(s2, 7) fmt.Println(s2, len(s2), cap(s2))
}
//[2 3 7] 3 4
2.切片追加
前面说了切片是动态的,可以进行增长。若底层数组扩容了,append操作完成后,会拥有一个全新的底层数组。package mainimport (
“fmt”
)func main() {
s1 := []int{1, 2, 3, 4, 5} fmt.Println(s1, len(s1), cap(s1)) s2 := append(s1, 6) fmt.Println(s2, len(s2), cap(s2)) s3 := append(s2, 8) fmt.Println(s3, len(s3), cap(s3))
}
[1 2 3 4 5] 5 5
[1 2 3 4 5 6] 6 10
[1 2 3 4 5 6 8] 7 10
在切片的容量小于1000个元素时,总会成倍的增加容量。一旦超过1000,容量每次增长25%。
3.使用3个索引创建切片
package mainimport (
“fmt”
)func main() {
s1 := []int{1, 2, 3, 4, 5} s2 := s1[2:3:4] fmt.Println(s1, len(s1), cap(s1)) fmt.Println(s2, len(s2), cap(s2))
}
[1 2 3 4 5] 5 5
[3] 1 2
我们可以用之前定义的公式,对于s1[2:3:4]就是s1[i:j:k]
长度:j-i=3-2-1
容量:k-i=4-2=2
切片的遍历
1.for的形式
package mainimport (
“fmt”
)func main() {
s1 := []int{10, 20, 30, 40, 50} for i := 0; i < len(s1); i++ { fmt.Println(i, s1[i]) }
}
0 10
1 20
2 30
3 40
4 50
2.range形式
package mainimport (
“fmt”
)func main() {
s1 := []int{10, 20, 30, 40, 50} for i, v := range s1 { fmt.Println(i, v) }
}
0 10
1 20
2 30
3 40
4 50
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 xiaoxin1218@qq.com
文章标题:[GO]切片的使用-4
文章字数:1.2k
本文作者:周信
发布时间:2019-10-08, 22:42:53
最后更新:2023-05-03, 10:25:35
原始链接:http://zx21.xyz/2019/10/08/GO-切片的使用-4/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。