【Golang - 90天从新手到大师】Day06 - 数组

 系列文章合集

Golang - 90天从新手到大师


数组是golang中最常用的一种数据结构,数组就是同一类型数据的有序集合

定义一个数组

格式: var name [n]type

n为数组长度,n>=0 且无法修改,type为数组的元素类型如:

var a [2]int

上面的例子定义了一个长度为2,元素类型为int的数组

数组长度作为数组类型的一部分,数组长度加数组元素类型才组成一个数组类型,如** [2]int** 与 ** [1]int** 不是同一个类型 所以不可以使用 == != 或进行赋值操作,

下面的程序是错误的

var a [2]int
var b [1]int
//下面的赋值是错误的
a = b

[2]int 与 [1]int 不是同一个类型

相同类型的的数组可以进行 ==与!=的比较操作

var a [2]int
var b [2]int
if a == b {fmt.Println("a = b")
}a[0] = 1
if a != b {fmt.Println("a != b")
}

数组元素的访问与修改

数组的下标是从0开始的整数,我们可以通过下表来访问或修改相对应的元素 如:

var a = [3]string{"zhangsan","lisi","wangwu"}
fmt.Println(a[0],a[1],a[2])
a[2] = "王五"
fmt.Println(a[0],a[1],a[2])

以上程序将输出:
zhangsan lisi wangwu
zhangsan lisi 王五

数组元素的默认值

数组定义后如果没有赋值或者数组内的元素没有完全赋值,那么未赋值的元素将会由元素类型的默认值填充,关于默认值详键 类型默认值章节

下面列举几个常见类型的数组

  • var a [2]int int类型元素的默认值为0

  • var b [2]string string类型元素的默认值为空字符串

  • var c [2]float64 float类型元素的默认值为0

  • var d [2]bool boolean类型元素的默认值为false

定义数组元素的初始值

我们可以在定义数组的时候指定数组的初始值

如:var a = [2]int{1, 2}

数组可以指定下标赋值,指定下标将被赋值的指定的值,而未指定的将有默认值填充

如:c := [10]bool{0: true, 2: true, 4: true, 6: true, 8: true}

如果不指定下标 则会由下标0开始 用指定的元素初始化 没有初始化到的 将用默认值填充

如:d := [5]string{"a", "b", "c"} 将输出 [a b c 空字符串 空字符串]

自动推断数组长度

假如我有一个元素类型为string的数组,里面定义了周一到周日,那么我可以不指定数组长度而由编译器推断

如:a := [...]string{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}

当然也可以用下标赋值的方式 go会自动创建一个满足条件的长度最小的数组

如:a := [...]string{2: "abc"} 将输出 [空字符串 空字符串 abc]

虽然我们可以在定义数组的时候不指定长度而由编译器推断,但不提倡这种方式

指针数组

数组元素的类型可以是任意相同的类型,所以,保存的元素为指针类型的数组就是指针数组 如:

a := [2]*int{}
x, y := 1, 2
a[0] = &x
a[1] = &y
fmt.Println(a)

a数组是一个指针数组,其中保存着变量x,y的指针

数组指针

数组指针就是指向一个数组的指针 如:

a := [5]int{1, 2, 3, 4, 5}
p := &a

数组p就是数组a的一个指针数组

获取数组的指针

使用new关键字获取数组的指针
如:a := new([2]int)
数组指针也可以对数组进行操作 方法与数组相同

数组是值类型

golang中的数组为值类型,传递进函数的时候传递的是数组的一个拷贝 看下面的一个例子

test := func(p [2]int) {p[0] = 123
}a := [2]int{1, 2}
fmt.Println("传递进函数前:", a)
test(a)
fmt.Println("传递进函数后:", a)

test是一个匿名函数,关于匿名函数的概念,我们将在后边详细介绍

我们可以通过查看数组元素的地址来确定他是引用类型还是值类型

func main(){b := func(p [2]int) [2]int {fmt.Println("函数内的数组元素的地址为", &p[0], &p[1])return p}var a = [2]int{1, 2}fmt.Println("函数外的数组元素的地址为", &a[0], &a[1])b(a)
}

执行结果为:
函数外的数组元素的地址为 0xc82000a290 0xc82000a298
函数内的数组元素的地址为 0xc82000a2b0 0xc82000a2b8

函数内的元素地址与函数外的不相同,因为元素发生了拷贝,所以在函数内修改数组元素内容是不会影像传入函数的参数数组,因为他仅仅是外部变量的一个拷贝

数组的遍历

数组可以通过for关键字来遍历 也可以使用for range关键字来同时遍历数组的值和键

package mainimport ("fmt"
)func main() {var a = [5]string{"a", "b", "c", "d", "e"}for i := 0; i < len(a); i++ {fmt.Println(a[i])}
}

以上程序会依此输出 a b c d e
数组的下标是从0开始的,**len() **函数用来计算数组或切片的元素个数,我们每次输出数组中的元素,然后将数组下标+1,随后再次访问数组的下一个元素,如果这个数组长度很长, **len(a) **这个计算最好在循环外边计算好,而不是每次循环的时候去计算,这样可以提高程序的执行速度,这里为了好理解所以写在了循环里

也可以使用for配合range来遍历,把上边的程序修改一下

package mainimport ("fmt"
)func main() {var a = [5]string{"a", "b", "c", "d", "e"}for i, value := range a {fmt.Println("数组下标是", i, "对应的值为", value)}
}

以上程序会输出
数组下标是 0 对应的值为 a
数组下标是 1 对应的值为 b
数组下标是 2 对应的值为 c
数组下标是 3 对应的值为 d
数组下标是 4 对应的值为 e
i为数组的下标 value为下标对应的值

由于golang严格规定了定义的变量必需要使用,如果我们仅仅是想遍历数组的value而不关心索引i的时候,可以使用_(下划线)来忽略 如 for _, value := range a{}

值得一提的是,字符串实质上也是个数组,所以也可以使用len()来计算长度,使用 for range关键字来循环遍历,也可以通过下标访问

var a string = "abc"
fmt.Println(string(a[0]), a[1], a[2])var a string = "找女友"
for k, value := range a {fmt.Println(k, string(value))
}

注意:utf8编码下一个汉字长度为3个字节(大部份情况下,实质上中文的长度为2-4 ) ,中文字符串遍历的时候下标一次增加3

多维数组


Go 语言支持多维数组,以下为常用的多维数组声明方式:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

以下实例声明了三维的整型数组:

var threedim [5][10][4]int

二维数组

二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:

var arrayName [ x ][ y ] variable_type

variable_type 为 Go 语言的数据类型,arrayName 为数组名,二维数组可认为是一个表格,x 为行,y 为列,下图演示了一个二维数组 a 为三行四列:

图片

二维数组中的元素可通过 a[ i ][ j ] 来访问。

初始化二维数组

多维数组可通过大括号来初始值。以下实例为一个 3 行 4 列的二维数组:

a = [3][4]int{  {0, 1, 2, 3} ,   /*  第一行索引为 0 */{4, 5, 6, 7} ,   /*  第二行索引为 1 */{8, 9, 10, 11}   /*  第三行索引为 2 */
}

访问二维数组

二维数组通过指定坐标来访问。如数组中的行索引与列索引,例如:

int val = a[2][3]

以上实例访问了二维数组 val 第三行的第四个元素。

二维数组可以使用循环嵌套来输出元素:

package mainimport "fmt"func main() {/* 数组 - 5 行 2 列*/var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}var i, j int/* 输出数组元素 */for  i = 0; i < 5; i++ {for j = 0; j < 2; j++ {fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )}}
}

以上实例运行输出结果为:

a[0][0] = 0
a[0][1] = 0
a[1][0] = 1
a[1][1] = 2
a[2][0] = 2
a[2][1] = 4
a[3][0] = 3
a[3][1] = 6
a[4][0] = 4
a[4][1] = 8

数组是值类型

数组是值类型 Go中的数组是值类型,而不是引用类型。这意味着当它们被分配给一个新变量时,将把原始数组的副本分配给新变量。如果对新变量进行了更改,则不会在原始数组中反映。

package mainimport "fmt"func main() {  a := [...]string{"USA", "China", "India", "Germany", "France"}b := a // a copy of a is assigned to bb[0] = "Singapore"fmt.Println("a is ", a)fmt.Println("b is ", b) 
}

运行结果:

a is [USA China India Germany France]  
b is [Singapore China India Germany France] 

数组的大小是类型的一部分。因此[5]int和[25]int是不同的类型。因此,数组不能被调整大小。不要担心这个限制,因为切片的存在是为了解决这个问题。

package mainfunc main() {  a := [3]int{5, 78, 8}var b [5]intb = a //not possible since [3]int and [5]int are distinct types
}

Go 语言向函数传递数组


如果你想向函数传递数组参数,你需要在函数定义时,声明形参为数组,我们可以通过以下两种方式来声明:

方式一

形参设定数组大小:

void myFunction(param [10]int)
{
.
.
.
}

方式二

形参未设定数组大小:

void myFunction(param []int)
{
.
.
.
}

实例

让我们看下以下实例,实例中函数接收整型数组参数,另一个参数指定了数组元素的个数,并返回平均值:

func getAverage(arr []int, int size) float32
{var i intvar avg, sum float32  for i = 0; i < size; ++i {sum += arr[i]}avg = sum / sizereturn avg;
}

接下来我们来调用这个函数:

package mainimport "fmt"func main() {/* 数组长度为 5 */var  balance = []int {1000, 2, 3, 17, 50}var avg float32/* 数组作为参数传递给函数 */avg = getAverage( balance, 5 ) ;/* 输出返回的平均值 */fmt.Printf( "平均值为: %f ", avg );
}
func getAverage(arr []int, size int) float32 {var i,sum intvar avg float32  for i = 0; i < size;i++ {sum += arr[i]}avg = float32(sum / size)return avg;
}

以上实例执行输出结果为:

平均值为: 214.000000

以上实例中我们使用的形参并为设定数组大小。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/357430.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dubbo快速入门

1. Dubbo概述 官网地址&#xff1a;https://cn.dubbo.apache.org/zh-cn/ Apache Dubbo 是一款高性能的轻量级的Java RPC框架&#xff0c;可以和Spring框架无缝集成。 本地调用&#xff1a;本机调用&#xff0c;指同个JVM内部的方法调用&#xff0c;例如三层架构之间的方法调用…

虚拟机IP地址频繁变化的解决方法

勾八动态分配IP&#xff0c;让我在学习redis集群的时候&#xff0c;配置很多的IP地址&#xff0c;但是由于以下原因导致我IP频繁变动&#xff0c;报错让我烦恼&#xff01;&#xff01;&#xff01;&#xff01; 为什么虚拟机的IP地址会频繁变化&#xff1f; 虚拟机IP地址频繁…

NV-Embed论文阅读笔记

这是NVIDIA的一篇论文&#xff0c;LLM通常使用的是GPT的decoder范式作为一个生成模型&#xff0c;文章探讨如何利用这样的decoder生成模型来实现BERT这样的encoder的功能&#xff0c;即提取有效的embedding。现有的方法提取embedding的方式无非是 1 mean pooling&#xff1b; 2…

32 - 判断三角形(高频 SQL 50 题基础版)

32 - 判断三角形 select *,if(xy>z and xz>y and zy > x,Yes,No) triangle fromTriangle;

基于simulink的PEM燃料电池控制系统建模与仿真,对比PID,积分分离以及滑模控制器

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 PID控制器 4.2 积分分离PID控制器 4.3 滑模控制器 5.完整工程文件 1.课题概述 基于simulink的PEM燃料电池控制系统建模与仿真,对比PID,积分分离以及滑模控制器。 2.系统仿真结果 &#xff08;完…

2024全国高校名单发布,电子版下载!

今天&#xff0c;教育部网站发布了《全国高等学校名单》。截至2024年6月20日&#xff0c;全国高等学校共计3117所&#xff0c;其中&#xff1a;普通高等学校2868所&#xff0c;含本科学校1308所、高职&#xff08;专科&#xff09;学校1560所&#xff1b;成人高等学校249所。本…

Nikto一键扫描Web服务器(KALI工具系列三十)

目录 1、KALI LINUX 简介 2、Nikto工具简介 3、信息收集 3.1 目标IP&#xff08;服务器) 3.2kali的IP 4、操作实例 4.1 基本扫描 4.2 扫描特定端口 4.3 保存扫描结果 4.4 指定保存格式 4.5 连接尝试 4.6 仅扫描文件上传 5、总结 1、KALI LINUX 简介 Kali Linux 是一…

Django 模版变量

1&#xff0c;模版变量作用 模板变量使用“{{ 变量名 }}” 来表示模板变量前后可以有空格&#xff0c;模板变量名称&#xff0c;可以由数字&#xff0c;字母&#xff0c;下划线组成&#xff0c;不能包含空格模板变量还支持列表&#xff0c;字典&#xff0c;对象 2&#xff0c;…

平面设计软件PS/AI/ID/CDR怎么选怎么下载(附教程)

随着设计行业的普遍化&#xff0c;平面设计软件也越来越多且功能越来越强大。平面设计软件需要在电脑上运行使用&#xff0c;来进行平面画面、平面文字的设计工作。如大家所了解的&#xff0c;Adobe Photoshop、Adobe Illustrator、CorelDRAW、Adobe InDesign是平面设计中最常用…

playwright vscode 插件源码解析

Playwright vscode插件主要功能 Playwright是微软开发的一款主要用于UI自动化测试的工具&#xff0c;在vscode中上安装playwright vscode插件&#xff0c;可以运行&#xff0c;录制UI自动化测试。 playwright vscode插件主要包括两块功能&#xff0c;功能一是在Test Explorer中…

机器学习课程复习——奇异值分解

1. 三种奇异值分解 奇异值分解&#xff08;Singular Value Decomposition, SVD&#xff09;包含了&#xff1a; 完全奇异值分解&#xff08;Complete Singular Value Decomposition, CSVD&#xff09;紧奇异值分解&#xff08;Tight Singular Value Decomposition, TSVD&…

快速UDP网络连接之QUIC协议介绍

文章目录 一、QUIC协议历史1.1 问题&#xff1a;QUIC为什么在应用层实现1.2 QUIC协议相关术语1.3 QUIC和TCP对比1.4 QUIC报文格式1.4.1 QUIC报文格式-Stream帧11.4.2 QUIC报文格式-Stream帧2 二、QUIC的特点2.1 连接建立低时延&#xff0c;2.2 多路复用流复用-HTTP1.1流复用-HT…

ubuntu22.04笔记: 更换为阿里源

没有按照LTS 版本 会遇到下面问题&#xff1a; 参考&#xff1a;https://zhuanlan.zhihu.com/p/691625646 Ubuntu 22.04代号为&#xff1a;jammy Ubuntu 20.04代号为&#xff1a;focal Ubuntu 19.04代号为&#xff1a;disco Ubuntu 18.04代号为&#xff1a;bionic Ubuntu …

ReactNative和Android通信

初始化一个RN项目以后&#xff0c;接下来想要让Android与React Native通信 写一个继承自ReactContextBaseJavaModule类的子类&#xff0c;重写getName方法 package com.awesomeprojectimport android.util.Log import android.widget.Toast import com.facebook.react.bridge.…

Apache Doris 之 Docker 部署篇

前言 在现代数据驱动的商业环境中&#xff0c;实时数据分析和高并发查询能力是企业成功的关键因素之一。传统的数据仓库和分析工具在面对大规模数据处理和实时分析需求时&#xff0c;往往力不从心。Apache Doris 作为一个现代的 MPP 数据库管理系统&#xff0c;凭借其强大的查…

最新Sublime Text软件安装包分享(汉化版本)

Sublime Text 是一款广受欢迎的跨平台文本编辑器&#xff0c;专为代码、标记和散文编辑而设计。它以其简洁的用户界面、强大的功能和高性能而著称&#xff0c;深受开发者和写作者的喜爱。 一、下载地址 链接&#xff1a;https://pan.baidu.com/s/1kErSkvc7WnML7fljQZlcOg?pwdk…

监控 Prometheus源码安装实战和动态更新 Centos7

安装go环境 下载go安装包 #创建文件夹 mkdir /usr/local/software #进入文件夹 cd /usr/local/software #下载安装包 wget https://dl.google.com/go/go1.17.6.linux-amd64.tar.gz配置go环境变量 #解压 tar -zxvf go1.17.6.linux-amd64.tar.gz#配置环境变量 echo "exp…

【GD32】从零开始学兆易创新32位微处理器——RTC实时时钟+日历例程

1 简介 RTC实时时钟顾名思义作用和墙上挂的时钟差不多&#xff0c;都是用于记录时间和日历&#xff0c;同时也有闹钟的功能。从硬件实现上来说&#xff0c;其实它就是一个特殊的计时器&#xff0c;它内部有一个32位的寄存器用于计时。RTC在低功耗应用中可以说相当重要&#xf…

【调试笔记-20240619-Windows-Typescripts中类型不匹配的解决方法】

调试笔记-系列文章目录 调试笔记-20240619-Windows-Typescripts中类型不匹配的解决方法 文章目录 调试笔记-系列文章目录调试笔记-20240619-Windows-Typescripts中类型不匹配的解决方法 前言一、调试环境操作系统&#xff1a;Windows 10 专业版调试环境调试目标 二、调试步骤搜…

Linux 五种IO模型

注&#xff1a;还有一种信号驱动IO&#xff0c;使用较少暂不讨论&#xff1b; 一&#xff0c;区分阻塞、非阻塞和同步、异步 看了很多文章对这两组概念解释和对比&#xff0c;说的太复杂了&#xff0c;其实没必要&#xff0c;两句话就能说清楚。 首先&#xff0c;对于读数据rec…