6.1.数组

这里将自己学习Go及其区块链的一些笔记、积累分享一下,如果涉及到了文章、文字侵权,请联系我删除或调整。


  • 数组是数据的集合,以满足按照逻辑对数据进行分组的需要。
  • 数组也是基本的数据结构(由多个数据元素组成),以存储一系列可被基零连续下标索引的数据。
  • 为了创建数组,需要声明一个数组类型的变量,在声明中指定其类型长度。

1)var arr [5]int 仅声明未初始化

​​​​​​方括号中的数字表示数组长度,即所含元素的个数,后面紧跟元素的数据类型,即数组的类型。

2)var arr = [5]int{10, 20, 30, 40, 50} 声明并初始化

 

 

数组也可以在声明的同时初始化,花括号中是用逗号分隔的初值序列,其长度可以小于但不能大于数组的长度,未显式指定初值的元素被默认初始化为适当类型的零值。

3)arr := [...]int{10, 20, 30, 40, 50} 注意省略号不可省略

带有显式初始化的数组声明,其长度也可以用省略号表示,编译器会根据初值的个数自动计算其长度,但如果连省略号也不写,那就不再是数组而变成切片了二者在性质上并不完全等价

  • 数组一经声明,其长度不可改变,既不能添加元素,也不能删除元素,但我们可以修改数组元素的值,可以把数组看作一种“值可写,但结构不可写”的数据类型。
  • 数组是一种独立的数据类型,可以内存复制的形式被整体地赋值、传参和从函数中返回,前提是目标数组必须与源数组具有完全相同的类型和长度
  • 数组中的元素可通过从0开始的,连续正整数形式的下标访问,试图访问超出合法下标范围的元素,即所谓下标越界,将导致编译错误。
  • 数组是一种空间递归的数据结构,所谓n维数组其实就是n-1维数组的一维数组,即我们可以将数组的元素也声明为数组。
  • 如果在声明的同时初始化高维数组,只有最高维的长度可以用省略号"..."表示。

​​​​​​​​​​​

// var 数组 [长度]类型
// var 数组 = [长度(...)]类型{初值表} 
// 数组 := [长度(...)]类型{初值表} 
package main

import "fmt"

// 传数组,复制数据
func foo(x [3]int) {
    for i := 0; i < len(x); i++ {
        x[i]++
    }

    fmt.Println("foo:", x)
}

在go语言中的函数声明时,参数声明为数组类型,那么函数调用过程的形参会对实参进行复制,在函数体内的操作不会修改原实参的数据。

// 传切片,共享数据
func bar(x []int) {
    for i := 0; i < len(x); i++ {
        x[i]++
    }
    fmt.Println("bar:", x)
}

在go语言中的函数声明时,参数声明为切片类型,那么函数调用过程的形参会共享实参的数据,在函数体内的操作修改原实参的数据。

在go语言中,可以对切片进行元素追加的操作(相当于重新建立了1个数据,并进行了数据的拷贝)。对于切片而言,当执行“追加元素”的操作时,切片会发生结构性的改变——会产生一次元素的复制

对于hum(x []int)函数而言,其先执行了自增,而后执行了元素复制;而fun(x []int)则是先执行了元素复制,而后执行自增。具体如下述demo所示。

// 共享->修改->复制
func hum(x []int) {	// 形参x与实参指向同一个内存区域
    for i := 0; i < len(x); i++ {
        x[i]++
    }
	// 此步执行完毕后,x指向了一个新的内存区域(形参x的副本 + 追加的元素)
	// 并且,新的数据没有返回给实参,则实参本身没有变化。
    x = append(x, x[len(x)-1]+1)

    fmt.Println("hum:", x)
}
// 共享->复制->修改
func fun(x []int) {	// 形参x与实参指向同一个内存区域
	// 此步执行完毕后,x指向了一个新的内存区域(形参x的副本 + 追加的元素)
    x = append(x, x[len(x)-1]+1)
	// 自增操作的对象是x指向的副本,而不再是原实参指向的数据,因此,fun函数中
	// 的任何操作,都不会影响到原实参指向的数据。
    for i := 0; i < len(x); i++ {
        x[i]++
    }

    fmt.Println("fun:", x)
}

func main() {
    //
    // 数组的声明与赋值
    //
    var a [3]string   // 以前文学习的数组初始化方法,声明并初始化了字符串数组a
    a[0] = "Hello World!"
    a[1] = "Hello George!"
    a[2] = "Hello Go!"
    fmt.Println(a)
    //
    // 数组与切片型参数
    //
    var b = [...]int{1, 2, 3}
    fmt.Println(b) // [1 2 3]
	// 传数组,复制数据,不影响原实参数据
    foo(b)         // [2 3 4]
    fmt.Println(b) // [1 2 3]
    
    // 传切片,共享数据,影响原实参数据
    bar(b[:])      // [2 3 4]
    fmt.Println(b) // [2 3 4]
    
    // 共享->修改->复制
	// hum首先执行了自增,因为是"传切片"所以实参原数据也发生了改变[1,2,3]->
	// [3,4,5];其次,hum执行了“追加元素”操作,此时发生了元素复制,新的元素
	// 添加在了b副本的末尾,而不是直接添加在了b的末尾。因此,hum函数内外打印
	// 的结果不同。
    hum(b[:])      // [3 4 5 6]
    fmt.Println(b) // [3 4 5]
    
    // 共享->复制->修改
	// fun虽然也是“传切片”,但fun函数第一行就执行了“追加元素”的操作,因此
	// fun后续所有的操作都是针对b的副本在执行,不影响实参指向的数据。因此,在
	// 执行fun函数后,b的打印结果依旧是[3,4,5],并没有发生自增。
    fun(b[:])      // [4 5 6 7]
    fmt.Println(b) // [3 4 5]

多维数据的实例:

 // 二维数组下标循环 
    c := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    fmt.Println(c)
    for i := 0; i < len(c); i++ {
        for j := 0; j < len(c[i]); j++ {
            fmt.Printf("c[%v][%v]: %v\n", i, j, c[i][j])
        }
    }
    // 二维数组范围循环 
    d := [...][3]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
    fmt.Println(d)
    for i, row := range d {
        for j, col := range row {
            fmt.Printf("d[%v][%v]: %v\n", i, j, col)
        }
    }
}
// 输出结果:
[[1 2 3] [4 5 6]]
c[0][0]: 1
c[0][1]: 2
c[0][2]: 3
c[1][0]: 4
c[1][1]: 5
c[1][2]: 6
[[1 2 3] [4 5 6] [7 8 9]]
d[0][0]: 1
d[0][1]: 2
d[0][2]: 3
d[1][0]: 4
d[1][1]: 5
d[1][2]: 6
d[2][0]: 7
d[2][1]: 8
d[2][2]: 9 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值