TOC

Golang 数组操作

声明

# array
[length]Type
[length]Type{v1, v2, ..., vn}
[...]Type{v1, v2, ..., vn}

# slice
[]Type
[]Type{v1, v2, ..., vn}
make([]Type, length)
make([]Type, length, capacity)

我想尝试动态创建数组(通过 arrLen 变量),没有找到方法,可能这就是静态类型语言吧。
所以,数组必须在写代码的时候就明确长度。否则就应该用切片。

此外,数组应该算是值类型。赋值的时候,会完全复制一份,传参也是一样。

Slice 等于数组指针 + 长度 + 容量。

package main

import "fmt"

func main() {
    var a []int
    fmt.Printf("%#v \t%d %d\n", a, len(a), cap(a)) // []int(nil) 0 0

    b := []int{1, 2, 3}
    fmt.Printf("%#v \t%d %d\n", b, len(b), cap(b)) // []int{1, 2, 3} 3 3

    var c [3]int
    fmt.Printf("%#v \t%d %d\n", c, len(c), cap(c)) // [3]int{0, 0, 0} 3 3

    d := [...]int{1, 2, 3}
    fmt.Printf("%#v \t%d %d\n", d, len(d), cap(d)) // [3]int{1, 2, 3} 3 3

    d2 := [...]int{3: 100}
    fmt.Printf("%#v \t%d %d\n", d2, len(d2), cap(d2)) // [4]int{0, 0, 0, 100} 4 4

    e := d[:]
    fmt.Printf("%#v \t%d %d\n", e, len(e), cap(e)) // []int{1, 2, 3} 3 3

    // 动态创建切片
    f := make([]int, 3, 10)
    fmt.Printf("%#v \t%d %d\n", f, len(f), cap(f)) // []int{0, 0, 0} 3 10

    // new 返回指针
    g := new([]int)
    fmt.Printf("%#v \t%d %d\n", g, len(*g), cap(*g)) // &[]int(nil) 0 0

    h := new([3]int)
    fmt.Printf("%#v \t%d %d\n", h, len(*h), cap(*h)) // &[]int{0, 0, 0} 3 3

    type User struct {
        Username string
        Password string
    }
    users := []User{
        {"a", "pass1"},
        {"b", "pass2"},  // 这样分行写的话,不能省略这个逗号
    }
    fmt.Printf("%+v \t%d %d\n", users, len(users), cap(users))
    // [{Username:a Password:pass1} {Username:b Password:pass2}] 2 2
}

索引

a[n]
a[n:m]
a[n:]
a[:m]
a[:]

// 索引为负数
// invalid argument: index -1 (constant of type int) must not be negative

// 索引越界
// invalid argument: array index 10 out of bounds [0:5]

遍历

for i := 0; i < len(arr); i++ {
    val := arr[i]
    // ...
}

for i, val := range arrayVar {
    // ...
}

// 如果只有一个变量接收遍历的值,那么这个变量将是 index
// 这个地方总是容易写错,要小心
for i := range arrayVar {
    val := arrayVar[i]
    // ...
}

复制

s1 := []int{1, 3, 6}
s2 := append([]int{}, s1...)
fmt.Printf("%#v %p\n", s1, s1)
fmt.Printf("%#v %p\n", s2, s2)

s3 := make([]int, len(s1))
copy(s3, s1)
fmt.Printf("%#v %p\n", s3, s3)

注意:copy 复制内容的长度以 src,dst 中较小的长度为准。

删除

a := []int{1, 2, 3, 4, 5, 6, 7}
// del a[3]
a = append(a[:3], a[4:]...)

插入

// 在尾部插入一个
a = append(a, ele)

// 在尾部插入一个数组或切片
a = append(a, arr...)

// copy 也是一种方法
a := [10]int{1, 2, 3}
b := []int{4, 5, 6}
copy(a[3:], b)

// WRONG!
a := []int{1, 2, 3, 5, 6, 7}
tmp := a[:3]
tmp = append(tmp, 4)
fmt.Println(a)  // [1 2 3 4 6 7]

func insert(slice []int, index int, num int) []int {
    rest_len := len(slice) - index
    tmp := make([]int, rest_len, len(slice)+1)
    copy(tmp, slice[:index])
    tmp[index] = num
    tmp = append(tmp, slice[index:]...)
    return tmp
}

弹出

数组长度固定无法执行“弹出”操作,但是可以删除其中的一个节点。

nums := []int{1, 2, 3, 4}
first := nums[0]
nums = nums[1:]
last := nums[len(nums) - 1]
nums := nums[:len(nums) - 1]

合并

package main

import "fmt"

func main() {
    a := []int{1, 2, 3}
    b := []int{1, 2, 3}
    c := [3]int{4, 5, 6}
    d := [3]int{4, 5, 6}

    // 切片合并
    e := append(a, b...)
    fmt.Printf("%#v, %#v, %#v\n", a, b, e)

    f := append(c[:], d[:]...)
    fmt.Printf("%#v, %#v, %#v\n", c, d, f)

    g := [6]int{}
    for i, v := range a {
        g[i] = v
    }
    length := len(a)
    for i, v := range a {
        g[i+length] = v
    }
    fmt.Printf("%#v\n", g)

    h := [6]int{}
    // func copy(dst, src []Type) int
    copy(h[:], a)
    fmt.Printf("%#v\n", h)
    copy(h[3:], a)
    fmt.Printf("%#v\n", h)
}

排序

package main

import (
    "fmt"
    "sort"
)

func main() {
    nums := []int{9, 5, 2, 7, 1}
    sort.Ints(nums)
    fmt.Println(nums)
}
  • sort.Strings
  • sort.Float64s