Golang基础篇-复合类型
文章目录
Golang复合类型大致分为数组、切片、map、结构体、指针等。
命名类型和类型别名
-
命名类型
type newType oldType
,newType
和oldType
是不同类型,只是底层类型相同。 -
类型别名
type alias = oldType
,newType
和oldType
是相同类型。
底层类型决定了类型支持的操作。
|
|
数组
数组创建方式
-
只声明不初始化:
var arrName [n]elementType
-
声明并使用字面值初始化:
arr := [n]elementType{element1, element2, element3..., elementn}
-
声明并使用字面值初始化,且数量由实际元素个数推导而来:
arr:= [...]elementType{element1, element2, element3}
,或者用arr:= [...]elementType{1:element1, 3:element3}
的方式。
特点
-
数组的长度是固定的。
-
数组是值类型,发生拷贝的时候会将所有元素拷贝一遍。
-
数组的长度是数组类型的一部分,
[5]int
和[10]int
是不同的类型。
数组示例
|
|
注意
省略号只能作为使用数组字面值初始化时推导字面值的长度,不能作为数组类型的一部分,即var arr4 [...]int = [...]int{1, 2, 3}
的写法是错误的。
切片
切片的本质是一个数据结构,其底层数据结构仍然是一个数组,但是通过封装的一些操作,让我们使用起来像是一个可变长度的数组。
在%GOROOT%\src\runtime\slice.go
中可以看到切片的定义:
|
|
这里的Pointer
是指向切片第一个元素对应到底层数组中的元素的指针而非底层数组第一个元素的指针,len
和cap
分别表示当前切片的长度和容量。
切片创建方式
-
通过已有数组创建切片
s := array[m:n]
表示创建一个切片,其底层数组为array
,第一个元素为array[m]
,长度为n - m
,这里的m和n都可以省略,如果m省略,则默认值为0
,如果n省略,则默认值为len(array) - 1
。 -
通过已有切片创建切片
s2 := s1[m:n]
表示创建一个切片,其底层数组和s1相同,第一个元素为s1[m]
,长度为n - m
,这里的m和n同样可以省略。 -
使用内置函数
make
创建,s := make([]elementType, len, cap)
,其中的len
和cap
都可以省略。 -
string类型可以通过强制转换直接创建对应的
[]byte
或者[]rune
。
切片支持操作
-
len(s)
返回切片长度。 -
cap(s)
返回切片容量。 -
s = append(s, 1, 2, 3)
向切片中追加元素,这里的参数时变长参数,可以使用s = append(s, s1...)
的方式将一整个切片转换成变长参数使用。 -
copy(to, from)
将from
切片中的内容复制到to
切片中,复制的实际长度为min(len(from), len(to))
。
切片示例
|
|
map
map创建方式
-
只声明不初始化
var m map[KeyType][ValueType]
。 -
使用字面值初始化
m := map[string]int{"a":1, "b":2}
。 -
使用
make
方法创建var m map[string]int = make(map[string]int, len)
。
map操作方式
-
使用map的key值访问其value值
v,ok := m["a"]
m["b"] = 5
。 -
通过
range
方式去遍历,每次顺序会不一样。 -
通过内置函数
delete(m, "a")
删除元素。 -
通过
len(m)
访问map包含键值对数量。
map特点
-
一个map类型变量是对map的引用,一个未创建的map是nil。
-
两个map不能进行比较,但是可以和nil进行比较。
-
可以安全地对未创建的map进行查找、delete、len和range操作,但是存入元素会导致panic。
-
map中的value并不是一个变量,不能对其进行取地址操作。
-
如果map中保存的value是一个结构体,不能通过
m[k].xxx = xxx
的方式修改value的值,但是如果是指针或者切片可以。
map示例
|
|
不能直接修改map value的成员的值。
|
|
但是改成指针可以。
|
|
这里大胆猜测因为Map的value是通过值拷贝的方式保存的,也就是说在保存非指针的情况下,colorMap
中键值"color1"
对应的value是变量color1
的一份拷贝,如果可以对其进行修改,其实这种修改不会影响到color1
变量本身,容易造成误解,所以Golang禁止了这种操作,而使用指针类型,即使是值拷贝,两个value保存的也仍然是同一份地址,对应的都是color1
变量的地址,不会造成误解。
结构体
结构体定义方法
- 直接使用结构体字面值:
|
|
- 使用命名类型:
|
|
结构体变量声明方式
- 按照结构体内成员声明顺序依次赋值,不灵活:
|
|
- 通过按照成员命名方式赋值,推荐:
|
|
结构体示例
|
|
指针
指针声明
-
var p *int = nil
-
多级指针
var p **int = nil
指针操作
-
解引用
n := *p
-
访问结构体成员
*p.Field = xxx
-
不允许指针计算。
-
允许在函数中通过指针返回局部变量的地址,这种情况下编译器会自动将局部变量的内存空间分配到堆上。