数组
数组和所有其它语言一样,定长、元素具有相同数据类型
- 声明
var a [3]int
- 数组字面量初始化
var a [3]int = [3]int{1,2,3}
- 可以不按顺序指定数组的初始化元素,这样未被指定的地方会被自动填0值
var sex [...]string{1:"male",2:"femal"}
这样sex[0]
就是0值
- 可以不按顺序指定数组的初始化元素,这样未被指定的地方会被自动填0值
- 初始化时自动推断数组长度
q := [...]int{1,2,3}
- 数组的长度是常量表达式,必须在编译时就确定
- 通过
len(s)
获得数组长度
- 数组字面量初始化
- 可以通过下标索引元素
a[2]
- 如果一个数组的元素类型是可比较的,那么数组也是可比较的,即按顺序逐一比较过去
slice
基本上可以视作一个std::vector<T>
使用
slice表示一个拥有相同类型元素的可变长度序列,通常类型写作[]T
-
slice用来访问一个数组的全部或部分成员,该数组称为slice的底层数组
-
slice有三个属性
- 指针:指针指向第一个slice访问的元素
- 长度:指slice中元素的个数,可以使用
len(s)
获得 - 容量:最大的可能长度,即从第一个能访问的1元素到底层数组末尾的长度,可以使用
cap(s)
获得
-
slice操作符
s[i:j]
表示引用序列s
的左闭右开区间 [ i , j ) [i,j) [i,j)。省略i
表示从头开始。省略j
表示直到结尾 -
slice可以继续被slice引用,特别的,如果超出了原slice引用的范围,可以自动进行扩容
-
由于slice是引用类型,当在函数中使用slice作为参数时,可以直接修改传入数组本身的数据
append 函数
将元素追加到slice后面,下面简单看一下实现
func appendInt(x []int, y int) []int {
var z []int //结果变量
zlen := len(x)+1 //该新slice应有的长度
if zlen <= cap(x) { //原slice还能扩容
z = x[:zlen] //扩容
}else { //不能继续扩容原slice,分配一个新的底层数组
zcap := zlen
if zcap < 2*len(x) {
zcap = 2*len(x) //增倍扩容
}
z = make([]int,zlen,zcap)
copy(z,x)
}
z[len(x)] = y //将添加来的新元素复制
return z
}
看一下用法
var x []int
x = append(x,1) //追加一个元素
x = append(x,1,2) //追加多个元素
x = append(x,x...) //追加x的所有元素
此时应该注意的是,该slice的底层数组可能处于不断的变化中
map
散列表,键值对,键的值是唯一的。值可以通过对应的值获取、更新、删除
map是散列表的引用,map的类型是map[键类型]值类型
。其中键的类型必须是可以通过==
进行比较的类型
- 初始化:
- 使用make函数
ages := make(map[sting]int)
- 使用字面量
ages := map[string]int("alice":31)
- 使用make函数
- 通过下标访问值
ages["alice"]
- 键值不存在也没关系,会自动返回0值。比如
ages["Bob"] +=1
- 其实返回的是两个变量,其中第一个变量是键对应的值,第二个变量是布尔值,用来报告该元素是否存在
age,flag = ages["Sb"]
- 键值不存在也没关系,会自动返回0值。比如
- 使用delete删除对应键的值
delete(ages,"alice")
- 使用
for
循环和range
配合遍历一个map,注意遍历顺序是随机的,range返回的变量是 键,值for age,name := range ages
Go语言没有提供集合类型,但是可以通过map实现一个集合,具体来说就是用键来储存集合的内容,map[类型]bool
,每次插入时使用,map[元素]=true
;检查集合是否有某元素时使用map[元素] == true
结构体
几乎和C完全一致,甚至必须使用type
定义新类型也是一样的
type E struct {
ID int
name string
}
E e
使用.
来获取成员,甚至可以使用.
作用于结构体变量的指针来获取成员
注意结构体的成员也有可导出和不可导出的区别,这里的可否导出也是针对的包级别
结构体字面量
- 或者是类C的,按顺序大括号
type Point struct{X,Y int}
p := Point{1,2}
- 或者是按照成员名
type Point struct{X,Y int}
p := Point{Y:2,X:1}
结构体比较
如果结构体的所有成员变量可比较,则结构体也可比较,比较结果是逐成员比较的结果
结构体嵌套和匿名成员
给出一个未使用匿名成员的嵌套
type Point struct {
X,Y int
}
type Circl struct {
Center Point
R int
}
type Wheel struct {
Circle C
Spokes int
}
var w Wheel
此时访问到X十分困难
w.C.Center.X = 1
通过在结构体声明中,给出一个不带名称的结构体成员,完成匿名成员的声明
type Point struct {
X,Y int
}
type Circl struct {
Center
R int
}
type Wheel struct {
Circle
Spokes int
}
var w Wheel
此时可以不加指定中间变量的访问到底层
w.X = 1
其效果其实等价于
w.Circl.Point.X = 1