美文网首页
Go核心编程-数组 [Array]

Go核心编程-数组 [Array]

作者: 大鱼人Echo | 来源:发表于2019-05-07 11:58 被阅读0次

    为什么需要数组

    案例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)
    }
    

    这种写法不太好的地方

    1. 使用传统方法不利于数据的管理与维护
    2. 传统的方法不够灵活,因此我们引入新的数据类型 => 数组

    什么是数组

    数组可以存放多个同一类型数据,数组也是一种数据类型,在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)
    
    }
    

    使用数组的优点

    1. 使用数组来解决问题,程序的可维护性增加
    2. 方法代码更加清晰,也容易扩展

    数组的定义和内存布局

    • 数组定义
      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)
    }
    

    数组的遍历

    1. 常规遍历 如上

    2. 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)
        }
    
    }
    

    数组使用的注意事项和细节

    1. 数组是有多个相同类型数据的组合, 一个数组一旦声明/定义了, 其长度是固定的,不能动态变化

    2. var arr []int 这时arr就是一个切片, 切片的概念后续章节会分享

    3. 数组中的元素可以是任何数据类型, 包括值类型和引用类型,但是不能混用

    4. 数组创建后, 如果没有赋值, 有默认值(零值)
      4.1 数值类型数组: 默认值为0
      4.2 字符串数组: 默认值为""
      4.3 bool数组: 默认值为false

    5. 使用数组的步骤
      5.1 声明数组并开辟空间
      5.2 给数组各个元素赋值(默认零值)
      5.3 使用数组

    6. 数组的下标是从0开始的

    7. 数组下标必须在指定范围内使用, 否则报panic: 数组越界
      比如 var arr[5]int 则有效下表为 0-4

    8. Go的数组属性类型, 在默认情况是值传递, 因此会进行值拷贝, 数组间不会相互影响

    9. 如果想在其他函数中, 去修改原来的数组, 可以使用引用传递(指针方式)

    10. 长度是数组类型的一部分, 在传递函数参数时需要考虑数组的长度, 具体看下面案例

    数组应用案例

    案例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)
    }
    

    相关文章

      网友评论

          本文标题:Go核心编程-数组 [Array]

          本文链接:https://www.haomeiwen.com/subject/svsmnqtx.html