切片介绍
切片:是一个很小的对象,对底层数组进行了抽象,并提供相关的操作方法。切片有 3 个字段的数据结构,这些数据结构包含 Go 语言需要操作底层数组的元数据
切片创建
package main
import (
"log"
)
type Fruit struct {
Fenshu int
Zhuid int
}
var slice9 []Fruit
func Demo01() {
slice := make([]string, 5)
log.Println(slice)
slice2 := make([]int, 3, 5)
log.Println(slice2)
slice3 := []string{"Red", "Blue", "Green", "Yellow", "Pink"}
log.Println(slice3)
slice4 := []string{99: "0"}
log.Println(slice4)
var slice5 []int
log.Println(slice5)
slice6 := slice4[1:2]
log.Println(slice6)
slice7 := make([]int, 0)
log.Println(slice7)
slice8 := []int{}
log.Println(slice8)
slice9 = make([]Fruit, 24)
log.Println(slice9)
}
func main() {
Demo01()
}
切片赋值
对切片里某个索引指向的元素赋值和对数组里某个索引指向的元素赋值的方法完全一样。
package main
import (
"log"
)
type Fruit struct {
Fenshu int
Zhuid int
}
func Demo01() {
slice := make([]string, 5)
slice[0] = "test"
log.Println(slice)
slice1 := []int{10, 20, 30}
log.Println(slice1)
slice2 := make([]Fruit, 3)
slice2 = []Fruit{
Fruit{15, 4},
Fruit{50, 8}}
log.Println(slice2)
}
func main() {
Demo01()
}
切片遍历
遍历整个切片并且添加打印
package main
import (
"log"
)
type Fruit struct {
Fenshu int
Zhuid int
}
func Demo01() {
slice2 := make([]Fruit, 10)
slice2 = []Fruit{
Fruit{1, 14},
Fruit{2, 24},
Fruit{3, 34},
Fruit{4, 44},
Fruit{5, 54},
Fruit{6, 64},
Fruit{7, 74},
Fruit{8, 84},
Fruit{9, 94},
Fruit{10, 104},
Fruit{11, 208}}
log.Println(slice2)
for index, value := range slice2 {
log.Printf("index:%d", index)
log.Println(value)
}
}
func main() {
Demo01()
}
当迭代切片时,关键字 range 会返回两个值。第一个值是当前迭代到的索引位置,第二个
值是该位置对应元素值的一份副本
切片传递
在函数间传递切片就是要在函数间以值的方式传递切片。由于切片的尺寸很小,在函数间复
制和传递切片成本也很低。让我们创建一个大切片,并将这个切片以值的方式传递给函数 foo,
package main
import (
"log"
)
func foo(slice []int) []int {
log.Println(slice)
slice[1] = 200
return slice
}
func main() {
slice := make([]int, 10)
log.Println(slice)
slice[0] = 100
foo(slice)
log.Println(slice)
}
2018/02/07 13:41:06 [0 0 0 0 0 0 0 0 0 0]
2018/02/07 13:41:06 [100 0 0 0 0 0 0 0 0 0]
2018/02/07 13:41:07 [100 200 0 0 0 0 0 0 0 0]
可以看出我们操作的是一个切片。
在 64 位架构的机器上,一个切片需要 24 字节的内存:指针字段需要 8 字节,长度和容量字段分别需要 8 字节。由于与切片关联的数据包含在底层数组里,不属于切片本身,所以将切片复制到任意函数的时候,对底层数组大小都不会有影响。复制时只会复制切片本身,不会涉及底层数组
在函数间传递 24 字节的数据会非常快速、简单。这也是切片效率高的地方。不需要传递指针和处理复杂的语法,只需要复制切片,按想要的方式修改数据,然后传递回一份新的切片副本。
切片截取/取长度len()/容量cap()
package main
import "log"
func main() {
var numbers = make([]int, 3, 5)
printSlice(numbers)
}
func printSlice(x []int) {
log.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}
打印:
len=3 cap=5 slice=[0 0 0]
package main
import "log"
func main() {
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
printSlice(numbers)
log.Println("numbers ==", numbers)
log.Println("numbers[1:4] ==", numbers[1:4])
log.Println("numbers[:3] ==", numbers[:3])
log.Println("numbers[4:] ==", numbers[4:])
numbers1 := make([]int, 0, 5)
printSlice(numbers1)
number2 := numbers[:2]
printSlice(number2)
number3 := numbers[2:5]
printSlice(number3)
}
func printSlice(x []int) { log.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x) }
打印
2018/02/07 13:51:44 len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
2018/02/07 13:51:44 numbers == [0 1 2 3 4 5 6 7 8]
2018/02/07 13:51:44 numbers[1:4] == [1 2 3]
2018/02/07 13:51:44 numbers[:3] == [0 1 2]
2018/02/07 13:51:44 numbers[4:] == [4 5 6 7 8]
2018/02/07 13:51:44 len=0 cap=5 slice=[]
2018/02/07 13:51:44 len=2 cap=9 slice=[0 1]
切片append() 和 copy()
package main
import "log"
func main() {
var numbers []int
printSlice(numbers)
numbers = append(numbers, 0)
printSlice(numbers)
numbers = append(numbers, 1)
printSlice(numbers)
numbers = append(numbers, 2, 3, 4)
printSlice(numbers)
numbers1 := make([]int, len(numbers), (cap(numbers))*2)
copy(numbers1, numbers)
printSlice(numbers1)
}
func printSlice(x []int) { log.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x) }
控制台
2018/02/07 13:54:22 len=0 cap=0 slice=[]
2018/02/07 13:54:22 len=1 cap=1 slice=[0]
2018/02/07 13:54:22 len=2 cap=2 slice=[0 1]
2018/02/07 13:54:22 len=5 cap=6 slice=[0 1 2 3 4]
2018/02/07 13:54:23 len=5 cap=12 slice=[0 1 2 3 4]
总结:
copy会重新的拷贝一个切片,如果加入的两个数组切片不一样大,就会按其中较小的那个数组切片的元素个数进行复制。
append
主要用于给某个切片(slice)追加元素
如果该切片存储空间(cap)足够,就直接追加,长度(len)变长;如果空间不足,就会重新开辟内存,并将之前的元素和新的元素一同拷贝进去
切片多线程操作
小结
Go 语言里切片经常用来处理数据的集合,映射用来处理具有键值对结构的数据。
内置函数 make 可以创建切片和映射,并指定原始的长度和容量。也可以直接使用切片和映射字面量,或者使用字面量作为变量的初始值。
切片有容量限制,不过可以使用内置的 append 函数扩展容量。
映射的增长没有容量或者任何限制。
内置函数 len 可以用来获取切片或者映射的长度。
内置函数 cap 只能用于切片。
通过组合,可以创建多维数组和多维切片。也可以使用切片或者其他映射作为映射的值。但是切片不能用作映射的键
请发表评论