切片slice
package main
import (
"fmt"
)
func main() {
var s1 []int //这样的话就完成了slice的声明,如果是数组的话,必须在中括号当中必须有明确的数字或3个点
fmt.Println(s1)
}
- 作为变成数组的替代方案,可以关联底层数组的局部或全部
package main
import (
"fmt"
)
func main() {
var s1 []int //这样的话就完成了slice的声明,如果是数组的话,必须在中括号当中必须有明确的数字或3个点,这是个空slice
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
fmt.Println(s1)
fmt.Println(a)
s2 := a[9]
s3 := a[5:10] //a[5,6,7,8,9],也可以写成a[5:]
fmt.Println(s2)
fmt.Println(s3)
}
- 它的值为引用类型、
- 可以直接创建或从底层数组获取生成
- 使用len()获取元素个数,cap()获取容量
- 一般情况下使用make创建
package main
import (
"fmt"
)
func main() {
s1 := make([]int, 3, 10) //括号中第一个参数是类型,第二个参数是长度,第三个是容量,如果不设置容量,它就会认为默认是你的长度
fmt.Println(len(s1), cap(s1))
}
- 如果多个slice指向相同底层数组,其中一个的值改变会影响全部
- make([]T,len,cap)
- 其中cap可以省略,则和len的值相同
- len表示存在的元素个数,cap表示容量
slice与底层数组对应的关系
package main
import (
"fmt"
)
func main() {
a := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
sa := a[2:5]
fmt.Println(sa)
sb := a[3:5]
fmt.Println(sb)
}
Reslice
- Reslice时索引以被slice的切片为准
- 索引不可以超过slice的切片的容量cap()值
- 索引越界不会导致底层数组的重新分配而是引发错误
package main
import (
"fmt"
)
func main() {
a := [...]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
sa := a[2:5]
fmt.Println(sa)
//这里的sa指向的是一个连续的内存块,所以它的最大容量到这个内存块的底部
fmt.Println(len(sa), cap(sa))
sb := sa[1:3]
fmt.Println(sb)
fmt.Println(len(sb), cap(sb))
}
//PS结果:
PS G:\mygo\src\mytest> go run .\myfirst.go
[c d e]
3 9
[d e]
2 8
Append
- 可以在slice尾部追加元素
- 可以将一个slice追加在另一个slice尾部
- 如果最终长度未超过追加到slice的容量则返回原始slice
- 如果超过追加的slice的容量则将重新分配数组并拷贝原始数据
package main
import (
"fmt"
)
func main() {
s1 := make([]int, 3, 6)
fmt.Printf("%v, %p \n", s1, s1)
s1 = append(s1, 1, 2, 3)
fmt.Printf("%v, %p \n", s1, s1)
//可以看到两次打印的内存地址是一样的,因为追加的元素没有超出原slice的容量
}
PS G:\mygo\src\mytest> go run .\myfirst.go
[0 0 0], 0xc04203ff50
[0 0 0 1 2 3], 0xc04203ff50
package main
import (
"fmt"
)
func main() {
s1 := make([]int, 3, 6)
fmt.Printf("%v, %p \n", s1, s1)
s1 = append(s1, 1, 2, 3)
fmt.Printf("%v, %p \n", s1, s1)
//可以看到两次打印的内存地址是一样的,因为追加的元素没有超出原slice的容量
s1 = append(s1, 4, 5, 6)
fmt.Printf("%v %p \n", s1, s1)
//此时可以看出,最后一次的打印会重新分配内存地址
}
PS G:\mygo\src\mytest> go run .\myfirst.go
[0 0 0], 0xc04203ff50
[0 0 0 1 2 3], 0xc04203ff50
[0 0 0 1 2 3 4 5 6] 0xc04203a0c0
package main
import (
"fmt"
)
func main() {
a := []int{1, 2, 3, 4, 5}
s1 := a[2:5]
s2 := a[1:3]
fmt.Println(s1, s2)
s1[0] = 9
fmt.Println(s1, s2) //slice是指向一个底层的数组,当多个slice指向同一个底层的数组的时候,其中一个发生改变,另外的slice都会发生改变
}
PS G:\mygo\src\mytest> go run .\myfirst.go
[3 4 5] [2 3]
[9 4 5] [2 9]
package main
import (
"fmt"
)
func main() {
a := []int{1, 2, 3, 4, 5}
s1 := a[2:5]
s2 := a[1:3]
fmt.Println(s1, s2)
s2 = append(s2, 3, 4, 5, 6, 7, 8, 9, 10) //当append的容量超过底层数组的长度时,会重新分配内存地址并拷贝原始数据
s1[0] = 9
fmt.Println(s1, s2) //slice是指向一个底层的数组,当多个slice指向同一个底层的数组的时候,其中一个发生改变,另外的slice都会发生改变
}
PS G:\mygo\src\mytest> go run .\myfirst.go
[3 4 5] [2 3]
[9 4 5] [2 3 3 4 5 6 7 8 9 10]
Copy
package main
import "fmt"
func main() {
s1 := []int{1, 2, 3, 4, 5, 6}
s2 := []int{7, 8, 9}
copy(s1, s2) //将S2赋值到s1当中
fmt.Println(s1, s2)
}
PS G:\mygo\src\mytest> go run .\mysecond.go
[7 8 9 4 5 6] [7 8 9]
package main
import "fmt"
func main() {
s1 := []int{1, 2, 3, 4, 5, 6}
s2 := []int{7, 8, 9}
s3 := s1[:] //将s1完整的拷贝给s3
fmt.Println(s1, s2)
fmt.Println(s3)
fmt.Printf("%p---%p \n", s1, s3)
}
PS G:\mygo\src\mytest> go run .\mysecond.go
[1 2 3 4 5 6] [7 8 9]
[1 2 3 4 5 6]
0xc04203ff50---0xc04203ff50