本文主要介绍数组(array)以及其基本使用。
数组
数组是一片连续的内存区域,是同一种数据类型元素的集合。Go语言中的数组与其他语言中的数组有显著不同的特性,例如:它不能进行扩容,再复制和传递时为值传递。
数组的定义#
比如:var a [5]int
, 数组的长度必须是常量,并且长度是数组类型的一部分。一旦定义,长度不能变。 [5]int
和[10]int
是不同的类型。
1
2
3
|
var a [3]int
var b [4]int
a = b //不可以这样做,因为此时a和b是不同的类型
|
数组可以通过下标进行访问,下标是从0
开始,最后一个元素下标是:len-1
,访问越界(下标在合法范围之外),则触发访问越界,会panic。
数组的初始化#
方法一:
初始化数组时可以使用初始化列表来设置数组元素的值。
1
2
3
4
5
6
7
8
|
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) //[北京 上海 杭州]
}
|
方法二:
按照上面的方法每次都要确保提供的初始值和数组长度一致,一般情况下我们可以让编译器根据初始值的个数自行推断数组的长度。
1
2
3
4
5
6
7
8
|
func main() {
var numArray = [...]int{1, 2}
var cityArray = [...]string{"北京", "上海", "深圳"}
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
}
|
方法三:
使用指定索引值的方式来初始化数组
1
2
3
4
5
|
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
}
|
遍历数组#
遍历数组通过 for 循环
1
2
3
4
5
6
7
8
9
10
11
|
func main() {
nums := [...]string{"Beijing", "Shanghai", "Hangzhou"}
// 方法1:for 循环
for i := 0; i < len(nums); i++ {
fmt.Println(nums[i])
}
// 方法2: for range 循环
for i, v := range nums {
fmt.Println(i, v)
}
}
|
多维数组#
多维数组有称嵌套数组,这里仅以二维数组为例。
初始化与遍历#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func main() {
a := [3][2]string{
{"北京", "上海"},
{"广州", "深圳"},
{"成都", "重庆"},
}
fmt.Println(a) //[[北京 上海] [广州 深圳] [成都 重庆]]
fmt.Println(a[2][1]) //支持索引取值:重庆
for _, v1 := range a {
for _, v2 := range v1 {
fmt.Printf("%s\t", v2)
}
fmt.Println()
}
}
|
注意: 多维数组只有第一层可以使用...
来让编译器推导数组长度。
1
2
3
4
5
6
|
//支持的写法
a := [...][2]string{
{"北京", "上海"},
{"广州", "深圳"},
{"成都", "重庆"},
}
|
数组值复制#
与C语言中的数组显著不同的是,Go语言中的数组在赋值和函数调用时的形参都是值复制。如下所示,无论是赋值的b还是函数调用中的c,都是值复制的。这意味着不管是修改b还是c的值,都不会影响a的值,因为他们是完全不同的数组。
1
2
3
|
a := int[3]{1,2,3}
b = a
func Change(c [3]int){}
|
可以使用下例中的程序打印出赋值前后的地址来验证值复制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
func CopyArray(c [3]int) {
fmt.Printf("c:%p\n", &c)
}
func main() {
a := [3]int{1, 2, 3}
fmt.Printf("a:%p\n", &a)
b := a
CopyArray(a)
fmt.Printf("b:%p\n", &b)
}
输出:
a:0xc0000a2030
c:0xc0000a2060
b:0xc0000a2048
|
可以看到每个数组在内存中的位置都是不相同的,这也验证了值复制。