Skip to content

Latest commit

 

History

History
 
 

lesson10

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

数组

一维数组

  • 声明:数组的大小必须是常量,不能是变量,比如下面的语法里的size必须是常量

    • 语法

      var variable_name [size] variable_type
    • 示例

      var num_list [10] int
  • 初始化

    • 指定数组大小

      var float_num_list1 [5]float32 = [5]float32{1.0, 2.0, 3.0, 4.0, 5.0}
      var float_num_list2 = [5]float32{1.0, 2.0, 3.0, 4.0, 5.0}
      int_num_list := [3]int{1, 2, 3}
      for index, value := range float_num_list1 {
      	fmt.Println("[float_num_list1]index=", index, "value=", value)
      }
      
      for index, value := range float_num_list2 {
      	fmt.Println("[float_num_list2]index=", index, "value=", value)
      }
      
      for index, value := range int_num_list {
      	fmt.Println("[int_num_list]index=", index, "value=", value)
      }
    • 不显式指定数组大小,编译器根据赋的值自行推导

      var balance1 []int = [...]int{1,2} // 等价于[2]int{1,2}
      var balance2 = [...]int{1,2,3}
      balance3 := [...]int{1, 2}
      fmt.Println("balance1=", balance1)
      fmt.Println("balance2=", balance2)
      fmt.Println("balance3=", balance3)
    • 指定数组大小情况下,特殊的初始化方式

      balance := [5]int{1:10, 3:30} // 将数组下标为1和3的元素分别初始化为10和30
      fmt.Println(balance) // [0, 10, 0, 30, 0]
  • 访问数组

    • 使用下标访问

      balance := [5]int{1:10, 3:30} // 将数组下标为1和3的元素分别初始化为10和30
      fmt.Println(balance)
      
      num := balance[1]
      fmt.Println("num=", num)
      for i:=0; i<5; i++ {
      	fmt.Printf("balance[%d]=%d\n", i, balance[i])
      }
    • range遍历

      var float_num_list1 [5]float32 = [5]float32{1.0, 2.0, 3.0, 4.0, 5.0}
      for index := range float_num_list1 {
          // index是数组下标
          fmt.Println("[float_num_list1]index=", index) 
      }
      
      for index, value := range float_num_list1 {
          // index是数组下标,value是对应的数组元素
      	fmt.Println("[float_num_list1]index=", index, "value=", value)
      }
    • 获取数组长度len(array)

      a := [...]int {1, 2, 3, 4, 5} 
      fmt.Println("array length=", len(a)) // array length=5

多维数组

  • 声明:数组的大小必须是常量,不能是变量,比如下面语法里的size1,size2,...,sizeN必须是常量

    • 语法

      var variable_name [size1][size2]...[sizeN] variable_type
    • 示例

      var threeDimArray [2][3][4]int // 三维数组,大小是 2x3x4
      var twoDimArray [2][3] // 二维数组,大小是2x3
  • 初始化

    • 初始化直接赋值

      array1 := [2][3]int {
          {0, 1, 2},
          {3, 4, 5}, // 如果花括号}在下一行,这里必须有逗号。如果花括号在这一行可以不用逗号
      }
    • 初始化默认值,后续再赋值

      array2 := [2][3]int{}
      array2[0][2] = 1
      array2[1][1] = 2
      fmt.Println("array2=", array2)
    • append赋值,只能对slice切片类型使用append,不能对数组使用append。参见后面lesson13里的slice类型介绍

      twoDimArray := [][]int{}
      row1 := []int{1,2,3}
      row2 := []int{4,5}
      twoDimArray = append(twoDimArray, row1)
      fmt.Println("twoDimArray=", twoDimArray)
      
      twoDimArray = append(twoDimArray, row2)
      fmt.Println("twoDimArray=", twoDimArray)
  • 访问二维数组

    • 数组下标遍历具体的元素

      array1 := [2][3]int {
          {0, 1, 2},
          {3, 4, 5}}
      for i:=0; i<2; i++ {
          for j:=0; j<3; j++ {
              fmt.Printf("array1[%d][%d]=%d ", i, j, array1[i][j])
          }
          fmt.Println()
      }
    • 数组下标遍历某行元素

      package main
      
      import "fmt"
      import "reflect"
      
      func main() {
          array := [2][3]int{{1, 2, 3}, {4, 5, 6}}
          for index := range array {
              // array[index]类型是一维数组
              fmt.Println(reflect.TypeOf(array[index])) 
              fmt.Printf("index=%d, value=%v\n", index, array[index])
          }
      }
    • range遍历

      twoDimArray := [2][3]int {
          {0, 1, 2},
          {3, 4, 5}}
      for index := range twoDimArray {
          fmt.Printf("row %d is ", index) //index的值是0,1,表示二维数组的第1行和第2行
          fmt.Println(twoDimArray[index]) //twoDimArray[index]类型就是一维数组
      }
       for row_index, row_value := range twoDimArray {
          for col_index, col_value := range row_value {
              fmt.Printf("twoDimArray[%d][%d]=%d ", row_index, col_index, col_value)
          }
          fmt.Println()
      }
  • 注意事项

    • slice类型的每一维度的大小可以不相同,比如下例里的第0行size是3,第1行size是2。如果直接访问twoDimArray[2][2]会报错。slice类型的介绍参见lesson13

      twoDimArray := [][]int{}
      row1 := []int{1,2,3}
      row2 := []int{4,5}
      twoDimArray = append(twoDimArray, row1)
      fmt.Println("twoDimArray=", twoDimArray)
      
      twoDimArray = append(twoDimArray, row2)
      fmt.Println("twoDimArray=", twoDimArray)
  • 数组作为函数参数进行传递

    • 如果数组作为函数参数,实参和形参的定义必须相同,要么都是长度相同的数组,要么都是slice类型。如果实参和形参的类型一个是数组,一个是slice,或者实参和形参都是数组但是长度不一致都会编译报错

      package main
      
      import "fmt"
      import "reflect"
      
      func sum(array [5]int, size int) int{
          sum := 0
          for i:=0; i<size; i++ {
              sum += array[i]
          }
          return sum
      }
      
      func sumSlice(array []int, size int) int{
          sum := 0
          for i:=0; i<size; i++ {
              sum += array[i]
          }
          return sum
      }
      
      func main() {
          a := [5]int {1, 2, 3, 4, 5} // a := [...]int{1, 2, 3, 4, 5}也可以去调用sum,编译器会自动推导出a的长度5
          fmt.Println("type of a:", reflect.TypeOf(a)) // type of a: [5]int
          ans := sum(a, 5)
          fmt.Println("ans=", ans)
          
          b := []int{1, 2, 3, 4, 5}
          ans2 := sumSlice(b, 5)
          fmt.Println("ans2=", ans2)
          
          array := [...]int {1}
          fmt.Println("type of array:", reflect.TypeOf(array)) // type of array: [1]int,是一个数组类型
          fmt.Println("array=", array)
      }
    • 值传递和引用传递

      • Go语言里只有值传递,没有引用传递。可以参考进阶篇文章Go有引用传递么?

      • 如果数组作为函数参数,在函数体内不能改变外部实参的值。如果使用数组作为形参,想修改实参的值,那就要传指向数组的指针

      • 如果slice作为函数参数,在函数体内可以改变外部实参的值,但是这并不意味着slice是引用传递,slice传参也是值传递。只不过slice这个结构里有一个指针指向底层的数组,实参把值拷贝给形参的时候,形参slice里的指针和外部实参slice的指针的值相同,也就指向了同一块数组内存空间,所以形参slice对数组元素做修改也会影响外部实参的值。

        // changeArray无法改变实参数组的值
        func changeArray(array [3]int) {
            array[0] = 10
        }
        
        // changeArray2可以改变实参的值
        func changeArray2(array *[3]int) {
            array[0] = 10
        }
        
        // changeArray3可以改变实参的值
        func changeArray3(array []int) {
            array[0] = 10
        }
        
        param := [3]int{1,2,3}
        changeArray(param)
        fmt.Println("param=", param) // param= [1 2 3]
        changeArray2(&param)
        fmt.Println("param=", param) // param= [10 2 3]
        
        sliceArray := []int{1,2,3}
        changeArray3(sliceArray)
        fmt.Println("sliceArray=", sliceArray) // sliceArray= [10 2 3]