数组与切片

数组

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
38
39
40
41
42
43
44
45
46
47
48
49
// 索引数组
a := [10]int{2:20}
// 不指定数组长度
a := [...]int{1,2,3,4}
// 多维数组,只有第一维可以使用...
a := [...][3]int{
{1,2,3},
{2,3,4}
}
a := [2][3]int{
{1,2,3},
{2,3,4}
}
//指针数组
x,y := 1,2
a := [...]*int{&x, &y}
//指向数组的指针
a :=[...]int{99:1}
var p *[100]int = &a
// 数组之间可以使用 == 或 != 比较,只有长度和类型相同才算相同的数组,才能比较
a :=[2]int{1,2}
b :=[2]int{3,2}
// 使用new关键字,返回指向数组的指针
a :=[2]int{}
a[1] = 2
b = new([2]int)
b[1] = 2
// 不论是指向数组的指针还是数组本身,都可以使用a[1]的形式给数组赋值
// go语言的数组是值类型,不是引用类型
//冒泡排序
func main() {
list := [...]int{12, 323, 4, 565, 67, 3}
fmt.Println(list)
var lenth = len(list)
for i := 0; i < lenth; i++ {
for j := i + 1; j < lenth; j++ {
if list[i] > list[j] {
tmp := list[i]
list[i] = list[j]
list[j] = tmp
}
}
}
fmt.Println(list)
}
// 结果:
➜ first go run helloworld.go
[12 323 4 565 67 3]
[3 4 12 67 323 565]

切片

切片与数组的定义区别

1
2
3
4
5
6
7
8
vs:=[]interface{}{
[]int{},// slice 切片
[]int{1,2,3},// slice 切片
[]int{1,2,3}[:],//切片再切还是切片
make([]int,3,10),//标准的slice 定义方式
[3]int{1,2,3},//array 数组,确定数组长度
[...]int{1,2,3},//array 数组,由编译器自动计算数组长度。
}

Reslice

  • 切片本质上是指向类型
  • 切片不能越界,如果超过底层数组,则报错,而不是追加数组长度
  • 索引不可超多数组容量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    a := [10]int{1,2,3,4,5,6,7,8,9}
    fpm.Prinln(a)
    // 0~4 容量为10
    s1 := a[:5]
    // 5-9, 索引5到索引9,索引10不取, 容量为5
    s1 := a[5,10]
    // 使用make,
    // 参数1:类型,
    // 参数2:包含几个元素,
    // 参数3:容量(先分配10个连续内存地址,如果增加到11个时,则需要从新分配,每次增加一倍,扩容至20,下次40,在下次80,造成这种现象的原因是因为:从新分配内存是一件效率非常低的)如果留空,则和参数相等
    s1 := make([]int,3,10)
    // 获取切片的长度,
    len(s1)
    // 获取切片容量
    map(s1)

Append

  • 可以在slice尾部追加元素
  • 可以将一个slice追加到另一个slice
  • 如果最终长度未超过追加到slice的容量,则返回原始slice
  • 如果超过追加的slice的容量,将重新分配数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    s1 := make([]int, 3, 6)
    fmt.Printf("%p\n", s1)
    s1 = append(s1, 1, 2, 3)
    fmt.Printf("%v %p\n", s1, s1)
    s1 = append(s1, 1, 2, 3)
    fmt.Printf("%v %p\n", s1, s1)
    // 对于指向同一个数组的slice,如果数组改变了,则两个slice指向的部分同样改变
    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)
    // 结果:
    ➜ first go run helloworld.go
    [3 4 5] [2 3]
    [9 4 5] [2 9]
  • 如果一个slice通过append添加时,如果超过了容量,那么就不在指向原来的数组,而是从新分配了一个
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    func main() {
    a := []int{1, 2, 3, 4, 5}
    s1 := a[2:5]
    s2 := a[1:3]
    fmt.Println(s1, s2)
    s2 = append(s2, 1, 2, 3, 4, 5, 5, 6, 6, 7)
    s1[0] = 9
    fmt.Println(s1, s2)
    }
    // 结果:
    ➜ first go run helloworld.go
    [3 4 5] [2 3]
    [9 4 5] [2 3 1 2 3 4 5 5 6 6 7]

copy

  • 从参数2复制到参数1(覆盖)
  • 该函数主要是切片(slice)的拷贝,不支持数组
  • 将第二个slice里的元素拷贝到第一个slice里,拷贝的长度为两个slice中长度较小的长度值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    s1 := []int{1, 2, 3, 4, 5, 6}
    s2 := []int{7, 8, 9}
    copy(s2, s1)
    copy(s1, s2)
    fmt.Println(s2, s1)
    // 结果
    ➜ first go run helloworld.go
    [1 2 3] [1 2 3 4 5 6]
    // 当然可以指定位置
    s1 := []int{1, 2, 3, 4, 5, 6}
    s2 := []int{7, 8, 9}
    copy(s1[3:6], s2)
    fmt.Println(s1)
    // 结果:
    ➜ first go run helloworld.go
    [1 2 3 7 8 9]

删除切片

1
2
// 比如想删除下标为k的切片
arr = append(arr[:k], arr[k+1:]...)

map

  • map是无序的
    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
    38
    39
    40
    41
    42
    43
    44
    // 初始化map
    m := map[int]string{1: "zhangsan", 2: "lisi", 3: "wangwu", 4: "zhaoliu"}
    // 初始化slice
    s := make([]int, len(m))
    i := 0
    // range 可遍历slice或map
    for k, _ := range m {
    // 将map的键赋给slice
    s[i] = k
    i++
    }
    fmt.Println(s)
    //结果(体现了map的无序性)
    ➜ first go run helloworld.go
    [1 2 3 4]
    ➜ first go run helloworld.go
    [4 1 2 3]

    // 如果使用range遍历slice和map,
    func main() {
    m := map[int]string{1: "zhangsan", 2: "lisi", 3: "wangwu", 4: "zhaoliu"}
    s := make([]int, len(m))
    i := 0
    for k, v := range m {
    s[i] = k
    i++
    fmt.Println(k, v)
    }
    fmt.Println(s)
    for k, v := range s {
    fmt.Println(k, v)
    }
    }
    // 结果如下:
    ➜ first go run helloworld.go
    4 zhaoliu
    1 zhangsan
    2 lisi
    3 wangwu
    [4 1 2 3]
    0 4
    1 1
    2 2
    3 3