在《【4】GO语言类型和为类型增加方法》里说过GO语言除了基础类型(如int、float64、complex128等)之外,还有复合类型,其中就包含本文的数组。对于数组大家都不陌生,在C语言中可以这样声明一个一维数组:int arr[10],那么GO语言是怎么定义的呢?
一、数组的声明
1、数组的声明格式为var arrName [num]type,比如:
var strArr [10]string // 声明一个由10个字符串组成的一维字符串数组
var byteArr [32]byte // 声明一个由32个byte组成的一维byte数组
var pointArr [12]*float64 // 声明一个由12个指向float64类型的指针组成的一维指针数组
var twoArrs [3][5]int //声明了一个由15个int元素组成的二维int数组
读者可能已经发现,数组在声明时就指定了数组的大小,并且后续数组大小不能修改
2、与GO基础类型类似,数组声明之后也被GO赋予了缺省值
其缺省的值是由数组元素类型所决定的,int的缺省值为0、string的缺省值为空串、指针的缺省值为nil,这里的nil与Java的null相似 :)
二、数组的初始化
数组的初始化格式为var arrName [num]type = [num]type{value, value, value,....},比如:
var strArr [6]string = [6]string{"a", "b", "c", "d", "e", "f"}
var byteArr [5]byte = [5]byte{32, 23, 42, 26, 21}
var floatArr [3]float64 = [3]float64{3.1415, 2.6728, 1.4114}
var twoArrs [3][5]int = [3][5]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}}
初始值时显式指定了数组元素的个数
在初始化时能否把数组元素个数去除呢?答案是肯定的,但必须把元素个数变为...,如下所示:
var strArr [6]string = [...]string{"a", "b", "c", "d", "e", "f"}
var byteArr [5]byte = [...]byte{32, 23, 42, 26, 21}
var floatArr [3]float64 = [...]float64{3.1415, 2.6728, 1.4114}
var twoArrs [3][5]int = [...][5]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}}
读者估计已发现二维数组中的第二个[]中的数值5并没有省略为...,否则会出现use of [...] array outside of array literal错误提示
能否把[...]type也去除掉呢?答案是不行!但可以把数组定义简写为:
strArr := [...]string{"a", "b", "c", "d", "e", "f"}
byteArr := [...]byte{32, 23, 42, 26, 21}
floatArr := [...]float64{3.1415, 2.6728, 1.4114}
twoArrs := [...][5]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}}
三、使用new声明数组
除了上面方式声明数组之外,还可以使用new声明数组
strArr := [3]string{"山东", "纠正哥", "搞笑"} // 通常初始化数组形式
newStrArr := new([3]string) // 使用new声明数组
newStrArr[0] = "山东" // 对new声明的数组进行赋值
newStrArr[1] = "纠正哥"
newStrArr[2] = "搞笑"
读者可能已发现使用new声明的数组,在打印时前面有一个&符号,这说明使用new声明的数组返回的是一个指向数组的指针,通过这个指针可以完成对数组元素的赋值,其示意如下:
四、数组的比较
intArr := [2]int{1, 2}
strArr := [2]string{"qing", "ke"}
fmt.Println(intArr == strArr)
很明显整型数组和字符串数组是无法比较,此时会抛出mismatched types [2]int and [2]string异常
那么修改为下面代码呢?
intArr1 := [2]int{1, 2}
intArr2 := [3]int{1, 2, 3}
fmt.Println(intArr1 == intArr2)
尽管都是整型数组,但一个是有3个元素的数组,一个是有2个元素的数组,GO语言会认为这是两个不同的类型,从而抛出mismatched types [2]int and [3]int异常
把数组长度都改为2个元素,但元素值不同呢?
intArr1 := [2]int{1, 2}
intArr2 := [2]int{1, 3}
fmt.Println(intArr1 == intArr2)
此时GO语言认为intArr1和intArr2是同一个类型,但由于其元素值不同,所以打印false
把代码修改如下,才会打印true
intArr1 := [2]int{1, 2}
intArr2 := [2]int{1, 2}
fmt.Println(intArr1 == intArr2)
在其它语言中数组之间并不支持==与!=比较,只有GO这种任性语言才提供 :)
五、再论数组的初始化
【例1】:
intArr := [10]int{1,2}
fmt.Println(intArr)
上面声明数组的长度为10,但初始化时只有2个值,哪么此时会不会报错呢?答案是不会,GO会自动把后面的元素赋予缺省值0
【例2】:
intArr := [10]int{1: 10, 2: 20, 3: 30, 4: 40, 9: 90}
fmt.Println(intArr)
这种数组初始化的方式很像JSON,它指定第2个元素值为10、第3个元素值为20、第4个元素值为30、第10个元素值为90,其它元素值由于没有指定值,所以使用缺省值
六、数组作为函数入参是值传递
package main
import "fmt"
func test(param [10]int) {
fmt.Printf("In test function the address is : %p\n", ¶m) // 打印入参的整型数组的地址
}
func main() {
intArr := [10]int{5: 10} // 声明并初始化一个整型数组
fmt.Printf("In main function the address is : %p\n", &intArr) // 打印这个整型数组的地址
test(intArr) // 调用test函数
}
从运行结果上看main函数中初始化的数组地址为0xc08200a1e0,而把这个数组传给test()函数,在test()函数里面打印入参的地址发现:入参地址为0xc08200a230与main()中初始化的数组并不是同一个,从而说明数组在GO语言中是值传递,而不是C语言的地址传递;这也意味着在test()方法中对入参数组进行修改不会影响main()中数组的元素值
七、数组长度函数
GO语言内置了len()函数,用于读取数组的长度,其使用示例如下:
intArr := [10]int{5: 10}
fmt.Println(len(intArr))
本文出自 “青客” 博客,请务必保留此出处http://qingkechina.blog.51cto.com/5552198/1616321
原文地址:http://qingkechina.blog.51cto.com/5552198/1616321