四、Go语言复合数据类型(上)
@Author:Runsen
复合数据类型主要包含Go中的一些复杂类型,主要有指针类型,数组类型,切片类型,结构体类型,Map类型和Channel类型
指针
相信大家都在在C语言听过指针。首先指针是一个变量,全名叫做指针变量,只不过这个变量里面存储的值是一个地址而已。所以指针,哪怕是空指针,都是有地址的,因为变量都是有地址的。
变量其实是一种使用方便的占位符,引用计算机中的内存地址。指针其实也就是把某个变量指向到特定内存地址,类似于Linux中的软链概念。
不用单独开辟出一块内存用于存储,而是把新变量的实际内存指向到已占有内存空间的现变量中。Go语言中取变量地址符用 &
,声明一个指针类型用 *
,比如声明一个int型的指针类型
下面举一个例子,代码如下:
package main
import "fmt"
func main() { var a * int fmt.Printf("&a: %v, a:%v \n",&a,a) b := 1 fmt.Printf("&b: %v, b:%v \n",&b,b) a = &b fmt.Printf("&a: %v, a:%v \n",&a,a) fmt.Printf("&b: %v, b:%v \n",&b,b)
}
&a: 0xc000006028, a:<nil>
&b: 0xc0000120f0, b:1
&a: 0xc000006028, a:0xc0000120f0
&b: 0xc0000120f0, b:1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
从输出我们可以看到空指针a的地址是存在,在a指向b之前,指针a的值为nil,指向b之后,数值变成了变量b的地址,而对a 做操作*a
的话,数值为变量b对应的数值1。
数组
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列。
格式规则为:var variable_name [SIZE] variable_type
。
比如定义一个长度为3,类型是int的数组:var a [3]int
注意:长度必须是常量,它是数组类型的一部分,一旦定义,长度不能改变。
初始化数组时可以使用初始化列表来设置数组元素的值,具体如下面的代码所示。
package main
import "fmt"
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) //[北京 上海 广州 深圳] // 我们还可以使用指定索引值的方式来初始化数组,例如: a := [...]int{1: 1, 3: 5} fmt.Println(a) // [0 1 0 5]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
数组的遍历有两种方法,分别是for range和通过索引遍历。
package main
import "fmt"
func main() {
var a = [...]string{"北京", "上海", "广州", "深圳"}
// 通过索引遍历数组
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
fmt.Println("================")
// 用for range遍历数组
for _, v := range a {
fmt.Println(v)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
其实多维数组和一维数组定义完全相同:var 数组名 [数组大小][数组大小]类型
下面我们定义一个二维数组,具体代码如下。
package main
import "fmt"
func main() { var cities = [3][2]string{ {"北京", "上海"}, {"广州", "重庆"}, {"深圳", "东莞"}, } fmt.Println(cities) //[[北京 上海] [广州 重庆] [深圳 东莞]] fmt.Println(cities[0][0]) //北京
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
切片
因为Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,于是Go中提供了一种灵活,功能强悍的内置类型切片(“动态数组”),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大,这个就是切片。
声明一个未指定大小的数组来定义切片:var identifier []type
。因此,切片不需要说明长度。
很多人使用make()函数来创建切片:,具体如下。
var slice1 []type = make([]type, len)
// 也可以简写为
slice1 := make([]type, len)
- 1
- 2
- 3
切片是可索引的,并且可以由 len() 方法获取长度。
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
下面我们具体使用下切片,具体代码如下。
package main
import "fmt"
func main(){ var numbers = make([]int,3,5) // 两个代码相同 // umbers := make([]int, 3,5) fmt.Printf("len=%d, cap=%d, slice=%v\n",len(numbers),cap(numbers),numbers) //len=3, cap=5, slice=[0 0 0]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
切片截取是通过设置下限及上限来设置截取切片[lower-bound:upper-bound]
,具体实例如下:
package main
import "fmt"
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
func main() {
/* 创建切片 */
numbers := []int{0,1,2,3,4,5,6,7,8,9} printSlice(numbers) /* 打印原始切片 */
fmt.Println("numbers ==", numbers) /* 打印子切片从索引1(包含) 到索引4(不包含)*/
fmt.Println("numbers[1:4] ==", numbers[1:4]) /* 默认下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3]) /* 默认上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:]) numbers1 := make([]int,0,5)
printSlice(numbers1) /* 打印子切片从索引 0(包含) 到索引 2(不包含) */
number2 := numbers[:2]
printSlice(number2) /* 打印子切片从索引 2(包含) 到索引 5(不包含) */
number3 := numbers[2:5]
printSlice(number3)
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 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
执行以上代码输出结果为:
len=10 cap=10 slice=[0 1 2 3 4 5 6 7 8 9]
numbers == [0 1 2 3 4 5 6 7 8 9]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8 9]
len=0 cap=5 slice=[]
len=2 cap=10 slice=[0 1]
len=3 cap=8 slice=[2 3 4]
[Finished in 1.3s]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
文章来源: maoli.blog.csdn.net,作者:刘润森!,版权归原作者所有,如需转载,请联系作者。
原文链接:maoli.blog.csdn.net/article/details/107816368
- 点赞
- 收藏
- 关注作者
评论(0)