Go语言之数组

08.Go语言之数组


文章目录

  • 08.Go语言之数组
    • 一、Array(数组)简介
    • 二、数组定义
      • 数组定义
      • 数组声明
    • 三、数组的初始化
      • 方式一
      • 方法二
      • 方法三
    • 四、数组的遍历
    • 五、多维数组
      • 二维数组
      • 二维数组的定义
      • 二维数组的遍历
    • 六、数组是值类型(数组拷贝和传参)
    • 七、小练习
      • 求数组所有元素之和
      • 找出数组中和为给定值的两个元素的下标,例如数组[1,3,5,8,7],找出两个元素之和等于8的下标分别是(0,4)和(1,2)

一、Array(数组)简介

数组是Go语言编程中最常用的数据结构之一。顾名思义,数组就是指一系列同一类型数据的集合。数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数组的长度。

在Go语言中数组是一个值类型(value type)。是真真实实的数组,而不是一个指向数组内存起始位置的指针,也不能和同类型的指针进行转化,这一点严重不同于C语言。所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组的内容,因为函数内操作的只是所传入数组的一个副本。

二、数组定义

数组定义

定义方式如下:

var arr [n]type

其中arr为数组变量名,n表示数组长度,type表示数组存储类型。

在Go语言中,数组长度在定义后就不可更改,在声明时长度可以为一个常量或者一个常量表达式(常量表达式是指在编译期即可计算结果的表达式)。数组的长度是该数组类型的一个内置常量,可以用Go语言的内置函数len()来获取。

arrLength := len(arr)

Golang Array和以往认知的数组的区别:

    1. 数组:是同一种数据类型的固定长度的序列。
    2. 数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。
    3. 长度是数组类型的一部分,因此,var a[5] intvar a[10]int是不同的类型。
    4. 数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
    for i := 0; i < len(a); i++ {
    }
    for index, v := range a {
    }
    5. 访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
    6. 数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。
    7.支持 "==""!=" 操作符,因为内存总是被初始化过的。
    8.指针数组 [n]*T,数组指针 *[n]T。

数组声明

常规声明方法:

var a [5]byte //长度为5的数组,每个元素为一个字节
var b [2*N] struct { x, y int5 } //复杂类型数组
var c [5]*int // 指针数组
var d [2][3]int //二维数组
var e [2][3][4]int //等同于[2]([3]([4]int))

三、数组的初始化

方式一

  • 定义时使用初始值列表的方式初始化
func main() {
	var testArray [3]int                        //数组会初始化为int类型的零值
	var numArray = [3]int{1, 2}                 //使用指定的初始值完成初始化
	var cityArray = [3]string{"北京", "上海", "深圳"} //使用指定的初始值完成初始化
	fmt.Println(testArray)                      //[0 0 0]
	fmt.Println(numArray)                       //[1 2 0]
	fmt.Println(cityArray)                      //[北京 上海 深圳]
}

方法二

  • 编译器根据初始值的个数自行推断数组的长度
func main() {
	var testArray [3]int
	var numArray = [...]int{1, 2}
	var cityArray = [...]string{"北京", "上海", "深圳"}
	fmt.Println(testArray)                          //[0 0 0]
	fmt.Println(numArray)                           //[1 2]
	fmt.Printf("type of numArray:%T\n", numArray)   //type of numArray:[2]int
	fmt.Println(cityArray)                          //[北京 上海 深圳]
	fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string
}

方法三

  • 通过指定索引值的方式来初始化数组
func main() {
	a := [...]int{1: 1, 3: 5}
	fmt.Println(a)                  // [0 1 0 5]
	fmt.Printf("type of a:%T\n", a) //type of a:[4]int
}

四、数组的遍历

遍历数组有如下两种方法:

func main() {
	var a = [...]string{"北京", "上海", "深圳"}
	// 方法1:for循环遍历
	for i := 0; i < len(a); i++ {
		fmt.Println(a[i])
	}

	// 方法2:for range遍历
	for index, value := range a {
		fmt.Println(index, value)
	}
}

五、多维数组

Go 语言支持多维数组,以下为常用的多维数组声明方式:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

以下实例声明了三维的整型数组:

var threedim [5][10][4]int

二维数组

  • 二维数组本质就是数组中又嵌套数组

二维数组的定义

组是最简单的多维数组,二维数组本质上是由一维数组组成的。二维数组定义方式如下:

var arrayName [ x ][ y ] variable_type

variable_type 为 Go 语言的数据类型,arrayName 为数组名,二维数组可认为是一个表格,x 为行,y 为列,下图演示了一个二维数组 a 为三行四列:

Go语言之数组_第1张图片

举个栗子,二维数组定义并初始化

func main() {
	a := [3][2]string{
		{"北京", "上海"},
		{"广州", "深圳"},
		{"成都", "重庆"},
	}
	fmt.Println(a) //[[北京 上海] [广州 深圳] [成都 重庆]]
	fmt.Println(a[2][1]) //支持索引取值:重庆
}

二维数组的遍历

func main() {
	a := [3][2]string{
		{"北京", "上海"},
		{"广州", "深圳"},
		{"成都", "重庆"},
	}
	for _, v1 := range a {
		for _, v2 := range v1 {
			fmt.Printf("%s\t", v2)
		}
		fmt.Println()
	}
}

输出:

北京	上海	
广州	深圳	
成都	重庆	

注意: 多维数组只有第一层可以使用...来让编译器推导数组长度。例如:

//支持的写法
a := [...][2]string{
	{"北京", "上海"},
	{"广州", "深圳"},
	{"成都", "重庆"},
}
//不支持多维数组的内层使用...
b := [3][...]string{
	{"北京", "上海"},
	{"广州", "深圳"},
	{"成都", "重庆"},
}

六、数组是值类型(数组拷贝和传参)

数组是值类型,赋值和传参会复制整个数组。因此改变副本的值,不会改变本身的值。

func modifyArray(x [3]int) {
	x[0] = 100
}

func modifyArray2(x [3][2]int) {
	x[2][0] = 100
}
func main() {
	a := [3]int{10, 20, 30}
	modifyArray(a) //在modify中修改的是a的副本x
	fmt.Println(a) //[10 20 30]
	b := [3][2]int{
		{1, 1},
		{1, 1},
		{1, 1},
	}
	modifyArray2(b) //在modify中修改的是b的副本x
	fmt.Println(b)  //[[1 1] [1 1] [1 1]]
}

注意:

  1. 数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。
  2. [n]*T表示指针数组,*[n]T表示数组指针 。

七、小练习

求数组所有元素之和

package main

import (
    "fmt"
    "math/rand"
    "time"
)

// 求元素和
func sumArr(a [10]int) int {
    var sum int = 0
    for i := 0; i < len(a); i++ {
        sum += a[i]
    }
    return sum
}

func main() {
    // 若想做一个真正的随机数,要种子
    // seed()种子默认是1
    //rand.Seed(1)
    rand.Seed(time.Now().Unix())

    var b [10]int
    for i := 0; i < len(b); i++ {
        // 产生一个0到1000随机数
        b[i] = rand.Intn(1000)
    }
    sum := sumArr(b)
    fmt.Printf("sum=%d\n", sum)
}

找出数组中和为给定值的两个元素的下标,例如数组[1,3,5,8,7],找出两个元素之和等于8的下标分别是(0,4)和(1,2)

package main

import "fmt"

// 找出数组中和为给定值的两个元素的下标,例如数组[1,3,5,8,7],
// 找出两个元素之和等于8的下标分别是(0,4)和(1,2)

// 求元素和,是给定的值
func myTest(a [5]int, target int) {
    // 遍历数组
    for i := 0; i < len(a); i++ {
        other := target - a[i]
        // 继续遍历
        for j := i + 1; j < len(a); j++ {
            if a[j] == other {
                fmt.Printf("(%d,%d)\n", i, j)
            }
        }
    }
}

func main() {
    b := [5]int{1, 3, 5, 8, 7}
    myTest(b, 8)
}

你可能感兴趣的:(GO,go)