《Go程序设计语言》学习笔记之数组
《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程序设计语言》学习笔记之数组的更多相关文章
- c语言学习笔记 函数数组传递笔记
今天学习c语言的一个小例子,果然还是陷入了php的编程习惯里,这里记录一下. #include <stdio.h> //例子很简单,就是编写一个函数把传递进来的数组里的值都赋值为1而已 / ...
- C语言学习笔记 (007) - 数组指针和通过指针引用数组元素的方法总结
1.数组指针:即指向数组的指针 那么, 如何声明一个数组指针呢? ]; /*括号是必须写的,不然就是指针数组:10是数组的大小*/ 拓展:有指针类型元素的数组称为指针数组. 2.通过指针引用数组元素的 ...
- C语言学习笔记 (004) - 数组名和数组首地址(转)
一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址.指针变量既然可以指向变量,当然也可以指向数组和数组元素(把数据起始地址或某一元素的地址放到一个指针变量中) ...
- C程序设计语言学习笔记
在Windows下运行C语言程序 Windows下的编程工具使用 VC 6.0,下面讲解如何在VC 6.0下运行上节的"Hello, world"程序. 1) 新建Win32 Co ...
- Go语言学习笔记(4)——数组和切片
1 数组的特点: 长度固定.元素数据类型相同.下标从0开始 1.1 声明和初始化: var array_name [size] type var arr1 [10] float32 ...
- C语言学习笔记之数组与指针的关系
首先,大家先需知道一个关于基类型的概念 基类型:组成一个新类型的基础类型 这句话是什么意思呢?举个例子: int a[3] = {1,2,3}; 上面是由三个int类型的数组成一个新的类型也就是数组, ...
- go语言学习笔记之数组
package main import ( "fmt" ) func main() { // Declare arrays var x[5] int //Assign value ...
- GO语言学习笔记(一)
GO语言学习笔记 1.数组切片slice:可动态增长的数组 2.错误处理流程关键字:defer panic recover 3.变量的初始化:以下效果一样 `var a int = 10` `var ...
- Go语言学习笔记八: 数组
Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...
- PHP学习笔记之数组篇
摘要:其实PHP中的数组和JavaScript中的数组很相似,就是一系列键值对的集合.... 转载请注明来源:PHP学习笔记之数组篇 一.如何定义数组:在PHP中创建数组主要有两种方式,下面就让我 ...
随机推荐
- 解决highlightjs中纯文本被解析成HTML无法展示的问题,记一次工作中bug修复的思考
壹 ❀ 引 在本周迭代bug修复工作中,遇到了两个比较头疼的bug(同一个客户所提),bug问题描述也很奇怪,客户表示产品的富文本编辑器里的代码块功能,在纯文本语言模式下贴特定代码进去有的看不见,有的 ...
- Kubernetes上使用Ingress Nginx将服务发布到外部IP
Kubernetes的网络结构 K8s的网络相对比较复杂, 包含了如下几类IP地址: Host Network 运行K8s集群的宿主服务器的内网IP, 其网段在配置宿主机时设置. 这些服务器可能是物理 ...
- Js中Math对象
Js中Math对象 Math是一个内置对象,它拥有一些数学常数属性和数学函数方法,Math用于Number类型,其不支持BigInt. 描述 Math不是一个函数对象,也就是说Math不是一个构造器, ...
- linux 快速安装LAMP教程
最近学习linux,安装lamp遇到一些问题,记录下来分享一下: ------------------------------------------------------------------- ...
- 从 vs 的 rc 文件中获取版本号
更新项目版本号时,需要与 rc 文件的 version 同步,比较方便的方法是直接从 rc 文件中获取版本号,并应用到程序中 // 删除日志检查 bool GetVersion() { // get ...
- 网络上收集的C++常见面试题
1. 进程与线程的关系,图解 进程简单理解就是我们平常使用的程序,进程拥有自己独立的内存空间地址,拥有一个以上的线程. 线程可以理解为轻量级的进程,是程序执行的最小单元.在某个进程启动后,会默认产生一 ...
- Spring使用注解方式进行事务管理
目录 使用步骤: 步骤一.在spring配置文件中引入tx:命名空间 步骤二.具有@Transactional 注解的bean自动配置为声明式事务支持 步骤三.在接口或类的声明处 ,写一个@Trans ...
- 【Azure 应用服务】应用代码中需要使用客户端证书访问服务接口,部署在应用服务后报错不能找到证书(Cannot find the X.509 certificate)
问题描述 在应用中,需要访问另一个服务接口,这个接口需要使用客户端证书进行认证.在代码中使用 System.Security.Cryptography.X509Certificates 加载Windo ...
- 菜单导航tab切换样式的小技巧
1.最终效果 2.HTML结构 <div class="licaiMenu"> <ul class="navi"> <li> ...
- Excel去除表格密码保护
表格受密码保护时,我们修改数据Excel弹出"您试图更改的单元格或图表受保护,因而是只读的.若要修改受保护单元格或图表,请先使用'撤消工作表保护'命令(在'审阅'选项卡的'更改'组中)来取消 ...