Golang语言之数组(array)快速入门篇

简介: 这篇文章是关于Go语言中数组的详细教程,包括数组的定义、遍历、注意事项、多维数组的使用以及相关练习题。

                                              作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.数组的定义

1.数组的引入

package main

import "fmt"

func main() {
    // 实现的功能,将西游记师徒四人的分数求和,平均数
    tangsanzang := 100
    sunwukong := 99
    zhubajie := 88
    shaheshang := 77

    // 求和
    sum := tangsanzang + sunwukong + zhubajie + shaheshang

    // 求平均数
    avg := sum / 4

    fmt.Printf("西游记师徒四人的总分: %d, 平均成绩: %d\n", sum, avg)


    // 上述代码有个缺点,分数变量个数定义太多,不利于项目维护。
}

2.数组的概述

数组(array)是同一种数据类型元素的集合,其有以下3个特点:
    - 1.长度固定;
    - 2.连续内存空间;
    - 3.同一类型集合;

在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。 


定义数组的语法:
    var 数组变量名 [元素数量]T

温馨提示:
    数组的长度必须是常量,并且长度是数组类型的一部分。一旦定义,长度不能变。

3.数组案例

package main

import "fmt"

func main() {

    // 定义一个长度为4的数组
    var xiyouji [4]int

    // 使用一个变量就可以进行存储
    xiyouji[0] = 100
    xiyouji[1] = 99
    xiyouji[2] = 88
    xiyouji[3] = 77

    // 求和
    sum := 0
    for i := 0; i < len(xiyouji); i++ {
        sum += xiyouji[i]
    }

    // 求平均数
    avg := sum / len(xiyouji)

    fmt.Printf("成绩的总和: %v, 成绩的平均数: %v\n", sum, avg)
}

4.数组的内存分析

package main

import "fmt"

func main() {
    // 声明长度为5的数组
    var array [5]uint16

    // 数组赋值
    array[0] = 100
    array[1] = 200
    array[2] = 300

    // 获取数组的长度
    fmt.Printf("数组长度为:%d,数组的内容:%v\n", len(array), array)

    // 数组中存储的地址
    fmt.Printf("数组的地址:%p\n", &array)

    // 第一个空间的地址
    fmt.Printf("数组的第一个地址:%p\n", &array[0])

    // 第二个空间的地址
    fmt.Printf("数组的第二个地址:%p\n", &array[1])

    // 第三个空间的地址
    fmt.Printf("数组的第三个地址:%p\n", &array[2])

    // 第四个空间的地址
    fmt.Printf("数组的第二个地址:%p\n", &array[3])

    // 第五个空间的地址
    fmt.Printf("数组的第三个地址:%p\n", &array[4])

}

5.四种数组初始化的方式

package main

import "fmt"

func main() {

    var (

        // 第一种: 带数组类型初始化列表
        array01 [7]string = [7]string{"北京", "上海", "深圳", "西安", "成都", "杭州", "乌兰察布"}

        // 第二种: 不带数组类型初始化列表
        array02 = [4]bool{false, true, true}

        // 第三种: 自行推断长度
        array03 = [...]uint8{11, 22, 33, 44, 55}

        // 第四种: 指定索引值
        array04 = [...]int{1: 100, 3: -200, 5: 300}
    )

    fmt.Printf("array01类型: %T,值: %v, 长度: %d\n", array01, array01, len(array01))
    fmt.Printf("array02类型: %T,值: %v, 长度: %d\n", array02, array02, len(array02))
    fmt.Printf("array03类型: %T,值: %v, 长度: %d\n", array03, array03, len(array03))
    fmt.Printf("array04类型: %T,值: %v, 长度: %d\n", array04, array04, len(array04))

}

二.数组的遍历

1.数组遍历的方式

数组的遍历方式有两种,即普通for循环和键值循环。

键值循环(for range)是GO语言特有的一种迭代结构,在许多情况下都非常有用,for  range看了眼遍历数组,切片,字符串,map即通道。

for range语法上类似于其他语言中的foreach语句,一般形式如下:
  for key,value := range 数组标识符 {
    ...
  }

温馨提示:
    1.数组标识符就是你定义的数组变量;
    2.每次遍历得到的索引用key接收,每次遍历得到的索引位置上的值用value接收;
    3.key,value的名称是随便起名,比如可以写成类似: "k,v"等;
    4.key,value属于局部变量,每次变量都被修改了数据;
    5.key,value的值如何你想忽略的话,接受的时候使用"_"代替即可;

2.for循环遍历

package main

import "fmt"

func main() {
    // 功能实现: 手动录入3个学生的分数,然后打印出来。
    var scores [3]int

    // 将分数存储在数组中:
    for i := 0; i < len(scores); i++ {
        fmt.Printf("请录入第[%d]个学生的成绩: ", i+1)
        fmt.Scanln(&scores[i])
    }

    // 使用for循环展示分数
    for i := 0; i < len(scores); i++ {
        fmt.Printf("第[%d]个学生的成绩为: %d\n", i+1, scores[i])
    } 
}

3.for range遍历

package main

import "fmt"

func main() {
    // 功能实现: 手动录入3个学生的分数,然后打印出来。
    var scores [3]int

    // 将分数存储在数组中:
    for i := 0; i < len(scores); i++ {
        fmt.Printf("请录入第[%d]个学生的成绩: ", i+1)
        fmt.Scanln(&scores[i])
    }

    // 使用for-range循环展示分数
    for index, value := range scores {
        fmt.Printf("第[%d]个学生的成绩为: %d\n", index+1, value)
    }
}

三.数组的注意事项

1.数组长度属于类型的一部分

package main

import "fmt"

func main() {

    var (
        // 数组长度属于类型的一部分
        array01 = [3]int{3, 5, 7}
        array02 = [5]int{11, 22, 33, 44, 55}
    )

    fmt.Printf("array01数组的类型为: %T,数据为: %v\n", array01, array01)
    fmt.Printf("array02数组的类型为: %T,数据为: %v\n", array02, array02)

}

2.数组属于值类型,默认进行值传递

package main

import "fmt"

func setName(name [3]string) {
    name[0] = "JasonYin"

    fmt.Printf("in setName ... name = %v\n", name)
}

func main() {

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

    温馨提示:
        (1)数组支持"=="、"!="操作符,因为内存总是被初始化过的;
        (2)"[n]*T"表示指针数组,"*[n]T"表示数组指针; 
    */

    var names = [3]string{"尹正杰", "yinzhengjie", "jasonyin2020"}

    fmt.Printf("调用setName前: in main ... names = %v\n", names)


    // 调用setName函数时,传递的数组属于值传递,因此setName内的修改并不会影响到main函数的数组
    setName(names)

    fmt.Printf("调用setName后: in main ... names = %v\n", names)
}

3.数组实现引用传递

package main

import "fmt"

// 接受的形参类型变为指针类型
func setName(name *[3]string) {

    // 取出指针的地址存储的数组地址,基于数组的内存地址修改数据
    (*name)[0] = "JasonYin"

    fmt.Printf("in setName ... name = %v,地址: %p\n", name, name)
}

func main() {

    var names = [3]string{"尹正杰", "yinzhengjie", "jasonyin2020"}

    fmt.Printf("调用setName前: in main ... names = %v,地址: %p\n", names, &names)

    // 传入names数组的地址
    setName(&names)

    fmt.Printf("调用setName后: in main ... names = %v,地址: %p\n", names, &names)
}

四.多维数组

1.字符串二维数组案例

package main

import (
    "fmt"
)

func main() {

    // 定义二维数组,如果有元素默认进行初始化赋值,则有默认值("零值")
    address := [5][2]string{
        {"陕西省", "西安市"},
        {"河北省", "石家庄市"},
        {"黑龙江省", "哈尔滨"},
        {"江苏省", "南京市"},
    }

    fmt.Println(address)

    // 支持索引取值
    fmt.Println(address[2][1])
}

2.二维数组的内存分析

package main

import "fmt"

func main() {
    // 定义二维数组,有默认的初始值
    var array [2][3]uint16

    // 二维数组赋值
    array[0][0] = 100
    array[0][1] = 200
    array[1][1] = 300

    fmt.Printf("array地址: %p\n", &array)
    fmt.Printf("array[0]地址: %p\n", &array[0])
    fmt.Printf("array[0][0]地址: %p\n", &array[0][0])

    fmt.Printf("array[1]地址: %p\n", &array[1])
    fmt.Printf("array[1][0]地址: %p\n", &array[1][0])
    fmt.Printf("array[1][2]地址: %p\n", &array[1][2])
}

3.二维数组的三种数组初始化的方式

package main

import "fmt"

func main() {

    var (

        // 第一种: 带数组类型初始化列表
        array01 [5][2]string = [5][2]string{
            {"陕西省", "西安市"},
            {"河北省", "石家庄市"},
            {"黑龙江省", "哈尔滨"},
            {"江苏省", "南京市"},
        }

        // 第二种: 不带数组类型初始化列表
        array02 = [4][2]bool{
            {true, false},
            {true, true},
            {false, false},
        }

        // 第三种: 自行推断长度,多维数组只有第一层可以使用"..."来让编译器推导数组长度。
        array03 = [...][3]uint8{
            {1, 4, 7},
            {2, 5, 8},
            {3, 6, 9},
            {11, 22, 33},
            {44, 55, 66},
            {77, 88, 99},
        }

        // 不支持多维数组的内层使用"...",会编译报错: "invalid use of [...] array (outside a composite literal)"
        // array03 = [3][...]uint8{
        //     {11, 22, 33},
        //     {44, 55, 66},
        //     {77, 88, 99},
        // }
    )

    fmt.Printf("array01类型: %T,值: %v, 长度: %d\n", array01, array01, len(array01))
    fmt.Printf("array02类型: %T,值: %v, 长度: %d\n", array02, array02, len(array02))
    fmt.Printf("array03类型: %T,值: %v, 长度: %d\n", array03, array03, len(array03))

}

五.二维数组的遍历

1.基于for循环遍历

package main

import "fmt"

func main() {
    // 定义二维数组
    var city = [...][3]string{
        {"西安", "安康", "渭南"},
        {"石家庄", "邯郸", "保定"},
        {"郑州", "洛阳", "南阳"},
    }

    // 通过for循环遍历
    for i := 0; i < len(city); i++ {
        for j := 0; j < len(city[i]); j++ {
            fmt.Print(city[i][j], "\t")
        }
        fmt.Println()
    }

}

2.for range遍历

package main

import "fmt"

func main() {
    // 定义二维数组
    var province = [...][3]string{
        {"西安", "安康", "渭南"},
        {"石家庄", "邯郸", "保定"},
        {"郑州", "洛阳", "南阳"},
    }

    // 通过for-range循环遍历
    for index, city := range province {
        for key, value := range city {
            fmt.Printf("province[%d][%v] = %v\t\t", index, key, value)
        }
        fmt.Println()
    }

}

六.练习题

1.将10以内的奇数放在同一个数组中并求和

package main

import (
    "fmt"
)

func main() {
    // 题意: 将10以内的奇数放在同一个数组中并求和
    numberList := [5]int{1, 3, 5, 7, 9}

    var sum int

    for _, v := range numberList {
        sum += v
    }

    fmt.Println(sum)
}

2.找出数组中和为指定值的两个元素的下标

package main

import (
    "fmt"
)

func main() {
    // 找出数组中和为指定值的两个元素的下标,从数组[1,3,5,7,8]中找出和为8的两个元素元素的下标。

    // 需求分析:
    //         (1)一次取出每个元素;
    //        (2)计算一下: other = 8 - 当前值;
    //        (3)上一步计算出other的值后再和现有数组的元素进行比较,若存在就打印出来

    numberList := [5]int{1, 3, 5, 7, 8}

    for k1, v1 := range numberList {
        other := 8 - v1
        // 假设当前的索引是k1,则那另一个数字比较时选择索引位置加一即可。
        for k2 := k1 + 1; k2 < len(numberList); k2++ {
            if numberList[k2] == other {
                fmt.Println(k1, k2)
            }
        }

        // 采用下面的循环方式会重复取索引哟~
        // for k2, v2 := range numberList {
        //     if other == v2 {
        //         fmt.Println(k1, k2)
        //     }
        // }
    }
}
目录
相关文章
|
2月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
93 4
Golang语言之管道channel快速入门篇
|
2月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
87 3
Golang语言之gRPC程序设计示例
|
2月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
78 4
|
13天前
|
人工智能 前端开发 JavaScript
拿下奇怪的前端报错(一):报错信息是一个看不懂的数字数组Buffer(475) [Uint8Array],让AI大模型帮忙解析
本文介绍了前端开发中遇到的奇怪报错问题,特别是当错误信息不明确时的处理方法。作者分享了自己通过还原代码、试错等方式解决问题的经验,并以一个Vue3+TypeScript项目的构建失败为例,详细解析了如何从错误信息中定位问题,最终通过解读错误信息中的ASCII码找到了具体的错误文件。文章强调了基础知识的重要性,并鼓励读者遇到类似问题时不要慌张,耐心分析。
|
14天前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
|
1月前
|
存储 JavaScript 前端开发
JavaScript Array(数组) 对象
JavaScript Array(数组) 对象
23 3
|
15天前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
23 0
|
2月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
41 3
Golang语言之Prometheus的日志模块使用案例
|
27天前
|
数据采集 JavaScript 前端开发
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
JavaScript中通过array.filter()实现数组的数据筛选、数据清洗和链式调用,JS中数组过滤器的使用详解(附实际应用代码)
|
2月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
60 4
Golang语言文件操作快速入门篇