为什么需要数组
案例1: 一个养鸡场有6只鸡,它们的体重分别是3kg,5kg,1kg,3.4kg,2kg,24kg。请问这6只鸡的总体重是多少?平均体重是多少?请你编写一个程序表示
传统写法
package main
import (
"fmt"
)
// 一个养鸡场有6只鸡,它们的体重分别是3kg,5kg,1kg,3.4kg,2kg,24kg。请问这6只鸡的总体重是多少?平均体重是多少?请你编写一个程序表示
func main() {
chick1 := 3.0
chick2 := 5.0
chick3 := 1.0
chick4 := 3.4
chick5 := 2.0
chick6 := 24.0
totalWeight := chick1 + chick2 + chick3 + chick4 + chick5 + chick6
// fmt.Sprintf("%.2f", totalWeight / 6) "%.2f"表示 四舍五入保留到小数点返回值
avgWeight := fmt.Sprintf("%.2f", totalWeight / 6)
fmt.Printf("totalWeight=%v avgWeight=%v", totalWeight, avgWeight)
}
这种写法不太好的地方
- 使用传统方法不利于数据的管理与维护
- 传统的方法不够灵活,因此我们引入新的数据类型 => 数组
什么是数组
数组可以存放多个同一类型数据,数组也是一种数据类型,在Go中数组是值类型
我们可以使用数组来解决养鸡场的问题
package main
import (
"fmt"
)
func main() {
// 1. 定义一个数组
var chicks [6]float64
// 给数组的每个元素赋值, 元素的下标是从0开始的 0-5
chicks[0] = 3.0
chicks[1] = 5.0
chicks[2] = 1.0
chicks[3] = 3.4
chicks[4] = 2.0
chicks[5] = 24.0
totalWeight := 0.0
// 遍历数组求出总体重
for i := 0; i < len(chicks); i++ {
totalWeight += chicks[i]
}
// 求出平均值
avgWeight := fmt.Sprintf("%.2f", totalWeight / float64(len(chicks)))
fmt.Printf("totalWeight=%v avgWeight=%v", totalWeight, avgWeight)
}
使用数组的优点
- 使用数组来解决问题,程序的可维护性增加
- 方法代码更加清晰,也容易扩展
数组的定义和内存布局
-
数组定义
var 数组名 [数组大小]数组类型
var arr [5]int
赋值: arr[0] = 1 a[1] = 30 -
数组在内存中的布局
数组的使用
案列1:从终端循环输入5个成绩,保存到float64数组,并输出
package main
import (
"fmt"
)
func main() {
var score [5]float64
// 1. 从终端循环输入5个成绩, 保存到float64数组, 并输出
for i := 0; i < len(score); i++ {
fmt.Printf("请输入第%d个元素的值: ", i + 1)
fmt.Scanln(&score[i])
}
// 2. 打印数组
for i := 0; i < len(score); i++ {
fmt.Printf("score[%d]=%v\n", i, score[i])
}
}
数组的四种初始化方式
package main
import (
"fmt"
)
// 四种初始化数组的方式
func main() {
// 方式1
var numArr1 [3]int = [3]int{1, 2, 3}
fmt.Println("numArr1= ", numArr1)
// 方式2
var numArr2 = [3]int{5, 6, 7}
fmt.Println("numArr2= ", numArr2)
// 方式3
// 这里的[...]是规定写法, 不定数组长度
var numArr3 = [...]int{8, 9, 10}
fmt.Println("numArr3= ", numArr3)
// 方式4
// 指定数组下标对应的值
var numArr4 = [...]int{1: 800, 0: 900, 2:999}
fmt.Println("numArr4= ", numArr4)
// 类型推导
strArr5 := [...]string{1: "tom", 0: "jack", 2: "Echo"}
fmt.Println("strArr5= ", strArr5)
}
数组的遍历
-
常规遍历 如上
-
for-range结构遍历
// 基本语法
for index, value := range strArr {
}
说明:
- 第一个返回值index是数组的下标
- 第二个返回值是该下标位置的值
- 他们都是仅在for循环内部可见的局部变量
- 遍历数组元素的时候, 如果不想使用下标index, 可以直接把下标index标为下划线_
- index和value的名字不是固定的, 程序员可以自行制定, 一般命名为index和value
package main
import (
"fmt"
)
func main() {
// 1. 定义字符串数组
heros := [...]string{"黄龙", "张康", "吴良材"}
// 2. 使用for range 遍历
for i, v := range heros {
fmt.Printf("i=%v v=%v\n", i, v)
fmt.Printf("heros[%d]=%v\n", i, heros[i])
}
// 3. 当不需要使用索引下标时可以使用_丢弃
for _, v := range heros {
fmt.Printf("元素的值=%v\n", v)
}
}
数组使用的注意事项和细节
-
数组是有多个相同类型数据的组合, 一个数组一旦声明/定义了, 其长度是固定的,不能动态变化
-
var arr []int 这时arr就是一个切片, 切片的概念后续章节会分享
-
数组中的元素可以是任何数据类型, 包括值类型和引用类型,但是不能混用
-
数组创建后, 如果没有赋值, 有默认值(零值)
4.1 数值类型数组: 默认值为0
4.2 字符串数组: 默认值为""
4.3 bool数组: 默认值为false -
使用数组的步骤
5.1 声明数组并开辟空间
5.2 给数组各个元素赋值(默认零值)
5.3 使用数组 -
数组的下标是从0开始的
-
数组下标必须在指定范围内使用, 否则报panic: 数组越界
比如 var arr[5]int 则有效下表为 0-4 -
Go的数组属性类型, 在默认情况是值传递, 因此会进行值拷贝, 数组间不会相互影响
-
如果想在其他函数中, 去修改原来的数组, 可以使用引用传递(指针方式)
-
长度是数组类型的一部分, 在传递函数参数时需要考虑数组的长度, 具体看下面案例
数组应用案例
案例1: 创建一个byte类型的26个元素的数组, 分别放置'A'-'Z', 使用for循环访问所有元素并打印出来。 提示: 字符数据运算 'A' + 1 -> 'B'
package main
import (
"fmt"
)
func main() {
// 1. 定义一个字节数组长度为26
var charArr [26]byte
// 2. 利用 'A' + 1 -> B 的特性进行数组赋值
for i := 0; i < len(charArr); i++ {
charArr[i] = 'A' + byte(i)
}
for _, value := range charArr {
// 3. 打印字符
fmt.Printf("%c\t", value)
}
}
案例2: 请求出一个数组的最大值, 并得到对应的下标
package main
import (
"fmt"
)
func main() {
// 1. 声明一个数组
var intArr [6]int = [...]int{1, -1, 9, 90, 11, 9000}
// 2. 假定第一个元素就是最大值, 下标就是0
maxValue := intArr[0]
maxValueIndex := 0
// 3. 从第二个元素开始循环比较, 如果发现更大, 就交换
for i := 1; i < len(intArr); i++ {
if maxValue < intArr[i] {
maxValue = intArr[i]
maxValueIndex = i
}
}
fmt.Printf("maxValueIndex: %d, maxValue: %d", maxValueIndex, maxValue)
}
案例3: 请求出一个数组的和和平均值 for-range
package main
import (
"fmt"
)
func main() {
// 1. 声明一个数组
var intArr [5]int = [...]int{1, -1, 9, 90, 12}
sum := 0
// 2. 求出总和sum
for _, value := range intArr {
sum += value
}
// 3. 求出平均值
// 让平均值保留到小数
fmt.Printf("sum=%v, 平均值=%v", sum, float64(sum) / float64(len(intArr)))
}
案例4: 随机生成5个数, 并将其反转打印
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var intArr [5]int;
// 1. 随机生成五个数, rand.Intn() 函数
// 为了每次生成的随机数不一样, 我们需要给一个seed值
rand.Seed(time.Now().UnixNano())
for i, _ := range intArr {
intArr[i] = rand.Intn(100) // 随机数生成范围:0 <= n < 100
}
fmt.Println("交换前:", intArr)
arrLength := len(intArr)
// 2. 思路:倒数第1个和第1个元素交换, 倒数第2个和第2个袁术交换
// 3. 交换次数是 arrLength / 2
// 使用一个临时变量
temp := 0
for i := 0; i < arrLength / 2; i++ {
temp = intArr[i]
intArr[i] = intArr[arrLength - 1 - i]
intArr[arrLength - 1 - i] = temp
}
fmt.Println("交换后:", intArr)
}
网友评论