前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >认识 Go 语言中的数组

认识 Go 语言中的数组

作者头像
江不知
发布2019-12-12 15:50:52
4310
发布2019-12-12 15:50:52
举报
文章被收录于专栏:编程拯救世界编程拯救世界

数组是具有相同唯一类型的一组已编号长度固定的数据项序列。

声明方式

在 Go 语言中,数组的声明方式为:

var identifier [len]type

声明时没有指定数组的初始化值,因此所有的元素都会被自动初始化为默认值 0

代码语言:javascript
复制
// 声明一个数组
var a1 [5]int

Go 语言中的数组是值类型,因此还可以用 new 来创建:

代码语言:javascript
复制
var a2 = new([5]int)

new 返回类型的指针,因此 a1a2 的区别在于:a1 的类型为 [5]inta2 的类型为 *[5]int

初始化方法

我们通过在 {} 中填写初始化值来初始化数组。

指明数组长度

指明数组的长度 len,然后在 {} 中填写初始化值,这些值会按下标从小到大的顺序分配。

初始化值的个数不允许超过长度 len。当初始化值的个数小于 len 时,未被初始化的位置等于默认值 0。

代码语言:javascript
复制
// 数组长度为 5,初始化了前两个数,未初始化的位是 0
b := [5]int{1, 2} 
for index, val := range b {
    fmt.Printf("下标 = %d, 值 = %d\n", index, val)
}

/* Output:
下标 = 0, 值 = 1
下标 = 1, 值 = 2
下标 = 2, 值 = 0
下标 = 3, 值 = 0
下标 = 4, 值 = 0
*/

也可以使用 {index1: a, index2: b} 的方式初始化数组,指明数组的索引和对应的下标值,未指明的下标所在位置的值等于默认值 0:

代码语言:javascript
复制
// 通过数组索引初始化
// d[0] = 1, d[2] = 3,其他位置等于 0
d := [5]int{0: 1, 2: 3} 
for index, val := range d {
    fmt.Printf("下标 = %d, 值 = %d\n", index, val)
}

/* Output:
下标 = 0, 值 = 1
下标 = 1, 值 = 0
下标 = 2, 值 = 3
下标 = 3, 值 = 0
下标 = 4, 值 = 0
*/

暗示数组长度

初始化时你也可以不直接指明数组的长度,而是使用 [...] 代替。和指明数组长度时相同,此时也可以使用顺序填写和指定索引两种方式来初始化数组。

当使用 {a, b, c} 方式传递初始化值时,Go 语言将通过初始化元素的个数来确定数组的长度

代码语言:javascript
复制
// 通过传递初始化值确定数组长度
// 传递了 5 个元素,数组长度为 5
c := [...]int{1, 2, 3, 4, 5}  
for index, val := range c {
    fmt.Printf("下标 = %d, 值 = %d\n", index, val)
}
/* Output:
下标 = 0, 值 = 1
下标 = 1, 值 = 2
下标 = 2, 值 = 3
下标 = 3, 值 = 4
下标 = 4, 值 = 5
*/

若通过指明数组的索引和对应的值来初始化数组,此时数组的长度就等于 最大索引数 + 1

代码语言:javascript
复制
// 最大索引是 9,所以数组的长度为 10
e := [...]int{9: 10} 
for index, val := range e {
    fmt.Printf("下标 = %d, 值 = %d\n", index, val)
}

/* Output:
下标 = 0, 值 = 0
下标 = 1, 值 = 0
下标 = 2, 值 = 0
下标 = 3, 值 = 0
下标 = 4, 值 = 0
下标 = 5, 值 = 0
下标 = 6, 值 = 0
下标 = 7, 值 = 0
下标 = 8, 值 = 0
下标 = 9, 值 = 10
*/

数组的遍历

在 Go 语言中使用 for ... range 遍历数组:

代码语言:javascript
复制
// i 是数组索引
for i, _ := range arr1 {
    // do something
}

数组是值类型

和 C/C++ 不同,Go 语言的数组是值类型的。这样一来,赋值和传参都会复制整个数组,而不是指针

我们初始化一个数组 a,并把它赋值给数组 b,然后打印两者的值与指针:

代码语言:javascript
复制
a := [5]int{1, 2, 3, 4, 5}
b := a
fmt.Printf("数组 a - 值:%v,指针:%p\n", a, &a)
fmt.Printf("数组 b - 值:%v,指针:%p\n", b, &b)
/* Output:
数组 a - 值:[1 2 3 4 5],指针:0xc00001e0f0
数组 b - 值:[1 2 3 4 5],指针:0xc00001e120
*/

可以看到,两者的值是相同的,但是内存地址却不同,说明在赋值的过程中复制了整个数组

我们再来看一下传参的例子。

定义一个函数 transmitA,把刚才我们初始化的数组 a 传入:

代码语言:javascript
复制
func main() {
    a := [5]int{1, 2, 3, 4, 5}
    fmt.Printf("数组 a - 值:%v,指针:%p\n", a, &a)

    // 把数组 a 传入函数
    transmitA(a)
}

func transmitA(a [5]int) {
    fmt.Printf("传入函数的数组 a - 值:%v,指针:%p\n", a, &a)
}

/* Output:
数组 a - 值:[1 2 3 4 5],指针:0xc00001e0f0
传入函数的数组 a - 值:[1 2 3 4 5],指针:0xc00001e150
*/

从输出可以看出,两者的值依然相同,内存地址却是不同的。这说明在传参时数组也被复制了

数组指针与指针数组

数组指针与指针数组听起来似乎有点拗口,那么来展开说明一下:

  • 数组指针:(指向)数组(的)指针
  • 指针数组:(装满了)指针(的)数组

也就是说,数组指针是个指针,它指向一个数组;而指针数组是个数组,它里面装满了指针

数组指针

声明一个数组 a,然后将它的地址赋值给 arrayPointer。这样一来,arrayPointer 就是一个指向数组 a 的指针,即数组指针,它的类型为 *[5]int

代码语言:javascript
复制
a := [5]int{1, 2, 3, 4, 5}
// 把数组 a 的地址赋值给 arrayPointer
// arrayPointer 是指向数组的指针,类型为 *[5]int
arrayPointer := &a
fmt.Println(arrayPointer)

/* Output:
&[1 2 3 4 5]
*/

指针数组

初始化数组 pointerArray,传入的初始化值为整型 mn 的内存地址(&m&n),那么 pointerArray 就是一个装着 int 类型指针的数组,即指针数组,它的类型为 [2]*int

代码语言:javascript
复制
m := 1
n := 2
// 初始化 pointerArray,传入 m 与 n 的地址
// pointerArray 包含了整型地址,是一个装着指针的数组
pointerArray := [2]*int{&m, &n}
fmt.Println(pointerArray)

/* Output:
[0xc0000aa000 0xc0000aa008]
*/

总结

  • 数组的长度是固定的,初始化时需要「明示」或「暗示」数组的长度
  • 数组的长度是数组类型的组成部分[2]int[100]int 是不同类型的数组
  • 使用 for … range 遍历数组
  • 在 Go 语言中,数组是值类型,赋值和传递参数都会发生数组的复制
  • 数组指针是一个指针,它指向了一个数组
  • 指针数组是一个数组,它里面装着指针

参考资料

  • 《Go 学习笔记》: https://github.com/qyuhen/book
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程拯救世界 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 声明方式
  • 初始化方法
    • 指明数组长度
      • 暗示数组长度
      • 数组的遍历
      • 数组是值类型
      • 数组指针与指针数组
        • 数组指针
          • 指针数组
          • 总结
          • 参考资料
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档