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

2024-06-20 15:52

本文主要是介绍【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

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

这篇关于【Golang - 90天从新手到大师】Day06 - 数组的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1078577

相关文章

KLayout ------ 旋转物体90度并做平移

KLayout ------ 旋转创建的物体 正文 正文 前段时间,有个小伙伴留言问我,KLayout 中如何旋转自己创建的物体,这里特来说明一下。 import pyapoly = pya.DPolygon([pya.DPoint(0, 0), pya.DPoint(0, 5), pya

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

IOS 数组去重的几种方式

本来只知道NSSet和KeyValues的。今天又新学了几种方式 还有就是和同事学的一种方式 外层循环从0开始遍历,内层从最后一个元素开始遍历 for(int i=0;i<index;i++){  for(int j=index-1;j>i;j-- ){ } }

[大师C语言(第三十六篇)]C语言信号处理:深入解析与实战

引言 在计算机科学中,信号是一种软件中断,它允许进程之间或进程与内核之间进行通信。信号处理是操作系统中的一个重要概念,它允许程序对各种事件做出响应,例如用户中断、硬件异常和系统调用。C语言作为一门接近硬件的编程语言,提供了强大的信号处理能力。本文将深入探讨C语言信号处理的技术和方法,帮助读者掌握C语言处理信号的高级技巧。 第一部分:C语言信号处理基础 1.1 信号的概念 在Unix-lik

Java基础(二)——数组,方法,方法重载

个人简介 👀个人主页: 前端杂货铺 ⚡开源项目: rich-vue3 (基于 Vue3 + TS + Pinia + Element Plus + Spring全家桶 + MySQL) 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步至千里,积小流成江海 🥇推荐学习:🍖开源 rich-vue3 🍍前端面试

poj 3882(Stammering Aliens) 后缀数组 或者 hash

后缀数组:  构建后缀数组,注意要在字符串莫末尾加上一个没出现过的字符。然后可以2分或者直接扫描,直接扫描需要用单调队列来维护 VIEW CODE #include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<queue>#include<stack>#include<string

poj 3294(Life Forms) 2分+ 后缀数组

我曾用字符串hash写,但是超时了。只能用后最数组了。大致思路:用不同的符号吧字符串连接起来,构建后缀数组,然后2分答案,依次扫描后缀数组,看是否瞒住条件。 VIEW CODE #include<cstdio>#include<vector>#include<cmath>#include<algorithm>#include<cstring>#include<cassert>#

C语言函数参数--数组长度

int read_column_numbers(int columns[], int max){} 在函数声明的数组参数中,并未指定数组的长度。这种格式是OK的,因为无论调用函数的程序传递给它的数组参数的长度是多少,这个函数都将照收不误。 这是一个伟大的特性,它允许单个函数操纵任意长度的一维数组。 这个特性不利的一面是函数没法知道该数组的长度。如果确实需要数组的长度,它的值必须作为一个单独的

从JavaScript 数组去重看兼容性问题,及性能优化(摘自玉伯博客)

缘由 JavaScript 数组去重经常出现在前端招聘的笔试题里,比如: 有数组 var arr = ['a', 'b', 'c', '1', 0, 'c', 1, '', 1, 0],请用 JavaScript 实现去重函数 unqiue,使得 unique(arr) 返回 ['a', 'b', 'c', '1', 0, 1, ''] 作为笔试题,考点有二: 正确。别小看这个考点

【Java】ArrayListString转化为String数组问题

Java的容器类Collections中toArray()方法,可以把诸如ArrayList<String>的动态数组、不定长转化静态数组、定长数组String[] 但是,如下的转化方式是错误的。 [java]  view plain copy String[] strArray = (String[]) arrayList.toArray();   如果这样执行会导致