golang 数组基础用法


数组

定义

数组是用来存储相同唯一类型的,一组已编号且长度固定的序列

声明 && 初始化数组

数组声明需要指定元素类型及元素个数,语法格式如下:

var arr_name [num] arr_type
var name [5]string{"xiaoming","xiaofang"}
  • 声明长度为5 类型为string的数组 var arr1 [5]string

  • 声明并初始化,不写长度用…代替

  • 声明并初始化,写长度

package main

import "fmt"

func main() {

    var arr1 [5]string
    fmt.Println(arr1)
    arr1[1] = "golang"
    fmt.Println(arr1)

    var arr2 = [...]int{1, 2, 3}
    fmt.Println(arr2)
}

访问数组元素

package main

import "fmt"

func main() {
    var arr1 [10]int
    // 根据索引赋值
    for i := 0; i < 10; i++ {
        arr1[i] = i
    }
    // 根据索引查询数据
    for i := 0; i < 10; i++ {
        fmt.Println(arr1[i])
    }
}
  • 索引越界 编译检查报错 invalid array index 20 (out of bounds for 10-element array)
  • fmt.Println(arr1[20])

指针数组

  • 数组的元素除了是某个类型外,还可以是某个类型的指针
  • new函数返回一个TYPE 类型的数据结构划分内存并执行默认的初始化操作,然后返回这个数据对象的指针
package main

import "fmt"

func main() {

    var arr1 [5]*int
    // 根据索引赋值
    arr1[0] = new(int)
    arr1[1] = new(int)
    arr1[2] = new(int)
    arr1[3] = new(int)
    arr1[4] = new(int)
    fmt.Println(arr1)
    *arr1[0] = 10
    *arr1[1] = 2
    fmt.Println(arr1)
    for i := 0; i < len(arr1); i++ {
        fmt.Printf("[索引:%d 值是: %d]\n", i, *arr1[i])
    }
    /*
       [0xc00001a098 0xc00001a0b0 0xc00001a0b8 0xc00001a0c0 0xc00001a0c8]
       [0xc00001a098 0xc00001a0b0 0xc00001a0b8 0xc00001a0c0 0xc00001a0c8]
       [索引:0 值是: 10]
       [索引:1 值是: 2]
       [索引:2 值是: 0]
       [索引:3 值是: 0]
       [索引:4 值是: 0]
    */

}
  • 只声明不初始化 ,必须用new,空值 panic: runtime error: invalid memory address or nil pointer dereference

  • 普通数据深拷贝的例子

    • 判定依据就是 新老对象的指针%p &var是一致的,说明是浅拷贝,否则是深拷贝
package main

import "fmt"

func main() {

    arr1 := [2]int{1, 2}
    var arr2 [2]int
    arr2 = arr1
    fmt.Printf("[%v %p]\n", arr1, &arr1)
    fmt.Printf("[%v %p]\n", arr2, &arr2)
    arr2[1] = 20
    fmt.Printf("[%v %p]\n", arr1, &arr1)
    fmt.Printf("[%v %p]\n", arr2, &arr2)

}
  • 两个数组指针直接复制
    • 原因是内部存放的是指针,指向同一块地址,直接赋值,内容都一样,看起来是浅拷贝
    • 但是其实数据copy是深拷贝
package main

import "fmt"

func main() {

    var arr1 [3]*string
    arr2 := [3]*string{new(string), new(string), new(string)}

    *arr2[0] = "k1"
    *arr2[1] = "k2"
    *arr2[2] = "k3"
    arr1 = arr2
    fmt.Println(arr1)
    fmt.Println(arr2)
    for i := 0; i < 3; i++ {
        fmt.Printf("[arr1 :%d :%v %v]\n", i, *arr1[i], arr1[i])
        fmt.Printf("[arr2 :%d :%v %v]\n", i, *arr2[i], arr2[i])
    }
    fmt.Printf("[%v %p]\n", arr1, &arr1)
    fmt.Printf("[%v %p]\n", arr2, &arr2)
    /*
        [0xc00004c240 0xc00004c250 0xc00004c260]
       [0xc00004c240 0xc00004c250 0xc00004c260]
       [arr1 :0 :k1 0xc00004c240]
       [arr2 :0 :k1 0xc00004c240]
       [arr1 :1 :k2 0xc00004c250]
       [arr2 :1 :k2 0xc00004c250]
       [arr1 :2 :k3 0xc00004c260]
       [arr2 :2 :k3 0xc00004c260]
    */
}

数组的特点

  • 固定长度:这意味着数组不可增长、不可缩减。想要扩展数组,只能创建新数组,将原数组的元素复制到新数组。
  • 内存连续:这意味可以在缓存中保留的时间更长,搜索速度更快,是一种非常高效的数据结构,同时还意味着可以通过数值的方式(arr[index])索引数组中的元素。
  • 固定类型:固定类型意味着限制了每个数组元素可以存放什么样的数据,以及每个元素可以存放多少字节的数据。

数组是值类型,就是深拷贝

  • 举例
package main

import "fmt"

func main() {

   arr1 := [2]int{1, 2}
   var arr2 [2]int
   arr2 = arr1
   fmt.Printf("[%v %p]\n", arr1, &arr1)
   fmt.Printf("[%v %p]\n", arr2, &arr2)
   arr2[1] = 20
   fmt.Printf("[%v %p]\n", arr1, &arr1)
   fmt.Printf("[%v %p]\n", arr2, &arr2)

}

所有的值类型变量在赋值和作为参数传递时都将产生一次复制

把数组传递给函数 数组指针

  • 数组是一个值类型,所有的值类型变量在赋值和作为参数传递时都将产生一次复制操作
  • 从内存和性能上来看,在函数间传递数组是一个开销很大的操作。因为无论这个数组有多长,都会完整复制,并传递给函数
  • 数组指针只需要很小传递
package main

import (
    "fmt"
    "unsafe"
)

func bigArrPoint(arr *[1e6]int64) {
    fmt.Printf("[数组指针复制:大小:%d字节]\n", unsafe.Sizeof(arr))
}

func bigArr(arr [1e6]int64) {
    fmt.Printf("[数组复制:大小:%d字节]\n", unsafe.Sizeof(arr))
}

func main() {

    var arr [1e6]int64
    bigArr(arr)
    bigArrPoint(&arr)
}

多维数组

  • 多维数组的典型用例是平面坐标(二维数组)和三维坐标(三维数组)
  • Golang 的数组本身只有一个维度,但是我们可以组合多个数组从而创建出多维数组
package main

import (
    "fmt"
)

func main() {

    arr1 := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}}
    fmt.Println(arr1)
    fmt.Println(arr1[3][1])
}

文章作者: qianli
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 qianli !
  目录