Go语言学习之数组的用法详解
引言
数组是相同数据类型的一组数据的集合,数组一旦定义长度不能修改,数组可以通过下标(或者叫索引)来访问元素。
相对于去声明 number0, number1, ..., number99 的变量,使用数组形式 numbers[0], numbers[1] ..., numbers[99] 更加方便且易于扩展。
数组元素可以通过索引(位置)来读取(或者修改),索引从0 开始,第一个元素索引为 0,第二个索引为1,以此类推。
一、数组的定义
1. 语法
var variable_name [SIZE] variable_type
variable_name:数组的名称
SIZE:数组长度,必须是常量
variable_type:数组保存元素的类型
2. 示例
package main import "fmt" func main() { var a [3]int //定义一个int类型的数组a,长度是3 var b [2]string //定义一个字符串类型的数组b,长度是2 fmt.Printf("a: %T\n", a) //使用%T来输出类型 fmt.Printf("b: %T\n", b) fmt.Printf("a: %v\n", a) fmt.Printf("b: %v\n", b) } //输出结果如下,可以看到没初始化的值,int是0,而字符串则是空的字符串 a: [3]int b: [2]string a: [0 0 0] b: [ ]
从上面运行的结果中可以看出来,数组和长度和元素类型共同组成了数组的类型
二、数组的初始化
初始化,就是给数组的元素赋值,没有初始化的数组,默认元素值都是零值,布尔类型是false,字符串是空字符串。
1. 未初始化的数组
package main import "fmt" func main() { var a [2]bool var b [2]int var c [3]string var d [3]float32 fmt.Printf("a: %v\n", a) fmt.Printf("b: %v\n", b) fmt.Printf("c: %v\n", c) fmt.Printf("d: %v\n", d) } //输出结果如下 a: [false false] b: [0 0] c: [ ] d: [0 0 0]
2. 使用初始化列表
package main import "fmt" func main() { var a = [3]int{1, 2, 3} var b = [2]string{"hello world"} var c = [2]bool{true, false} a1 := [2]int{1, 2} //类型推断 fmt.Printf("a: %v\n", a) fmt.Printf("b: %v\n", b) fmt.Printf("c: %v\n", c) fmt.Printf("a1: %v\n", a1) } //输出结果如下 a: [1 2 3] b: [hello world ] c: [true false] a1: [1 2]
使用初始化列表,就是将值写在大括号里面
3. 省略数组长度
如果数组长度不确定,可以使用 ...
代替数组的长度,编译器会根据元素个数自行推断数组的长度
package main import "fmt" func main() { var a = [...]int{1, 2, 3, 4, 5} var b = [...]string{"hello", "world", "hello", "go"} var c = [...]bool{true, false} a1 := [...]int{1, 2} //类型推断 fmt.Printf("a: %v\n", a) fmt.Printf("b: %v\n", b) fmt.Printf("c: %v\n", c) fmt.Printf("a1: %v\n", a1) } //输出结果如下 a: [1 2 3 4 5] b: [hello world hello go] c: [true false] a1: [1 2]
4. 指定索引值的方式来初始化
可以通过指定所有方式来初始化,未指定的所有默认值为零值
package main import "fmt" func main() { var a = [...]int{0: 1, 2: 2} var b = [...]string{1: "hello", 2: "go"} var c = [...]bool{2: true, 5: false} a1 := [...]int{1, 2} //类型推断 fmt.Printf("a: %v\n", a) fmt.Printf("b: %v\n", b) fmt.Printf("c: %v\n", c) fmt.Printf("a1: %v\n", a1) } //输出结果如下 a: [1 0 2] b: [ hello go] c: [false false true false false false] a1: [1 2]
总结
初始化数组中{}中的元素个数不能大于[]中的数字。
如果忽略[]中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:
5. 访问数组元素
数组元素可以通过索引(位置)来读取。
格式为数组名后加中括号,中括号中为索引的值。数组的最大下标为数组长度-1,大于这个下标会发生数组越界。
示例
package main import "fmt" func main() { var a [2]int a[0] = 100 a[1] = 200 fmt.Printf("a[0]: %v\n", a[0]) fmt.Printf("a[1]: %v\n", a[1]) //对数组进行修改 a[0] = 1 a[1] = 2 fmt.Println("---------修改后--------") fmt.Printf("a[0]: %v\n", a[0]) fmt.Printf("a[1]: %v\n", a[1]) } //输出结果如下 a[0]: 100 a[1]: 200 ---------修改后-------- a[0]: 1 a[1]: 2
6. 根据数组长度遍历数组
可以根据数组长度,通过for
循环的方式来遍历数组,数组的长度可以使用len
函数获得
使用len()
函数获取数组的长度
package main import "fmt" func main() { var a1 = [3]int{1, 2, 3} fmt.Printf("len(a1): %v\n", len(a1)) var a2 = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} fmt.Printf("len(a2): %v\n", len(a2)) } //输出结果如下 len(a1): 3 len(a2): 9
数组遍历,根据长度和下标
package main import "fmt" func main() { a := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i := 0; i < len(a); i++ { fmt.Printf("a[%d]:%v\n", i, a[i]) } } //输出结果如下 a[0]:1 a[1]:2 a[2]:3 a[3]:4 a[4]:5 a[5]:6 a[6]:7 a[7]:8 a[8]:9
使用for range
package main import "fmt" func main() { var a = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i, v := range a { //i也可以使用空白标识符代替,不接受索引的值 fmt.Printf("a[%v]:%v\n", i, v) } } //输出结果如下 a[0]:1 a[1]:2 a[2]:3 a[3]:4 a[4]:5 a[5]:6 a[6]:7 a[7]:8 a[8]:9
三. 访问数组元素
1. 访问数组元素
- 数组元素可以通过索引(位置)来读取。
- 格式为数组名后加中括号,中括号中为索引的值。数组的最大下标为数组长度-1,大于这个下标会发生数组越界。
示例 ①
package main import "fmt" func main() { var a [2]int a[0] = 100 a[1] = 200 fmt.Printf("a[0]: %v\n", a[0]) fmt.Printf("a[1]: %v\n", a[1]) //对数组进行修改 a[0] = 1 a[1] = 2 fmt.Println("---------修改后--------") fmt.Printf("a[0]: %v\n", a[0]) fmt.Printf("a[1]: %v\n", a[1]) } //输出结果如下 a[0]: 100 a[1]: 200 ---------修改后-------- a[0]: 1 a[1]: 2
示例 ②
package main import "fmt" func main() { //声明数组的同时快速初始化数组 balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} //输出数组元素 for i := 0; i < 5; i++ { fmt.Printf("balance[i]: %f\n", balance[i]) } //输出每个数组元素的值 balance2 := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} for x := 0; x < 5; x++ { fmt.Printf("balance2[x]: %f\n", balance2[x]) } //将索引为1和3的元素初始化 balance3 := [5]float32{1: 2.0, 3: 7.0} for y := 0; y < 5; y++ { fmt.Printf("balance3: %f\n", balance3[y]) } } //输出结果如下 balance[i]: 1000.000000 balance[i]: 2.000000 balance[i]: 3.400000 balance[i]: 7.000000 balance[i]: 50.000000 balance2[x]: 1000.000000 balance2[x]: 2.000000 balance2[x]: 3.400000 balance2[x]: 7.000000 balance2[x]: 50.000000 balance3: 0.000000 balance3: 2.000000 balance3: 0.000000 balance3: 7.000000 balance3: 0.000000
2. 根据数组长度遍历数组
可以根据数组长度,通过for
循环的方式来遍历数组,数组的长度可以使用len
函数获得
使用len()
函数获取数组的长度
package main import "fmt" func main() { var a1 = [3]int{1, 2, 3} fmt.Printf("len(a1): %v\n", len(a1)) var a2 = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} fmt.Printf("len(a2): %v\n", len(a2)) } //输出结果如下 len(a1): 3 len(a2): 9
数组遍历,根据长度和下标
package main import "fmt" func main() { a := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i := 0; i < len(a); i++ { fmt.Printf("a[%d]:%v\n", i, a[i]) } } //输出结果如下 a[0]:1 a[1]:2 a[2]:3 a[3]:4 a[4]:5 a[5]:6 a[6]:7 a[7]:8 a[8]:9
使用for range
package main import "fmt" func main() { var a = [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i, v := range a { //i也可以使用空白标识符代替,不接受索引的值 fmt.Printf("a[%v]:%v\n", i, v) } } //输出结果如下 a[0]:1 a[1]:2 a[2]:3 a[3]:4 a[4]:5 a[5]:6 a[6]:7 a[7]:8 a[8]:9
四、冒泡排序
1. 控制台输入十名学生的成绩,如果低于60自动修改为60,并最终展示成绩清单
package main import "fmt" func main() { var source [10]float32 //分数 var s float32 //初始化成绩 //遍历数组 for i := 0; i < 10; i++ { fmt.Printf("请输入第%d学生的成绩:", i+1) fmt.Scan(&s) if s < 60 { //修改为60分 source[i] = 60 } else { //添加学生成绩 source[i] = s } } fmt.Println("成绩录入成功!") fmt.Println("成绩清单如下") for j := 0; j < 10; j++ { fmt.Printf("第%d名学生的成绩", j+1) fmt.Println(source[j]) } } //终端输入结果 PS D:\goproject\src\dev_code\day10\test\main> go run .\ 请输入第1学生的成绩:50 请输入第2学生的成绩:55 请输入第3学生的成绩:80 请输入第4学生的成绩:70 请输入第5学生的成绩:90 请输入第6学生的成绩:50 请输入第7学生的成绩:30 请输入第8学生的成绩:44 请输入第9学生的成绩:55 请输入第10学生的成绩:66 成绩录入成功! 成绩清单如下 第1名学生的成绩60 第2名学生的成绩60 第3名学生的成绩80 第4名学生的成绩70 第5名学生的成绩90 第6名学生的成绩60 第7名学生的成绩60 第8名学生的成绩60 第9名学生的成绩60 第10名学生的成绩66
2. 随机输入5个数字,求出最大值
package main import ( "fmt" ) func main() { var ( tmp int //用来接收比较出来最大的那个数字 num int //录入的数字 numbers [5]int //5个数字 ) for i := 0; i < 5; i++ { fmt.Printf("请输入第%d个数字:", i+1) fmt.Scan(&num) //输入的数字添加到集合中 numbers[i] = num } fmt.Println("录入成功!") tmp = numbers[0] for j := 0; j < 5; j++ { //比较最大的数,大的那个数用tmp来接收保存,循环的进行比较 if numbers[j] > tmp { //如果是求最小值,把>改为<即可 tmp = numbers[j] } } fmt.Println("最大值:", tmp) } //终端输入结果如下 PS D:\goproject\src\dev_code\day10\test\main> go run .\ 请输入第1个数字:888 请输入第2个数字:756 请输入第3个数字:358 请输入第4个数字:218 请输入第5个数字:8489 录入成功! 最大值: 8489
3. 冒泡排序
思路
- 冒泡排序要对一个列表多次重复遍历。它要比较相邻的两项,并且交换顺序排错的项,每对列表进行一次遍历,就有一个最大项排在了正确的位置。
- 列表的每一个数据项都会在其相应的位置
冒泡
。如果列表有n
项,第一次遍历就要比较n-1
对数据。 - 一旦列表中最大的数是所比较的数据对中的一个,它就会沿着列表一直后移,直到这次遍历结束
package main import "fmt" var arr = [...]int{34, 61, 22, 75, 42} func main() { fmt.Println("初始值为:", arr) //外循环控制比较的轮数 for j := 0; j < len(arr)-1; j++ { //内循环控制比较的次数 for i := 0; i < len(arr)-j-1; i++ { //内层的每轮比较的次数都-1次 if arr[i] > arr[i+1] { //两数比较以后进行位置交换 arr[i], arr[i+1] = arr[i+1], arr[i] } } } fmt.Println("----排序结束----") fmt.Println(arr) } //输出结果如下 初始值为: [34 61 22 75 42] ----排序结束---- [22 34 42 61 75]
控制台随机输入几个数,进行冒泡排序
package main import "fmt" var ( numbers int //指定输入的数 arr = []int{} //空数组 ) func main() { for i := 0; i < 5; i++ { fmt.Printf("请输入第%d个数字:", i+1) fmt.Scan(&numbers) arr = append(arr, numbers) //使用append进行添加数组元素 fmt.Println("添加成功") } fmt.Println("初始值为:", arr) //外循环控制比较的轮数 for j := 0; j < len(arr)-1; j++ { //内循环控制比较的次数 for i := 0; i < len(arr)-j-1; i++ { //内层的每轮比较的次数都-1次 if arr[i] > arr[i+1] { //两数比较以后进行位置交换 arr[i], arr[i+1] = arr[i+1], arr[i] } } } fmt.Println("----排序结束----") fmt.Println(arr) } //输出结果如下 请输入第1个数字:88 添加成功 请输入第2个数字:99 添加成功 请输入第3个数字:50 添加成功 请输入第4个数字:146 添加成功 请输入第5个数字:48 添加成功 初始值为: [88 99 50 146 48] ----排序结束---- [48 50 88 99 146]
五、多维数组
Go 语言支持多维数组,如下
//常用的多维数组声明方式: var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
//三维的整型数组: var threedim [5][10][4]int
1. 二维数组
二维数组是最简单的多维数组,二维数组本质上是由一维数组组成的。
二维数组定义方式如下
var arrayName [ x ][ y ] variable_type
variable_type
为 Go 语言的数据类型,arrayName
为数组名,二维数组可认为是一个表格
,x 为行,y 为列
下图演示了一个二维数组 a 为三行四列:
二维数组中的元素可通过 a[i][j]
来访问
package main import "fmt" func main() { //创建数组 numbers := [][]int{} //使用 append() 函数向空的二维数组添加两行一维数组 x := []int{1, 2, 3} y := []int{4, 5, 6} numbers = append(numbers, x) numbers = append(numbers, y) //显示两行数据,查看二维数组中的第一个数组和第二个数组 fmt.Printf("二维数组中的第1个一维数组为: %v\n", numbers[0]) fmt.Printf("二维数组中的第1个一维数组为: %v\n", numbers[1]) fmt.Printf("二维数组中的第1个一维数组的第一个元素为: ") fmt.Println(numbers[0][0]) //numbers[0]里面的第一个元素[0],为1 } //输出结果如下 二维数组中的第1个一维数组为: [1 2 3] 二维数组中的第1个一维数组为: [4 5 6] 二维数组中的第1个一维数组的第一个元素为: 1
2. 初始化二维数组
多维数组可通过大括号来初始值,以下为一个3行4列的二维数组
a := [3][4]int { {0,1,2,3}, //第1行索引为0 {4,5,6,7}, //第2行索引为1 {8,9,10,11}, //第3行索引为2 }
注意,上面的代码中倒数第二行的 }
必须有逗号,因为最后一行的 }
不能单独一行,也可以写成下面这样
a := [3][4]int { {0,1,2,3}, //第1行索引为0 {4,5,6,7}, //第2行索引为1 {8,9,10,11}} //第3行索引为2
示例,初始化一个2行2列的二维数组
package main import "fmt" func main() { //创建二维数组 list := [2][2]string{} //向二维数组中添加元素 list[0][0] = "你好" //第1个一维数组中的第1个元素 list[0][1] = "欢迎" //第1个一维数组中的第2个元素 list[1][0] = "来到" //第2个一维数组中的第1个元素 list[1][1] = "南京" //第2个一维数组中的第2个元素 //输出结果 fmt.Println(list) } //输出结果如下 [[你好 欢迎] [来到 南京]]
3. 访问二维数组
二维数组通过指定坐标来访问。如数组中的行索引与列索引,例如:
//访问二维数组 val 第三行的第四个元素 val := a[2][3] //或 var value int = a[2][3]
二维数组可以使用循环嵌套来输出元素
package main import "fmt" func main() { nums := [2][3]int{ {1, 2, 3}, {4, 5, 6}, } //遍历二维数组中的每个元素 //外层循环读取行 for i := 0; i < 2; i++ { //内层循环读取列 for j := 0; j < 3; j++ { fmt.Println(nums[i][j]) } } } //输出结果如下 1 2 3 4 5 6
创建各个维度元素数量不一致的多维数组
package main import "fmt" func main() { // 创建空的二维数组 list := [][]string{} // 创建三一维数组,各数组长度不同 num1 := []string{"zhang", "wang", "zhao"} num2 := []string{"li"} num3 := []string{"sun", "jin"} // 使用 append() 函数将一维数组添加到二维数组中 list = append(list, num1) list = append(list, num2) list = append(list, num3) // 循环输出 for i := range list { fmt.Printf("list: %v\n", i) fmt.Println(list[i]) } } //输出结果如下 list: 0 [zhang wang zhao] list: 1 [li] list: 2 [sun jin]
六、向函数传递数组
如果想向函数传递数组参数,需要在函数定义时,声明形参为数组,可通过如下两种方式来声明:
1. 形参设定数组大小
void myFunction(param [10]int) { . . . }
2. 形参未设定数组大小
void myFunction(param []int) { . . . }
3. 示例
函数接收整形数组参数,另一个参数指定了数组元素的个数,并求和
package main import "fmt" //定义数组,有5个元素 var numbers [5]int func main() { numbers = [5]int{10, 20, 30, 40, 50} fmt.Println("元素和为:", sum(numbers)) } func sum(arr [5]int) int { //定义求和的变量s s := 0 //求和过程 for i := range arr { s += arr[i] } return s } //输出结果如下 元素和为: 150
函数接收整形数组参数,另一个参数指定了数组元素的个数,并求出平均值
package main import "fmt" var ( //数组长度为5 nums = [5]int{10, 20, 40, 60, 80} avg float32 s int ) func main() { //数组作为参数传递给函数 avg = sums(nums, len(nums)) //输出返回的平均值 fmt.Printf("平均值为: %f", avg) } //传入数组和他的长度,返回值的类型为float32 func sums(x [5]int, length int) float32 { for i := 0; i < length; i++ { s += x[i] } avg = float32(s) / float32(length) return avg } //输出结果如下 平均值为: 42.000000
总结
数组的元素可以通过下标的方式来访问,下标的最大长度为数组长度-1,如果大于这个下标则会越界
遍历数组的两种方法:
① 通过 for
循环,长度可以使用len()
获取
② 通过for range
循环遍历数组,返回数组下标和对应的值;若不想要下标,可以使用空白标识符_
来取代