Go入门系列(三)复合数据类型

目录:
一、指针类型(Pointer)
二、数组类型
三、结构化类型(struct)
四、 切片类型
五、Map 类型
六、迭代

一、指针类型(Pointer)

Go语言指针类似C/C++,区别在于它不支持指针运算。
&为取地址符&,放到一个变量前使用就会返回相应变量的内存地址。
一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。

func main() {
    a:=1
    ptr:=&a //等价var ptr *int=&a
    fmt.Println(ptr)
    fmt.Println(*ptr)
}
#输出
0xc00000a0b8
1

指针最基本的操作就是对地址直接访问(读/写):

func main() {
    a:=1
    ptr:=&a //等价var ptr *int=&a
    fmt.Println(ptr)
    *ptr=2
    fmt.Println(a)
}
#输出
0xc00000a0b8
2

介绍到这里似乎开始疑惑为什么总有人对指针谈虎色变呢?因为指针一旦结合函数、数组、切片、闭包等投入到实例应用时,越界、野指针、偏移等等各种问题便产生了,作为入门系列不在此展开。

二、数组类型

数组是具有相同唯一类型的一组已编号且长度固定的数据项序列。
格式规则为:var variable_name [SIZE] variable_type

func main() {
    var user [10] string
    user[0]="rabbit"
    fmt.Print(user)
}
#输出
[rabbit         ]

或者可不设置size直接进行初始化,Go 语言会根据元素的个数来设置数组的大小:

func main() {
    var user =[] string{"rabbit","carrot"}
    fmt.Print(user)
}
#输出
[rabbit carrot]

当然可以像其它基本类型一样继续偷懒:

func main() {
    user:=[] string{"rabbit","carrot"}
    fmt.Print(user)
}

三、结构化类型(struct)

即结构体,结构体是由一系列具有相同类型或不同类型的数据构成的数据集合,结构体定义需要使用 type 和 struct 语句,格式规则样例如下,相对于数组可以存储同一类型的数据,结构体可以为不同项定义不同的数据类型。:

type People struct {
    name    string
    age int
    city    string
}

基本访问方式:

func main() {
    type User struct {
        name    string
        age int
        city    string
    }
    user :=User{name:"rabbit",age:18}
    fmt.Print(user.name)
}
#输出
rabbit

同样,我们可以结合刚刚提到的指针,将指针结合到结构体变量中:

func main() {
    type User struct {
        name    string
        age int
        city    string
    }

    user :=User{name:"rabbit",age:18}
    ptr:=&user
    fmt.Print(ptr.name)
}
#输出
rabbit

此外,你可以像其他数据类型一样将结构体类型作为参数传递给函数。并以以上实例的方式访问结构体变量,这个我们在下一章的函数章节会提到。

四、切片类型

切片是对数组的抽象,Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
我们可以直接对数组进行截取,len()cap()分别可测量长度和测量切片最长可以达到多少。

func main() {
    arr:=[]int{1,2,3,4,5}
    s:=arr[0:3]
    fmt.Println(arr)
    fmt.Println(s)
    fmt.Println(len(s),cap(s))
}

我们也可以通过内置的make()方法声明一个切片,其规则为:

s :=make([]int,len,cap) 

初始化为空切片,实际长度初始化后重新动态校正:

func main() {
    arr:=[]int{1,2,3,4,5}
    s:=make([]int,0,5)
    fmt.Println(len(s),cap(s),s)
    s=arr[3:5]
    fmt.Println(len(s),cap(s),s)
}
#输出
0 5 []
2 2 [4 5]

make()方法中的cap参数可以省略,此外切片提供了copy()方法和append()方法,用以拷贝切片和增加新元素。

func main() {
    arr:=[]int{1,2,3,4,5}
    s:=arr[0:3]
    s1:=make([]int,10)
    fmt.Println(len(s),cap(s),s)
    copy(s1,s)
    fmt.Println(len(s1),cap(s1),s1)
    s1=append(s,6,7,8)
    fmt.Println(len(s1),cap(s1),s1)
}
#输出
3 5 [1 2 3]
10 10 [1 2 3 0 0 0 0 0 0 0]
6 10 [1 2 3 6 7 8]

其中copy()方法有个需要注意的地方,如果s1声明的长度为0,你会发现s1并未copy成功,因为copy()不会新建新的内存空间,由它原来的切片长度决定。

五、 Map 类型

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
如果你有python基础,我说字典类型你可能会立刻明白,yes,就是它。
map声明方式有两种,其格式规则为:

/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

需要注意的是,使用前者需要初始化,我们尝试下基本使用。

func main() {
    user:=make(map[string]int)
    user["rabbit"]=18
    user["carrot"]=17

    fmt.Print(user,user["rabbit"])
}
#输出
map[carrot:17 rabbit:18] 18

或者使用前者并借助make初始化:

func main() {
    var user map[string]int
    user=make(map[string]int)
    user["rabbit"]=18
    user["carrot"]=17

    fmt.Print(user,user["rabbit"])
}

此外,在切片小节我们提到了,make()方法是有一个可省略的容量属性的,我们上述代码同样选择了忽略,但请留意它的存在,如下使用也是允许的。

user=make(map[string]int,100)

此外,map支持delete()方法:

func main() {
    var user map[string]int
    user=make(map[string]int,100)
    user["rabbit"]=18
    user["carrot"]=17
    fmt.Println(user)
    delete(user,"carrot")
    fmt.Println(user)
}
#输出
map[carrot:17 rabbit:18]
map[rabbit:18]

六、迭代

当然,迭代并不算数据类型,放在本节最后讨论下复合数据类型的迭代方式,主要借助range方法。
首先遍历我们刚看完的map类型:

func main() {
    user:=make(map[string]int,100)
    user["rabbit"]=18
    user["carrot"]=17

    for k,v :=range user{
        fmt.Printf("%s - > %d\n",k,v)
    }
}
#输出
carrot - > 17
rabbit - > 18

然后尝试下数组迭代:

func main() {
    arr:=[]int{1,2,3,4,5}
    for i,num:=range arr{
        println(i,num)
    }
}
#输出
0 1
1 2
2 3
3 4
4 5

可以看到相对于python区别还是比较大的,返回值为两个,索引和值。
在此暂时以这两个常用类型为例,后边根据进度补充。

你可能感兴趣的:(Go入门系列(三)复合数据类型)