Post

Day08(切片 slice 和 range)

切片(slice) 和 range 使用

源码

切片(slice

Go 数组在一定情况下,不能满足开发业务需求(数组固定长度、有很多局限性),切片是可变长度序列,切片底层就是数组做了一层封装(也叫做动态数组)。切片可以自动扩容,切片是引用类型,包含地址、长度(len)、容量(cap

切片什么时候扩容

  • 如果切片的容量小于 1024 个元素,那么扩容的时候 slicecap就翻番,乘以 2;一旦元素个数超过 1024 个元素,增长因子就变成 1.25,即每次增加原来容量的四分之一。
  • 如果扩容之后,还没有触及原数组的容量,那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么,Go 就会开辟一块新的内存,把原来的值拷贝过来,这种情况丝毫不会影响到原数组
  • 首先判断,如果新申请容量(cap)大于 2 倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)。
  • 否则判断,如果旧切片的长度小于 1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap),
  • 否则判断,如果旧切片长度大于等于 1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的 1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap
  • 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)。

基本使用

  • 定义方式

指定长度与容量:make([]Type, length, capacity)

指定长度:make([]Type, length)

1
2
3
4
5
6
7
8
9
10
package main

import "github.com/Cc360428/HelpPackage/UtilsHelp/logs"

func main() {
	var slice1 []string
	logs.Info(slice1)
	slice2 := make([]int, 1, 2)
	logs.Info(len(slice2), cap(slice2))
}
1
2
2020/04/24 23:47:25.578 [I] [slice.go:7]  []
2020/04/24 23:47:25.621 [I] [slice.go:9]  1 2
  • 初始化以及切割
1
2
3
a[2:]  // 等同于 a[2:len(a)]
a[:3]  // 等同于 a[0:3]
a[:]   // 等同于 a[0:len(a)]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import "github.com/Cc360428/HelpPackage/UtilsHelp/logs"

func main() {
	s := []int{1, 2, 3}
	logs.Info(s)
	s1 := s[:1]
	logs.Info(s1)
	s2 := s[1:]
	logs.Info(s2)
	s3 := s[1:2]
	logs.Info(s3)
}
1
2
3
4
2020/04/24 23:55:30.339 [I] [slice2.go:7]  [1 2 3]
2020/04/24 23:55:30.366 [I] [slice2.go:9]  [1]
2020/04/24 23:55:30.366 [I] [slice2.go:11]  [2 3]
2020/04/24 23:55:30.366 [I] [slice2.go:13]  [2]
  • len()cap()
1
2
3
4
5
6
7
8
9
10
11
12
package main

import "github.com/Cc360428/HelpPackage/UtilsHelp/logs"

func main() {
	// 定义长度为:1 ,容量为2
	s1 := make([]int, 1, 2)
	logs.Info(len(s1), cap(s1))
	s2 := make([]int,6)
	s1 = append(s1, s2...)
	logs.Info(len(s1), cap(s1))
}
1
2
2020/04/25 00:01:32.871 [I] [slice3.go:8]  1 2
2020/04/25 00:01:32.899 [I] [slice3.go:11]  7 8
  • append()copy()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "github.com/Cc360428/HelpPackage/UtilsHelp/logs"

func main() {
	var s []int
	logs.Info(s, len(s), cap(s))
	s = append(s, 0)
	logs.Info(s, len(s), cap(s))
	s = append(s, 612, 12, 3132, 1024)
	logs.Info(s, len(s), cap(s))
	s2 := make([]int, len(s))
	s2[0] = 888
	s2[1] = 999
	s2[2] = 666
	s = append(s, s2 ...)
	logs.Info(s, len(s), cap(s))
	s3 := make([]int,5)
	copy(s3, s2)
	logs.Info(s3, len(s3), cap(s3))
}
1
2
3
4
5
2020/04/25 00:14:53.179 [I] [slice4.go:7]  [] 0 0
2020/04/25 00:14:53.213 [I] [slice4.go:9]  [0] 1 1
2020/04/25 00:14:53.213 [I] [slice4.go:11]  [0 612 12 3132 1024] 5 6
2020/04/25 00:14:53.213 [I] [slice4.go:17]  [0 612 12 3132 1024 888 999 666 0 0] 10 12
2020/04/25 00:14:53.213 [I] [slice4.go:20]  [888 999 666 0 0] 5 5

删除元素和 sort.Ints()排序

总结一下就是:要从切片 a 中删除索引为 index的元素,操作方法是 a = append(a[:index], a[index+1:]...)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
	"github.com/Cc360428/HelpPackage/UtilsHelp/logs"
	"sort"
)

// 删除索引为2
func main() {
	a := []int{1, 2, 3,9, 5, 6, 7, 8}
	a = append(a[:2], a[3:]...)
	logs.Info(a)
	sort.Ints(a)
	logs.Info(a)
}
1
2
2020/04/25 00:21:05.501 [I] [slice5.go:12]  [1 2 9 5 6 7 8]
2020/04/25 00:21:05.535 [I] [slice5.go:14]  [1 2 5 6 7 8 9]

range

for遍历循环迭代 arrayslicechannelmap

1
2
3
for k ,v := range Type{
    fmt.Println(k,v)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
	"github.com/Cc360428/HelpPackage/UtilsHelp/logs"
)

func main() {
	// array
	array := []int{1, 2, 3, 4}
	for k, v := range array {
		logs.Info(k, v)
	}
	slice := make([]int, 3)
	for k, v := range slice {
		logs.Info(k, v)
	}
	// slice
	channel := make(chan int, 2)
	go func() {
		for i := 1; i <= 3; i++ {
			channel <- 8 * i
		}
		defer close(channel)
		// !close(channel) --> fatal error: all goroutines are asleep - deadlock!
	}()
	// channel
	for k := range channel {
		logs.Info("channel", k)
	}
	// map
	mapType := make(map[string]interface{})
	mapType["name"] = "lcc"
	mapType["age"] = 18
	for k, v := range mapType {
		logs.Info(k, v)
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
2020/04/25 09:47:23.485 [I] [range.go:11]  0 1
2020/04/25 09:47:23.510 [I] [range.go:11]  1 2
2020/04/25 09:47:23.510 [I] [range.go:11]  2 3
2020/04/25 09:47:23.510 [I] [range.go:11]  3 4
2020/04/25 09:47:23.510 [I] [range.go:15]  0 0
2020/04/25 09:47:23.510 [I] [range.go:15]  1 0
2020/04/25 09:47:23.510 [I] [range.go:15]  2 0
2020/04/25 09:47:23.510 [I] [range.go:28]  channel 8
2020/04/25 09:47:23.510 [I] [range.go:28]  channel 16
2020/04/25 09:47:23.511 [I] [range.go:28]  channel 24
2020/04/25 09:47:23.511 [I] [range.go:35]  name lcc
2020/04/25 09:47:23.511 [I] [range.go:35]  age 18
This post is licensed under CC BY 4.0 by the author.