Golang(4)
切片
原数组存在很多的不足:
- 在方法中申明数组,需要声明长度,故该函数只能接收该长度的数据,其他的都不支持
- 当原数组只能支持指定长度的容量,当容量已满的情况,就不能往数组中添加元素,例如下代码
//1
func arraySum(x [3]int) int{
sum := 0
for _, v := range x{
sum = sum + v
}
return sum
}
//2
a := [3]int{1, 2, 3}
特点
- 切片基于数组的再封装
- 可变长度的序列
- 支持自动扩容
- 为一个引用类型
- 内部包括长度、容量、地址的数据结构
声明
var name []T
package main
import "fmt"
func main() {
var a [] string
var b = []int{1,2,3}
var c = []bool{false,true}
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}
切片表达式
package main
import "fmt"
func main() {
a := [7]int{1, 2, 3, 4, 5, 6, 7}
s := a[4:6] // s := a[low:high]
//s:[5 6] len(s):2 cap(s):3
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
//s:[1 2 3 4 5 6 7] len(s):7 cap(s):7
fmt.Printf("s:%v len(s):%v cap(s):%v\n", a, len(a), cap(a))
}
切片的cap()值可以理解为,切片总长度-左指针位置
使用make()函数构造切片
以上都是基于数组的基础上,进行切片构造操作
还可以通过make函数来动态的进行切片操作
make([]T,size,cap)
//[]T 为元素类型
//size 为元素数量
//cap 为数组容量
切片的原理
切片本质所涵盖的信息为三个:数组指针、长度、容量
判断切片是否为空的方式
判断是否为空的方式:使用len(s) == 0的方式。
错误的方式: s == nil
原因,切片有两种情况:
- 可能s被初始化后,s != nil,但是len(s)和cap(s)均为0
- 可能s未被初始化,s == nil,len(s)和cap(s)均为0
package main
import "fmt"
func main() {
var a []int
b := []int{}
c := make([]int,0,0)
//0 0 true
fmt.Printf("%d\t%d\t%v\n", len(a) , cap(a) ,a==nil)
//0 0 false
fmt.Printf("%d\t%d\t%v\n", len(b) , cap(b) ,b==nil)
//0 0 false
fmt.Printf("%d\t%d\t%v\n", len(c) , cap(c) ,c==nil)
}
拷贝赋值
拷贝前后两个变量共享底层数组,对一个切片的修改会影响另一个切片的内容
package main
import "fmt"
func main() {
s1 := []int{0,0,0}
s2 := s1
s2[0] = 100
//[100 0 0]
fmt.Println(s1)
//[100 0 0]
fmt.Println(s2)
}
切片添加元素append()方法
- 使用append方法时,切片无需初始化
- 此外append还可以添加多个元素或切片
package main
import "fmt"
func main() {
var s []string
s = append(s,"123","3456")
fmt.Println(s)
s1 := []string{"789"}
s = append(s,s1...)
fmt.Println(s)
}
切片扩容逻辑
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}