Go 语言基础之数组(五)

友情提醒:本文最后更新于 654 天前,文中所描述的信息可能已发生改变,请谨慎使用。

数组是同一种数据类型元素的集合。在Go语言中,数组和python列表有很大区别,它具有如下特点:

  • 数组是同一种数据类型的固定长度的序列。
  • 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。
  • 长度是数组类型的一部分,因此,var a [5]int和var a [10]int是不同的类型。
  • 数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
  • 访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
  • 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。
  • 数组支持 "=="、"!=" 操作符,因为内存总是被初始化过的。
  • 指针数组 [n]T,数组指针 [n]T。

一. 数组的初始化

  • 初始化数组时可以使用初始化列表来设置数组元素的值。
func main() {
    var testArray [3]int                        //数组会初始化为int类型的零值
    var numArray = [3]int{1, 2}                 //使用指定的初始值完成初始化
    var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化
    fmt.Println(testArray)                      //[0 0 0]
    fmt.Println(numArray)                       //[1 2 0]
    fmt.Println(cityArray)                      //[北京 上海 深圳]
}
  • 按照上面的方法每次都要确保提供的初始值和数组长度一致,一般情况下我们可以让编译器根据初始值的个数自行推断数组的长度,例如:
func main() {
    var testArray [3]int
    var numArray = [...]int{1, 2}
    var cityArray = [...]string{"北京", "上海", "深圳"}
    fmt.Println(testArray)                          //[0 0 0]
    fmt.Println(numArray)                           //[1 2]
    fmt.Printf("type of numArray:%T\n", numArray)   //type of numArray:[2]int
    fmt.Println(cityArray)                          //[北京 上海 深圳]
    fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string
}
  • 还可以使用指定索引值的方式来初始化数组,例如:
func main() {
    a := [...]int{1: 1, 3: 5}
    fmt.Println(a)                  // [0 1 0 5]
    fmt.Printf("type of a:%T\n", a) //type of a:[4]int
}

二. 数组的遍历

遍历数组有以下两种方法:

func main() {
    var a = [...]string{"北京", "上海", "深圳"}
    // 方法1:for循环遍历
    for i := 0; i < len(a); i++ {
        fmt.Println(a[i])
    }

    // 方法2:for range遍历
    for index, value := range a {
        fmt.Println(index, value)
    }
}

三. 多维数组

package main

import (
    "fmt"
)

var arr0 [5][3]int
var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}

func main() {
    a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。
    fmt.Println(arr0, arr1)
    fmt.Println(a, b)
}

输出结果:

[[0 0 0] [0 0 0] [0 0 0] [0 0 0] [0 0 0]] [[1 2 3] [7 8 9]]
[[1 2 3] [4 5 6]] [[1 1] [2 2] [3 3]]

值拷贝行为会造成性能问题,通常会建议使用 slice,或数组指针。

package main

import (
    "fmt"
)

func test(x [2]int) {
    fmt.Printf("x: %p\n", &x)
    x[1] = 1000
}

func main() {
    a := [2]int{}
    fmt.Printf("a: %p\n", &a)

    test(a)
    fmt.Println(a)
}

输出结果:

a: 0xc000134010
x: 0xc000134030
[0 0]

内置函数 len 和 cap 都返回数组长度 (元素数量)。

package main

func main() {
    a := [2]int{}
    println(len(a), cap(a)) 
}
// 输出:2 2

多维数组的遍历:

package main

import (
    "fmt"
)

func main() {

    var f [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}

    for k1, v1 := range f {
        for k2, v2 := range v1 {
            fmt.Printf("(%d,%d)=%d ", k1, k2, v2)
        }
        fmt.Println()
    }
}
// 输出:
// (0,0)=1 (0,1)=2 (0,2)=3 
// (1,0)=7 (1,1)=8 (1,2)=9

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。若要修改数组内元素的值,需要传递数组指针。

package main

import "fmt"

func printArr(arr *[5]int) {
    arr[0] = 10
    for i, v := range arr {
        fmt.Println(i, v)
    }
}

func main() {
    var arr1 [5]int
    printArr(&arr1)
    fmt.Println(arr1)
    arr2 := [...]int{2, 4, 6, 8, 10}
    printArr(&arr2)
    fmt.Println(arr2)
}
// 输出
//0 10
//1 0
//2 0
//3 0
//4 0
//[10 0 0 0 0]
//0 10
//1 4
//2 6
//3 8
//4 10
//[10 4 6 8 10]

上一篇:Go 语言基础之流程控制(四)

下一篇:Go 语言基础之切片(六)