《Go程序设计语言》学习笔记之数组

一. 环境

  Centos8.5, go1.17.5 linux/amd64

二. 概念

  数组是具有固定长度且拥有零个或多个相同数据类型元素的序列。

三. 声明

声明一个数组a,然后打印数组、数组a的长度、数组a的类型。从打印的a的类型中可以看出数组的长度是类型的一部分

// test sample
package main import (
"fmt"
) func main() {
var a [3]int
fmt.Printf("a: %d\n", a)
fmt.Printf("len: %d\n", len(a))
fmt.Printf("type: %T\n", a)
}

运行结果如下

 

四. 初始化

声明与初始化个人感觉是C/C++中的说法,严格来说在Go中不太严谨。在Go中,定义的变量,如果没有显式初始化的话,变量会默认初始化。也就是说,声明即是初始化。Go中有个零值机制。零值机制保障所有的变量是良好定义的,Go里面不存在未初始化变量。

下面示例了4种初始化的方式

第一种,声明了一个长度为3的整型数组a,从打印结果来看, 每个元素初始值为零值。

第二种,声明了一个长度为3的整型数组b,使用数组字面量初始化一个数组。字面量数组中只有两个元素,但是数组b的长度为3,最后一个元素的初始值为零值。

第三种,使用短变量声明的形式,使用数组字面量来初始化整型数组c,数组字面量中的长度是”...“,则数组的长度由初始化数组的元素个数决定。

第四种,先使用常量计数器iota声明一组常量值作为下标,然后将下标与对应位置上的元素的值对应起来。这种的方式好处就是索引可以按照任意顺序出现。

 8 func main() {
9 // init way1, zero value
10 var a [3]int
11 for _, v := range a {
12 fmt.Printf("%d\t", v)
13 }
14 fmt.Printf("\n")
15
16 // init way2
17 fmt.Println("----------")
18 var b [3]int = [3]int{1, 2}
19 for _, v := range b {
20 fmt.Printf("%d\t", v)
21 }
22 fmt.Printf("\n")
23
24 // init way3
25 fmt.Println("----------")
26 c := [...]int{4, 5, 6}
27 for _, v := range c {
28 fmt.Printf("%d\t", v)
29 }
30 fmt.Printf("\n")
31
32 // init way4
33 fmt.Println("----------")
34 type Currency int
35
36 const (
37 USD Currency = iota
38 EUR
39 GBP
40 RMB
41 )
42
43 symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}
44 for _, v := range symbol {
45 fmt.Printf("%s\t", v)
46 }
47 fmt.Printf("\n")
48 } 

运行结果如下

五. 访问

数组中的元素可通过下标进行访问  

  8 func main() {
9 arr := [3]string{"China", "America", "Japan"}
10 fmt.Printf("%s\n", arr[0])
11 fmt.Printf("%s\n", arr[1])
12 fmt.Printf("%s\n", arr[2])
13 }

运行结果如下

六. 使用

1.变量

作变量使用,这个没什么好说的了。

2.修改元素的值

1) 通过下标指定元素,对指定的元素进行修改

 8 func main() {
9 a1 := [...]int{1, 2, 3}
10
11 for i, _ := range a1 {
12 a1[i] += 4
13 }
14
15 fmt.Printf("%d %d %d\n", a1[0], a1[1], a1[2])
16 }

 运行结果如下

2) 笔者用过的错误的修改方式,有些想当然了。

Go中基本是值语义的,即是值传递的

for循环中,v是数组中元素的一个副本,对副本的修改不会对原始元素产生影响 

  8 func main() {
9 a1 := [...]int{1, 2, 3}
10
11 for _, v := range a1 {
12 v += 4
13 }
14
15 fmt.Printf("%d %d %d\n", a1[0], a1[1], a1[2])
16 }

  运行结果如下,并未修改成功。

3.比较

如果一个数组的元素类型是可比较的,那这个数组也是可比较的。

  8 func main() {
9 a1 := [...]int{1, 2, 3}
10 a2 := [...]int{1, 2, 4}
11 a3 := [3]int{1, 2, 3}
12 fmt.Printf("%t %t %t\n", a1 == a2, a1 == a3, a2 == a3)
13 } 

运行结果如下

若两个数组的类型不一致,则不允许进行比较

 14     a4 := [4]int{1, 2, 3, 4}
15 fmt.Printf("%t\n", a1 == a4) 

编译时报错如下,提示无效操作

invalid operation: a1 == a4 (mismatched types [3]int and [4]int)

4.作函数参数

Go中,数组是值传递的。一般是传递一个数组的指针,这样有两个好处,一是对于较大的数组,效率较高; 二是可以对原数组进行修改。下面示例两种传参方式

1) 值传递,在被调用函数 modifyArrayElement 中,通过打印结果可以看到是修改成功了,但是这只是对传入的数组的副本进行了修改,对原始数组并未产生影响。

  8 func modifyArrayElement(array [5]int) {
9 array[0] += 10
10 array[1] += 10
11 array[2] += 10
12 array[3] += 10
13 array[4] += 10
14
15 fmt.Println("...in function...")
16 for _, v := range array {
17 fmt.Println(v)
18 }
19 fmt.Println("...in function...")
20 }
21
22 func main() {
23 a1 := [...]int{1, 2, 3, 4, 5}
24 fmt.Println(a1)
25
26 modifyArrayElement(a1)
27 fmt.Println(a1)
28 }

运行结果如下

2) 指针传递,在被调用函数 modifyArrayElement 的参数中,传入的是长度为5的数组的指针,通过指针可以对原数组进行修改。代码第9行和第10行array前的解引用符号"*"可以省略,可进行隐式转化。

  8 func modifyArrayElement(array *[5]int) {
9 for i, _ := range *array {
10 (*array)[i] += 10
11 }
12 }
13
14 func main() {
15 a1 := [...]int{1, 2, 3, 4, 5}
16 fmt.Println(a1)
17
18 modifyArrayElement(&a1)
19 fmt.Println(a1)
20 }

 运行结果如下

5.赋值

可以将一个数组赋值给另一个数组

1) 将数组b赋值给数组a

  8 func main() {
9 a := [...]int{1, 2, 3}
10 fmt.Println(a)
11 b := [3]int{4, 5, 6}
12
13 a = b
14 fmt.Println(a)
15 }
16

运行结果如下

2) 通过清零函数zero将传入的数组清零,对传入的数组指针进行解引用,然后对数组进行赋值,完成清零操作。

  8 func zero(array *[5]int) {
9 *array = [5]int{}
10 }
11
12 func main() {
13 a := [...]int{1, 2, 3, 4, 5}
14 fmt.Println(a)
15
16 zero(&a)
17 fmt.Println(a)
18 }

运行结果如下

4.与slice结合使用

具体参考slice一文

七. 注意

1) 适用场景

适用于固定长度的序列,如使用SHA256加密散列生成的摘要,其长度为256位,即[32]byte。

2) 越界

在访问或修改数组中的元素时,注意越界的问题

示例代码

  8 func main() {
9 a := [...]int{1, 2, 3, 4, 5}
10
11 fmt.Println(a)
12 fmt.Println(a[5])
13 }

编译时,提示无效的数组索引5

八.疑问

数组中的元素可以是哪些类型?

1) 基本类型

2) 数组类型

  8 func main() {
9 // element type: int
10 a1 := [...]int{1, 2, 3, 4, 5}
11 a11 := [...]int{11, 22, 33, 44, 55}
12 a111 := [...]int{11, 22, 33, 44, 55}
13
14 // element type: string
15 a2 := [...]string{"aa", "bb", "cc", "dd", "ee"}
16
17 // element type: bool
18 a3 := [5]bool{true, false, false, false, false}
19
20 // element type: array
21 a4 := [3][5]int{a1, a11}
22
23 fmt.Println(a1)
24 fmt.Println(a11)
25 fmt.Println(a111)
26
27 fmt.Println("----------")
28 fmt.Println(a2)
29 fmt.Println(a3)
30 fmt.Println(a4)
31 }

运行结果如下

其它类型待完善 

《Go程序设计语言》学习笔记之数组的更多相关文章

  1. c语言学习笔记 函数数组传递笔记

    今天学习c语言的一个小例子,果然还是陷入了php的编程习惯里,这里记录一下. #include <stdio.h> //例子很简单,就是编写一个函数把传递进来的数组里的值都赋值为1而已 / ...

  2. C语言学习笔记 (007) - 数组指针和通过指针引用数组元素的方法总结

    1.数组指针:即指向数组的指针 那么, 如何声明一个数组指针呢? ]; /*括号是必须写的,不然就是指针数组:10是数组的大小*/ 拓展:有指针类型元素的数组称为指针数组. 2.通过指针引用数组元素的 ...

  3. C语言学习笔记 (004) - 数组名和数组首地址(转)

    一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址.指针变量既然可以指向变量,当然也可以指向数组和数组元素(把数据起始地址或某一元素的地址放到一个指针变量中) ...

  4. C程序设计语言学习笔记

    在Windows下运行C语言程序 Windows下的编程工具使用 VC 6.0,下面讲解如何在VC 6.0下运行上节的"Hello, world"程序. 1) 新建Win32 Co ...

  5. Go语言学习笔记(4)——数组和切片

    1 数组的特点: 长度固定.元素数据类型相同.下标从0开始 1.1 声明和初始化: var array_name [size] type         var arr1 [10] float32   ...

  6. C语言学习笔记之数组与指针的关系

    首先,大家先需知道一个关于基类型的概念 基类型:组成一个新类型的基础类型 这句话是什么意思呢?举个例子: int a[3] = {1,2,3}; 上面是由三个int类型的数组成一个新的类型也就是数组, ...

  7. go语言学习笔记之数组

    package main import ( "fmt" ) func main() { // Declare arrays var x[5] int //Assign value ...

  8. GO语言学习笔记(一)

    GO语言学习笔记 1.数组切片slice:可动态增长的数组 2.错误处理流程关键字:defer panic recover 3.变量的初始化:以下效果一样 `var a int = 10` `var ...

  9. Go语言学习笔记八: 数组

    Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...

  10. PHP学习笔记之数组篇

    摘要:其实PHP中的数组和JavaScript中的数组很相似,就是一系列键值对的集合.... 转载请注明来源:PHP学习笔记之数组篇   一.如何定义数组:在PHP中创建数组主要有两种方式,下面就让我 ...

随机推荐

  1. CF1822F Gardening Friends

    题目链接 题解 知识点:树的直径,枚举. 考虑一个结论:树上任意点的最远点一定是树的直径的端点. 那么对于一个根节点,只要知道了树的直径,那么我们就可以立即得到最远距离,即乘 \(k\) 树的价值. ...

  2. SSD 简介—— NAND 芯片介绍

    制作 存储芯片的制作和其他芯片制作大致相同,从沙子中提取单晶硅制作晶圆再封装芯片. 闪存芯片从架构上分为NOR和NAND NOR Flash的source line把每个cell都并联起来,而NAND ...

  3. .net core微服务之服务发现

    一:nacos https://nacos.io/docs/latest/what-is-nacos/ https://github.com/alibaba/nacos 二:consul https: ...

  4. STC89C52驱动MAX7219LED点阵级联, 文字滚动效果

    级联下的传值方式 级联下, N个MAX7219相当于组成了一个8*N bit宽度的锁存器, 如果需要对第M个7219进行写入, 需要做M次寻址+写入后拉高CS, 才能到达这个7219. 如果仅仅对这个 ...

  5. 大米新闻微信小程序和Springboot新闻管理系统项目源码

    介绍 本项目分为大米news小程序端和springboot新闻管理系统后台项目.小程序主要用来新闻展示,后台管理系统用于提供相关新闻API. 项目源码 参考:https://www.bilibili. ...

  6. [攻防世界][Web]PHP2

    打开靶机对应的url 就一行字 Can you anthenticate to this website? 第一感觉就需要做目录文件扫描 使用御剑和dirsearch进行扫描,发现一个文件 index ...

  7. 全表查询sql执行链路排查

    问题描述: 发现有sql查询全表数据,慢查询语句,根据druid上的sql监控查看到. 主要根据标红的列确定问题sql. 点击进去可以看到详细sql信息. 问题排查目标: 发现这个语句高层调用方特别多 ...

  8. 【Azure 应用服务】能否通过 Authentication 模块配置 Azure AD 保护 API 应用?

    问题描述 在App Service Authentication 中配置 Azure AD 注册的应用信息后,根据官方文档,可以让前端应用实现用户 AAD 登录,然后通过前端应用获取的Token,来访 ...

  9. 【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn

    问题描述 App Service 配置 Application Settings 访问Storage Account.如下: { "name": "WEBSITE_CON ...

  10. C++的智能指针

    #pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问题 ,指针指针需要的是浅拷贝,并且需要处理资源释放问题 ...