文章目录
- 介绍
- 使用
- 创建
- 扩容
- 复制
- 删除
- 遍历
- 扩展
- 证明切片是基于数组封装的
- 内存地址变化的几种情况
- 如何判断切片为空
- 练习 - sort排序
介绍
- 元素类型相同
- 序列长度可变(底层实现是通过新建新数组), 支持自动扩容, 尽量避免使用
- 引用类型
- 三要素
- 地址: 切片中第一个元素的内存地址 -> %p
- 大小: 切片中当前元素的数量 -> len()
- 容量: 切片中可容纳元素的数量 -> cap()
使用
创建
package main
import "fmt"
func main() {
// 先声明, 再赋值
var sliceA []int
alice = []int{1, 2, 3}
// 推导赋值
var sliceB = []int{1, 2, 3}
//
sliceC := []int{} // 长度和容量都为 0, 输入无法写入
// 由数组获得切片, 此时的切片容量为索引起始值到数组末尾的元素数量, 索引不可超过界限
arr := [3]int{1,2,3} // 创建数组
sliceD := arr [:]
// 切片再切片, 索引不可超过界限
sliceE := sliceD [1:]
// make构造一个切片, 长度为0, 容量为3
sliceF := make([]int, 0, 3) // 无法使用索引赋值
}
扩容
- 使用 append 方法
- 底层重建数组
- 扩容的策略
- 通常情况下, 为当前容量的两倍
- 若增加的容量超过原容量的一倍, 容量=原容量+扩容容量, 遇到奇数+1
package main
import "fmt"
func main() {
// 验证扩容后, 内存地址会发生变化
a := make([]int, 0, 0)
for i := 0; i < 5; i++ {
// 使用append进行扩容, append(数组, 元素1, 元素2..)
aa = append(aa, 1)
fmt.Printf("aa长度为: %v; 容量为: %v; ptr为: %p\n", len(aa), cap(aa), aa)
}
}
复制
package main
import "fmt"
func main() {
// 由于切片是引用类型, 所以需要copy方法(深拷贝)
a := []int{1,2,3}
// 验证引用类型
b := a
b[0] = 100
fmt.Println(a, b) // 结果为: [100, 2, 3] [100, 2, 3]
// 深拷贝复制
c := make([]int, len(a), cap(a)) // 构建一个容量和长度和 a 相同的切片
copy(c, a)
a[0] = 100
fmt.Println(a, c) // [1, 2, 3] [100, 2, 3]
}
删除
package main
import "fmt"
func main() {
// 使用append将删除元素前后连接起来
// append用法: slice = append(slice[start:end], ele1, ele2...)
a := []int{1,2,3,4,5}
b = append(a[0:2], 4, 5)
// ...的用法, 表示将切片打散为多个单一元素
c = append(a[0:2], a[3:]...) // a[3:]... 例子中为4, 5
}
遍历
package main
import "fmt"
func main() {
a := []int{1,2,3}
for k,v := range a {
fmt.Println(k,v) // k 为索引, v 为值
}
}
扩展
证明切片是基于数组封装的
a := [...]int{1,2,3,4}
b := a[:] // 得到切片
// 对比两个内存地址, 相同则证明切片是基于数组进行封装的
fmt.Printf("%p", &a) // & 用于得到值类型的内存地址
fmt.Printf("%p", b) // 引用类型不需要&
内存地址变化的几种情况
a := [...]int{1,2,3,4}
b := a[:] // 得到切片
// 1. 当第一个元素的内存地址发生变化
c := b[1:]
fmt.Printf("%p", c) // 与a b的内存地址做对比
// 2. 容量发生变化
d := append(b, 6, 7)
fmt.Printf("%p", d) // 与a b的内存地址做对比
如何判断切片为空
package main
import "fmt"
func main() {
// 用 3 种方法创建切片, 结果如下
var a []int // [], 0, 0
b := []int{} // [], 0, 0
c := make([]int, 0, 100) // [], 0, 100
// 但只有第一种方法创建时, 值实际为 nil
// 所以len(slice) == 0 时, 切片为空
}
练习 - sort排序
package main
import "fmt"
func main() {
// 使用 sort.Ints(slice)
a := []int{1, 9, 8, 2, 3, 7, 6, 5, 4}
// 使用sort对切片进行排序, 改变原切片
sort.Ints(a)
fmt.Println(a)
}