slice
slice不是数组或数组指针,它是通过内部指针和相关属性引用数组片段,以实现边长方案
slice引用类型,但自身是结构体,值拷贝传递
//在runtime.h中的源码
struct slice
{
byte* array;
uintgo len; //表示可用元素数量,读写操作不能超过该限制
uintgo cap; //表示最大扩张容量,不能超出数组限制
}
slice使用方式[a:b:c],a表示从a位置开始,b表示到b位置结束,c表示最大位置是c,len=b-a,cap=c-a
package main
import "fmt"
func main() {
data := [...]int{0, 1, 2, 3, 4, 5, 6}
slice := data[1:4:5]
fmt.Println(slice) //[1 2 3]
}
slice使用举例
package main
import "fmt"
func main() {
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := data[:6:8]
slice1 := data[5:]
slice2 := data[:3]
slice3 := data[:]
fmt.Println(slice, slice1, slice2, slice3) //[0 1 2 3 4 5] [5 6 7 8 9] [0 1 2] [0 1 2 3 4 5 6 7 8 9]
}
slice读写操作实际目标是底层数组,只需要注意索引号的差别
package main
import "fmt"
func main() {
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
slice := data[6:8]
slice[0] += 100
slice[1] += 200
fmt.Println(slice) //[106 207]
fmt.Println(data) //[0 1 2 3 4 5 106 207 8 9]
}
直接创建slice对象,自动分配底层数组
package main
import "fmt"
func main() {
data := [...]int{0, 1, 2, 3, 8:100}
fmt.Println(data, len(data), cap(data)) //[0 1 2 3 0 0 0 0 100] 9 9
s2 := make([]int, 6, 8)
fmt.Println(s2, len(s2), cap(s2)) //[0 0 0 0 0 0] 6 8 没有初始化值,直接用0填充
s3 := make([]int, 6)
fmt.Println(s3, len(s3), cap(s3)) //[0 0 0 0 0 0] 6 6 省略cap那么久默认cap=len
}
可以用指针直接访问底层数组,退化成普通数组操作
package main
import "fmt"
func main() {
s := []int{0, 1, 2, 3, 4}
p := &s[2] //直接使用指针修改数组底层的值
*p += 100
fmt.Println(s)
}
依然是二维数组
package main
import "fmt"
func main() {
data := [][]int{
[]int{1, 2, 3},
[]int{100, 200},
[]int{11, 22, 33, 44},
}
fmt.Println(data) //[[1 2 3] [100 200] [11 22 33 44]]
}
可直接修改struct array成员
package main
import "fmt"
func main() {
d := [5]struct {
x int
}{}
s := d[:] //这里是引用
d[1].x = 10
s[2].x = 20
fmt.Println(d) //[{0} {10} {20} {0} {0}]
fmt.Printf("%p, %p\n", &d, &d[0]) //0xc4200720c0, 0xc4200720c0
}