GoLang基础数据类型--->数组(array)详解
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.Golang数组简介
数组是Go语言编程中最常用的数据结构之一。顾名思义,数组就是指一系列同一类型数据的集合。数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数组的长度。换句话说,与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列。
二.定义数组
在Go语言中,数组长度在定义后就不可更改,在声明时长度可以为一个常量或者一个常量表达式(常量表达式是指在编译期即可计算结果的表达式)。数组的长度是该数组类型的一个内置常量,可以用Go语言的内置函数len()来获取。
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import (
11 "strings"
12 "fmt"
13 "reflect"
14 )
15
16 func main() {
17 var golang_array [5]string //定义一个长度为5的字符串数组。我们可以用一个定义数组的公式:“var golang_array [n]type ”, n表示数组长度,type表示数组存储类型。
18 line := "yinzhengjie is a good boy"
19 list := strings.Split(line, " ") //将字符串切割成相应的一个切片。
20 for k,v := range list{
21 golang_array[k] = v //将切片的每一个值赋值给我们刚刚定义的长度为5的数组。
22 }
23 fmt.Println(reflect.TypeOf(list)) //查看list的数据类型
24 fmt.Println(golang_array)
25 fmt.Println(reflect.TypeOf(golang_array))
26 }
27
28
29
30 #以上代码执行结果如下:
31 []string
32 [yinzhengjie is a good boy]
33 [5]string
三.常见的数组声明方法
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 type new struct {
13 x,y int64
14 }
15
16 var (
17 Golang_bytes_array [10]byte //声明长度为5的数组,每个元素为一个字节;
18 Golang_pointer_array [5]*int //指针数组
19 Golang_two_dimensional_array [2][3]int //二维数组
20 Golang_three_dimensional_array [2][3][4]int //三维数组,等同于[2]([3]([4]int))
21 Golang_string_array [5]string //字符串数组
22 Golang_dynamic_array = [...]int{1,2,3,4} //这种方法需要进行赋值操作。
23 )
24
25 func main() {
26 fmt.Println(Golang_bytes_array)
27 fmt.Println(Golang_pointer_array)
28 fmt.Println(Golang_two_dimensional_array)
29 fmt.Println(Golang_three_dimensional_array)
30 fmt.Println(Golang_string_array)
31 fmt.Println(Golang_dynamic_array)
32 }
33
34
35
36 #以上代码执行结果如下:
37 [0 0 0 0 0 0 0 0 0 0]
38 [<nil> <nil> <nil> <nil> <nil>]
39 [[0 0 0] [0 0 0]]
40 [[[0 0 0 0] [0 0 0 0] [0 0 0 0]] [[0 0 0 0] [0 0 0 0] [0 0 0 0]]]
41 [ ]
42 [1 2 3 4]
四.数组初始化
1.二维数组初始化展示
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func main() {
13 Golang_two_dimensional_array := [2][5]string{{"a","b"},{"c","d"}} //进行初始化,当然还可以这样写:Golang_two_dimensional_array := [...][5]string{{"a","b"},{"c","d"}}
14 res := Golang_two_dimensional_array
15 for _,v := range res {
16 for x,y := range v{
17 fmt.Println(x,y)
18 }
19 }
20 fmt.Println(Golang_two_dimensional_array)
21 }
22
23
24
25
26 #以上代码执行结果如下:
27 0 a
28 1 b
29 2
30 3
31 4
32 0 c
33 1 d
34 2
35 3
36 4
37 [[a b ] [c d ]]
2.多维数组初始化展示
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import (
11 "fmt"
12 )
13
14 func main() {
15 Golang_Multidimensional_array := [...][3][10]string{ //该行效果等同于:"Golang_Multidimensional_array := [3][3][10]string",这不过我那样写可以动态扩展,没有把参数写死。
16 {
17 {
18 "中华名族园","北京奥林匹克公园","国家体育馆","中国科学技术官","奥林匹克公园网球场","蟹岛绿色生态农庄","国家游泳中心(水立方)","中国紫檀博物馆","北京欢乐谷","元大都城",
19 },
20 {
21 "北京野生动物园","男孩子麋鹿苑","中华文化园","留民营生态农场","中国印刷博物馆","北普陀影视城","大兴滨河森林公园","呀路古热带植物园","庞各庄万亩梨园","西黄垈村",
22 },
23 {
24 "颐和园","北京大学","西山八大处","圆明园遗址公园","*广播电视塔","北京植物园","紫竹院公园","凤凰岭","香山公园","王渊潭",
25 },
26 },
27 {
28 {
29 "秦始皇兵马俑","大雁塔","大唐芙蓉园","华清池","黄巢堡国家森林公园","西安碑林博物馆","骊山国家森林公园","西安城墙","秦始皇陵","翠华山",
30 },
31 {
32 "中坝大峡谷","香溪洞","安康双龙生态旅游度假区","瀛湖生态旅游景区","简车湾休闲景区","南宫山","天书峡景区","汉江燕翔洞景区","飞渡峡-黄安坝景区","千层河",
33 },
34 {
35 "西柏坡红色旅游区","嶂石岩","天桂山","天山海世界","五岳塞","驼梁山","辛集国际皮革城","东方巨龟苑","白鹿温泉度假中心","灵寿秋山景区",
36 },
37 },
38 {
39 {
40 //此处的字符串未填写,感兴趣的朋友可以继续写下去;
41 },
42 {
43 //此处的字符串未填写,感兴趣的朋友可以继续写下去;
44 },
45 {
46 //此处的字符串未填写,感兴趣的朋友可以继续写下去;
47 },
48 },
49 }
50
51 fmt.Println(Golang_Multidimensional_array)
52
53 for i:=0;i<50 ;i++ {
54 fmt.Print("*")
55 }
56 fmt.Print("我是分割线")
57 for i:=0;i<50 ;i++ {
58 fmt.Print("*")
59 }
60 fmt.Println()
61
62 for k,v := range Golang_Multidimensional_array{
63 fmt.Println(k,v)
64 //for x,y := range v{
65 // fmt.Println(x,y)
66 //}
67 }
68 }
69
70
71
72 #以上代码执行结果如下:
73 [[[中华名族园 北京奥林匹克公园 国家体育馆 中国科学技术官 奥林匹克公园网球场 蟹岛绿色生态农庄 国家游泳中心(水立方) 中国紫檀博物馆 北京欢乐谷 元大都城] [北京野生动物园 男孩子麋鹿苑 中华文化园 留民营生态农场 中国印刷博物馆 北普陀影视城 大兴滨河森林公园 呀路古热带植物园 庞各庄万亩梨园 西黄垈村] [颐和园 北京大学 西山八大处 圆明园遗址公园 *广播电视塔 北京植物园 紫竹院公园 凤凰岭 香山公园 王渊潭]] [[秦始皇兵马俑 大雁塔 大唐芙蓉园 华清池 黄巢堡国家森林公园 西安碑林博物馆 骊山国家森林公园 西安城墙 秦始皇陵 翠华山] [中坝大峡谷 香溪洞 安康双龙生态旅游度假区 瀛湖生态旅游景区 简车湾休闲景区 南宫山 天书峡景区 汉江燕翔洞景区 飞渡峡-黄安坝景区 千层河] [西柏坡红色旅游区 嶂石岩 天桂山 天山海世界 五岳塞 驼梁山 辛集国际皮革城 东方巨龟苑 白鹿温泉度假中心 灵寿秋山景区]] [[ ] [ ] [ ]]]
74 **************************************************我是分割线**************************************************
75 0 [[中华名族园 北京奥林匹克公园 国家体育馆 中国科学技术官 奥林匹克公园网球场 蟹岛绿色生态农庄 国家游泳中心(水立方) 中国紫檀博物馆 北京欢乐谷 元大都城] [北京野生动物园 男孩子麋鹿苑 中华文化园 留民营生态农场 中国印刷博物馆 北普陀影视城 大兴滨河森林公园 呀路古热带植物园 庞各庄万亩梨园 西黄垈村] [颐和园 北京大学 西山八大处 圆明园遗址公园 *广播电视塔 北京植物园 紫竹院公园 凤凰岭 香山公园 王渊潭]]
76 1 [[秦始皇兵马俑 大雁塔 大唐芙蓉园 华清池 黄巢堡国家森林公园 西安碑林博物馆 骊山国家森林公园 西安城墙 秦始皇陵 翠华山] [中坝大峡谷 香溪洞 安康双龙生态旅游度假区 瀛湖生态旅游景区 简车湾休闲景区 南宫山 天书峡景区 汉江燕翔洞景区 飞渡峡-黄安坝景区 千层河] [西柏坡红色旅游区 嶂石岩 天桂山 天山海世界 五岳塞 驼梁山 辛集国际皮革城 东方巨龟苑 白鹿温泉度假中心 灵寿秋山景区]]
77 2 [[ ] [ ] [ ]]
3.先声明再初始化
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import (
11 "fmt"
12 "strings"
13 )
14
15 var (
16 yinzhengjie [5]string //声明变量
17 )
18
19 func main() {
20 str := "a,b,c,d,e"
21 list := strings.Split(str,",")
22 for k,v := range list{
23 yinzhengjie[k] = v //在上面通过“var”关键字提前声明了变量,现在我们只需要进行初始化就成。注意是没有加“:”哟!
24 }
25 fmt.Println(yinzhengjie)
26 }
27
28
29
30 #以上代码执行结果如下:
31 [a b c d e]
4.直接声明并初始化
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func main() {
13 var a [2]int //先声明变量类型
14 a[0] = 100 //对已经声明的
15 b := [5]byte{'a','b','c','d','e'} //声明并初始化一个长度为“5”的字节(“uint8”)数组
16 c := [3]int{1,22,333}
17 d := [...]int{1,2,3,4} //可以省略长度而采用`...`的方式,Golang会自动根据元素个数来计算长度,
18 e := [...]int{10:666} //不指定长度,对第“11”个元素(下标为10)赋值“666”
19 f := [2][3]int{[3]int{1,2,3},[3]int{4,5,6}}
20 g := [2][3]int{{100,200,300},{400,500,500}} //如果内部的元素和外部的一样,那么上面的声明可以简化,直接忽略内部的,因为都是“int”型
21 fmt.Println(a)
22 fmt.Println(b)
23 fmt.Println(c)
24 fmt.Println(d)
25 fmt.Println(e)
26 fmt.Println(f)
27 fmt.Println(g)
28 }
29
30
31
32
33 #以上代码执行结果如下:
34 [100 0]
35 [97 98 99 100 101]
36 [1 22 333]
37 [1 2 3 4]
38 [0 0 0 0 0 0 0 0 0 0 666]
39 [[1 2 3] [4 5 6]]
40 [[100 200 300] [400 500 500]]
5.数组的花式定义和赋值
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func main() {
13 var num [5]int //先定义一个容量为5的数组num。
14 num = [5]int{1,3,5,7,9} //给这num数组赋值
15 fmt.Printf("num数组的元素是:%d\n",num)
16
17 var a [3]int = [3]int{1,2,3} //将一个容量为三长度也为3的数组赋值给另一个容量为三的数组.
18 fmt.Printf("a数组的元素是:%d\n",a)
19 fmt.Printf("a[1]所对应的值是:%d\n",a[1]) //表示取a数组下标对应是1的value.
20 fmt.Printf("a数组的容量是:%d,该容量的长度是:%d,还可以存取%d个成员\n",cap(a),len(a),(cap(a)-len(a))) //cap函数用于计算数组的容量,len函数用于计算数组的长度.
21
22
23 b := [...]int{1,2,3,4} //这种定义方式其实就是不写具体的容量参数,那么容量的值就和长度是相等的。
24 fmt.Printf("b数组的元素是:%d\n",b)
25 fmt.Printf("该数组的容量是:%d,该容量的长度是:%d,还可以存取%d个成员\n",cap(b),len(b),(cap(b)-len(b)))
26
27 c := [...]int{4:20,7:-1} //定义下标为4的值为20,下标为7的值为-1。给指定数组下标赋初值,数组的长度为最大下标的加1,如果一个数组没有写明容量的话,会根据其下标最大的元素来定义其容量和长度。
28 fmt.Printf("c数组的元素是:%d\n",c)
29 fmt.Printf("该数组的容量是:%d,该容量的长度是:%d,还可以存取%d个成员\n",cap(c),len(c),(cap(c)-len(c)))
30 }
31
32
33
34
35 #以上代码执行结果如下:
36 num数组的元素是:[1 3 5 7 9]
37 a数组的元素是:[1 2 3]
38 a[1]所对应的值是:2
39 a数组的容量是:3,该容量的长度是:3,还可以存取0个成员
40 b数组的元素是:[1 2 3 4]
41 该数组的容量是:4,该容量的长度是:4,还可以存取0个成员
42 c数组的元素是:[0 0 0 0 20 0 0 -1]
43 该数组的容量是:8,该容量的长度是:8,还可以存取0个成员
五.数组访问方式
1.通过range访问
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func main() {
13 Number := [6]int{100,200,300,400,500,600}
14 for k,v := range Number{
15 fmt.Printf("Number[%d]=%d\n",k,v) //range具有两个返回值,第一个返回值i是元素的数组下标,第二个返回值v是元素的值。
16 }
17 }
18
19
20
21
22 #以上代码执行结果如下:
23 Number[0]=100
24 Number[1]=200
25 Number[2]=300
26 Number[3]=400
27 Number[4]=500
28 Number[5]=600
2.通过for循环来访问
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func main() {
13 Number := [6]int{100,200,300,400,500,600}
14 for i := 0;i < len(Number) ;i++ {
15 fmt.Printf("Number[%d]=[%d]\n",i,Number[i])
16 }
17 }
18
19
20
21 #以上代码执行结果如下:
22 Number[0]=[100]
23 Number[1]=[200]
24 Number[2]=[300]
25 Number[3]=[400]
26 Number[4]=[500]
27 Number[5]=[600]
六.数组进阶知识
1.数组的内存大小以及内存地址的查看
在Go语言中数组是一个值类型(value type)。是真真实实的数组,而不是一个指向数组内存起始位置的指针,也不能和同类型的指针进行转化,这一点严重不同于C语言。所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。我们来看下面这个案例:
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import (
11 "fmt"
12 "unsafe"
13 )
14
15 func main() {
16 Number := [...]int{100,200,300,400,500,600}
17 fmt.Printf("Number的元素是:%d\n",Number)
18 fmt.Printf("Number所占内存大小是:[%d]bytes\n",unsafe.Sizeof(Number)) //长度为“1”的数组所占内存大小是“8”字节。
19
20 var n1,n2 int64
21 n1 = 100
22 n2 = n1 //所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。知识把值给copy走了。
23 fmt.Printf("n1所对应的值是:[%d],n1的内存地址是:[%d]\n",n1,&n1)
24 fmt.Printf("n2所对应的值是:[%d],n2的内存地址是:[%d]\n",n2,&n2)
25 }
26
27
28
29
30 #以上代码执行结果如下:
31 Number的元素是:[100 200 300 400 500 600]
32 Number所占内存大小是:[48]bytes
33 n1所对应的值是:[100],n1的内存地址是:[825741263336]
34 n2所对应的值是:[100],n2的内存地址是:[825741263344]
2.作用域-数组值传递
如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组的内容,因为函数内操作的只是所传入数组的一个副本。当然,你也可以理解成作用域的不用,导致数据无法修改。更多关于Golang和C的数组区别可以点击这里:
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func Update(Golang_array [4]int) [4]int {
13 Golang_array[0] = 100
14 fmt.Printf("我在Update函数里面:Golang_array的值是%v\n",Golang_array)
15 return Golang_array
16 }
17
18 func main() {
19 Golang_array := [...]int{1,2,3,4}
20 res := Update(Golang_array) //将Golang_array数组交给该函数处理。
21 fmt.Println("Update处理结果是:",res)
22 fmt.Printf("我在main函数里面:Golang_array的值是%v\n",Golang_array) //这里要注意的是,它在main函数中的作用域当中,所以它拿不到Update作用域的“Golang_array”
23 }
24
25
26
27 #以上代码执行结果如下:
28 我在Update函数里面:Golang_array的值是[100 2 3 4]
29 Update处理结果是: [100 2 3 4]
30 我在main函数里面:Golang_array的值是[1 2 3 4]
3.查询数组的基本属性
1 /*
2 #!/usr/bin/env gorun
3 @author :yinzhengjie
4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
5 EMAIL:y1053419035@qq.com
6 */
7
8 package main
9
10 import "fmt"
11
12 func main() {
13 var num [5]int //先定义一个容量为5的数组num。
14 num = [5]int{1,3,5,7,9} //给这num数组赋值
15 fmt.Printf("num数组的元素是:%d\n",num)
16 var a [3]int = [3]int{1,2,3} //将一个容量为三长度也为3的数组赋值给另一个容量为三的数组.
17 fmt.Printf("a数组的元素是:%d\n",a)
18 fmt.Printf("a[1]所对应的值是:%d\n",a[1]) //表示取a数组下标对应是1的value.
19 fmt.Printf("a数组的容量是:%d,该容量的长度是:%d,还可以存取%d个成员\n",cap(a),len(a),(cap(a)-len(a))) //cap函数用于计算数组的容量,len函数用于计算数组的长度.
20 b := [...]int{1,2,3,4} //这种定义方式其实就是不写具体的容量参数,那么容量的值就和长度是相等的。
21 fmt.Printf("b数组的元素是:%d\n",b)
22 fmt.Printf("该数组的容量是:%d,该容量的长度是:%d,还可以存取%d个成员\n",cap(b),len(b),(cap(b)-len(b)))
23 c := [...]int{4:20,7:-1} //定义下标为4的值为20,下标为7的值为-1。给指定数组下标赋初值,数组的长度为最大下标的加1,如果一个数组没有写明容量的话,会根据其下标最大的元素来定义其容量和长度。
24 fmt.Printf("c数组的元素是:%d\n",c)
25 fmt.Printf("该数组的容量是:%d,该容量的长度是:%d,还可以存取%d个成员\n",cap(c),len(c),(cap(c)-len(c)))
26 }
27
28
29
30
31 #以上代码执行结果如下:
32 num数组的元素是:[1 3 5 7 9]
33 a数组的元素是:[1 2 3]
34 a[1]所对应的值是:2
35 a数组的容量是:3,该容量的长度是:3,还可以存取0个成员
36 b数组的元素是:[1 2 3 4]
37 该数组的容量是:4,该容量的长度是:4,还可以存取0个成员
38 c数组的元素是:[0 0 0 0 20 0 0 -1]
39 该数组的容量是:8,该容量的长度是:8,还可以存取0个成员