认识 Go 语言中的数组

网友投稿 749 2022-09-01

认识 Go 语言中的数组

认识 Go 语言中的数组

声明方式

在 Go 语言中,数组的声明方式为: var identifier [len]type声明时没有指定数组的初始化值,因此所有的元素都会被

自动初始化为默认值 0

// 声明一个数组 var a1 [5]int

Go 语言中的数组是值类型,因此还可以用

new

来创建:

var a2 = new([5]int)

new

返回类型的指针,因此

a1

a2

的区别在于:a1

的类型为[5]int,a2

的类型为

*[5]int。

初始化方法

我们通过在

{}

中填写初始化值来初始化数组。

指明数组长度

指明数组的长度

len,然后在

{}

中填写初始化值,这些值会按下标从小到大的顺序分配。初始化值的个数不允许超过长度

len。当初始化值的个数小于

len

时,未被初始化的位置等于默认值 0。

// 数组长度为 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:

// 通过数组索引初始化 // 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 语言将

通过初始化元素的个数来确定数组的长度

// 通过传递初始化值确定数组长度 // 传递了 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:

// 最大索引是 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

遍历数组:

// i 是数组索引 for i, _ := range arr1 {

    // do something }

数组是值类型

和 C/C++ 不同,Go 语言的数组是

值类型

的。这样一来,

赋值和传参都会复制整个数组,而不是指针

。我们初始化一个数组

a,并把它赋值给数组

b,然后打印两者的值与指针:

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

传入:

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。

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,传入的初始化值为整型

m

n

的内存地址(&m

&n),那么

pointerArray

就是一个装着

int

类型指针的数组,即指针数组,它的类型为

[2]*int。

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 语言中,数组是值类型,赋值和传递参数都会发生数组的复制

数组指针是一个指针,它指向了一个数组

指针数组是一个数组,它里面装着指针

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Yii框架中CGridView的使用方法以及详细示例
下一篇:CGridView中实现批量删除
相关文章

 发表评论

暂时没有评论,来抢沙发吧~