切片(Slice)的操作 | 青训营笔记

214 阅读2分钟

3. 切片

3.1 切片的定义

切片是数组的一个引用,因此切片是引用类型。切片的长度是切片类型的一部分,因此切片的长度是可以改变的。

var s1 []int
s2 := []int{1, 3, 5, 7, 9}
s3 := make([]int, 3, 5)
s4 := append(s3, 11)
s5 := make([]int, 3, 5)
copy(s5, s4)

3.2 切片的遍历

func main() {
    s := []int{1, 3, 5}
    for i := 0; i < len(s); i++ {
        fmt.Println(s[i])
    }
    for i := range s {
        fmt.Println(s[i])
    }
    for i, v := range s {
        fmt.Println(i, v)
    }
    for _, v := range s {
        fmt.Println(v)
    }
}

3.3 切片的截取

切片的截取是一个左闭右开的区间。

切片截取后,切片的长度和容量都会发生变化, 长度为截取的长度,容量为原切片的容量减去截取的起始位置。

func main() {
    s := []int{1, 3, 5, 7, 9}
    fmt.Println(s[2:4])
    fmt.Println(s[:4])
    fmt.Println(s[2:])
    fmt.Println(s[:])
}

3.4 切片的扩展

切片的扩展是指切片的长度超过了切片的容量,此时切片会重新分配内存。

扩容后,切片的指针会发生变化,因此扩容后的切片和原切片不再共享底层数组。

分配内存有两种情况:

  • 如果扩容后的容量小于 1024,那么新切片的容量会翻倍,直到新容量大于等于扩容后的容量。
  • 如果扩容后的容量大于等于 1024,那么新切片的容量会增加 25%,直到新容量大于等于扩容后的容量。

原因是为了避免内存的频繁分配和释放,因此在扩容时会预留一部分内存,以便下次扩容时可以直接使用。

3.5 切片的删除

func main() {
    s1 := []int{1, 3, 5, 7, 9}
    // 删除索引为 2 的元素
    s2 := append(s1[:2], s1[3:]...)
    fmt.Println(s2)
}

3.6 切片的指针

func main() {
    s1 := []int{1, 3, 5, 7, 9}
    s2 := &s1
    s2[0] = 0
    fmt.Println(s1)
    fmt.Println(s2)
}

4. map

4.1 map 的定义

map 是一种无序的键值对的集合,map 的键是唯一的,但是值可以重复。

var m1 map[string]int
m2 := make(map[string]int)
m3 := map[string]int{"a": 1, "b": 2, "c": 3}

4.2 map 的遍历

map 的遍历是无序的。

如果只遍历 map 的键,可以使用 for range 循环。

如果需要同时遍历 map 的键和值,可以使用 for range 循环。

如果只遍历 map 的值,可以使用 for range 循环,但是需要使用 _ 占位符占位。

顺序遍历 map,需要先将 map 的键放入切片中,然后对切片进行排序,最后遍历切片,根据切片的值取出 map 的值。

func main() {
    m := map[string]int{"a": 1, "b": 2, "c": 3}
    for k := range m {
        fmt.Println(k)
    }
    for k, v := range m {
        fmt.Println(k, v)
    }
    for _, v := range m {
        fmt.Println(v)
    }
}

4.3 map 的删除

func main() {
    m := map[string]int{"a": 1, "b": 2, "c": 3}
    delete(m, "a")
    fmt.Println(m)
}

4.4 map 的指针

func main() {
    m1 := map[string]int{"a": 1, "b": 2, "c": 3}
    m2 := &m1
    m2["a"] = 0
    fmt.Println(m1)
    fmt.Println(m2)
}