Go 常见数据类型-01数组

前言

最近刚练习完GoAPI实战,途中发现自己对Go各种数据类型的理解还是很浅薄,所以打算重新把Go各种数据类型的一些理解做一个整理,同时也分享给大家,初学者,理解浅薄,有不足的欢迎大家指出交流。

数组的声明:

数组的声明需要指定元素的数据类型,以及存储元素的数量(数组长度),如以下代码所示

var a [3]int
var b [4]int
a = b //不可以这样做,因为此时a和b是不同的数组类型

数组长度必须是一个非负整数的常量(或常量表达式),数组长度也是数组类型的一部分,所以[3]int和[4]int不是同一种类型

数组需要在声明时指定数组长度(编译时需要知道数组长度以便分配内存),数组最大长度为2GB。

数组一旦声明,它所存储的数据类型和数组长度便都不能修改了。如果需要存储更多的元素,必须先创建一个更长的数组,然后把原来的数组里的值复制到新数组里面。

初始化数组

数组可以有多种初始化方式,如:

方式1

go 语言在声明变量时,都是使用相应类型的零值来初始化变量的,数组也一样。数组初始化时,其每个元素都被初始化对应类型的零值。比如下面的整形数组里,每个元素都被初始化为0(整形的零值)

var testArr [3]int             // 数组会初始化为零值 [0 0 0]
var testArr = [3]int{1, 2}     // 数组会将未指定的下标值初始化为0值 [1 2 0]
var testArr = [3]int{1, 2, 3}  // 数组使用指定的数据初始化 [1 2 3]

方式2

以上的方式需要保证初始化的数组长度和指定数组长度一样,除此以外我们还可以让编译器自己判断数组的长度

var testArr = [...]int{1, 2, 3}     // 数组自动指定长度为3 [1 2 3]

方式3

此外还可以通过指定索引值的方式来初始化数组:

var testArr = [...]int{1:20, 5: 30}  // [0 20 0 0 0 30]

数组的操作

数组访问

对于数组arr[],第一个元素是arr[0],第三个元素是arr[2],总体来说下标i代表的元素是arr[i],最后一个元素是arr[len(arr)-1],超出范围会报panic。

数组修改

GO语言通过数组下标(索引位置)来读取和修改数组元素,下标(索引)从0开始,逐渐类推。

数组是效率很高的数据结构,因为数组在内存分配中是连续的,要访问数组里某个单独的值,使用[]运算符既可。
数组的值也可以是指针,下面声明一个所有元素都是指针的数组,然后使用*运算符就可以访问元素指针所指向的值:

// 声明包含5个元素的指向整数的数组
// 用整形指针初始化索引为0和1的数组元素
array := [5]*int{0: new(int), 1: new(int)}
// 为索引0和1的元素赋值
*array[0] = 10
*array[1] = 20

fmt.Println(*array[0])
//输出为:10

fmt.Println(*array[2])
// 报错 panic: runtime error: invalid memory address or nil pointer dereference,因为此时 array[2] 没有指定类型

数组赋值

在GO语言中,数组是一个类型值,这意味着数组也可以像函数一样用在赋值操作中,变量名代表整个数组,因此同样类型的数组可以赋值类另一个数组,如:

// 声明一个包含5个元素的字符串数组
var array1 [5]string
// 声明第二个包含5个元素的字符串数组并初始化
array2 := [5]string{"a", "b", "c", "d", "e"}
array1 = array2

数组作为一个变量类型,它包括数组长度和每个元素的类型两个部分。只有两部分都相同的数组才是类型相同的数组,才能相互赋值。

数组的类型

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。

var array1 [3]string
array2 := [3]string{"", "", ""}

array2[0] = "a"
array2[1] = "b"
array2[2] = "c"
array1 = array2
array2[0] = "d"
fmt.Println(array1[0])
// 输出a

而在下面操作中,复制操作后,两个数组指向同一组字符串,修改其中一个数组的某个值后,另一个数组的值也相应改变。

// 声明一个包含3个元素的指向字符串的指针数组
var array1 [3]*string
// 声明第二个包含3个元素的指向字符串的指针数组,并使用字符串指针初始化这个数组
array2 := [3]*string{new(string), new(string), new(string)}
*array2[0] = "a"
*array2[1] = "b"
*array2[2] = "c"

array1 = array2
*array2[1] = "d"
fmt.Println(*array1[1])
// 输出d

注意:

  • 数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。
  • [n]*T表示指针数组,*[n]T表示数组指针.

多维数组

数组本身只有一个维度,但是可以组合多个数组创建多维数组。多维数组用于管理具有依赖关系的数据(比如坐标系),下面是声明二维数组的示例代码:

//声明一个二维整形数组,两个维度分别存储4个元素和2个元素
var array [4][2]int
//使用数组字面量来声明并初始化一个二维整形数组
array := [4][2]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}}
//声明并初始化外层数组中索引为1和3的元素
array := [4][2]int{1: {3, 4}, 3: {7, 8}}
//声明并初始化外层数组和内层数组的单个元素
array := [4][2]int{1: {0: 1}, 3: {1: 2}}

访问单个元素,需要组合[]运算符。如:

array[0][1] = 1

和一维数组一样,只要类型一致,就可以将多维数组互相赋值,又因为每个数组都是一个单独的值,所以还可以独立赋值某个维度,如:

// 将array1的索引为1的维度赋值到一个同类型的新数组里
var array3 [2]int = array1[1]
// 将外层数组的索引为1、内层数组的索引为0的整形值复制到新的整形变量里
var value int = array1[1][0]

多维数组也可以使用...来编译器自动判断数组长度。但只支持第一层数组这样使用。如:

//支持的写法
a := [...][2]string{
    {"北京", "上海"},
    {"广州", "深圳"},
    {"成都", "重庆"},
}
//不支持多维数组的内层使用...
b := [3][...]string{
    {"北京", "上海"},
    {"广州", "深圳"},
    {"成都", "重庆"},
}

数组的遍历

一维数组遍历

func main() {
    var a = [...]string{"a", "b", "c"}
    // 方法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)
    }
}

二维数组遍历

func main() {
    a := [3][2]string{
        {"北京", "上海"},
        {"广州", "深圳"},
        {"成都", "重庆"},
    }
    for _, v1 := range a {
        for _, v2 := range v1 {
            fmt.Printf("%s\t", v2)
        }
        fmt.Println()
    }
}

慢慢会把其它数据类型的也做一个整理,做一个合集,希望整理完对自己学习Go会有帮助。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!