数组
在GO中,总是会使用对应类型的零值来初始化变量。
如果用...说明可以通过数组长度来初始化
array := [...]int{10,20,30,40,50}
可以制定特定元素赋值
array := [5]int{1:10,2:20}
同其他语言不同,在go中数组是一个值,而不是一个指针,可以进行赋值
attry1 = array2
但是保证数组长度和类型都是一致的才可以赋值
func foo(array *[1e6]int) { // 必须要是指向长度为1e6的数组的指针,强化了数组是一个值的概念
return
}
func main(){
fmt.Println("fuck world")
// array := [...]int {10,20,390}
var array [1e6]int
foo(&array)
}
切片
切片是按照动态数组来构建的,可以自动增长和缩小。 切片的底层内存也是在连续块中分配的
切片的三个字段数据结构: 指向底层数组的指针,长度,容量
创建和初始化
如果只指定长度,那么切片的容量和长度相等 slice := make([]string,5) 分别指明的话,第一个位长度,第二个为容量,长度小于容量
多余的空余容量可以通过基于这个切片的切片访问,也可以通过后期合并在切片中
切片字面量: slice := []string {'red',"blue"} 定义类似于数组,但是[]里面不需要加东西 这种初始化长度和容量相等
如和设置初始化的长度和容量呢
slice := []int{99 : 0}
nil切片和空切片
只声明不做任何事的时候,就会创建nil切片。
var slice []int
空切片:
slice := []int{}
分别表示没有收到数据和数据为空
使用切片
切片的赋值操作等使用和数组一致,即使用下标。
使用切片创造切片 newslice := slice[1:3] 长度为 3-1 容量位k-1
这两个切片共享底层数组。一个修改了,另一个也能感知到。
切片相比于数组来说,优势就是可以动态增加容量
newslice = append(newslice,60)
使用容量来添加一个长度,并赋值. append还是可变参数,若使用...运算符,可以把一个切片的所有元素追加进来.
如果底层数组里没有多的容量,那么go就会创建一个新的底层数组将被引用的现有的值赋值到新数组里,在追加新的值。 append很智能,当容量小于1000的时候,总是成倍增长,一旦超过一千,可能就是1.25的增长。
用三个索引来创建切片
slice := source[i:j:k]
长度: j - i; 容量: k-i
具体涵义:从i下标开始到j下标是长度,到k下标是容量
三个索引的意义:
- 当基于切片创造切片后,因为这些切片都共享一个底层数组,但是呢append后又会分配新的容量到长度里面,同时为这个空闲容量赋值。当容量不够时,可能还会创建新的数组。 所以对单个切片的修改很容易影响到多个切片,但是又很难找到问题所在。 因此引入三个索引,控制子切片的长度和容量相等,当append时,就会分配新数组,不用担心会影响其他切片且保证了底层数组的整洁。
遍历切片 Range
range 会返回两个返回值:当前元素的索引,当前元素的副本。 缺点就是每次都只能从头开始遍历。
多维切片
slice := [][]int {{0},{10,20}}
每一个元素都是一个切片
函数间传递切片
切片本身不大,它就是指针加上来长度和容量。 所以,我们一般用值传递的方式传递切片。这也是切片效率高的原因
func foo(slice []int){
fmt.Println("fuck world")
}
func main(){
fmt.Println("fuck world")
slice := make([]int,1e6)
foo(slice)
}
映射 类似hash
映射是==无序==的,即便使用同样的顺序保存键值对,每次迭代映射的时候也不一样。因为它使用了散列表
散列表
桶 : 散列表的存储单元。
对于每一个键,通过散列函数会得到散列值。其中散列值的低位被用来是选择桶。
散列表用两个数据结构存储数据:数组:主要由用于区分每个键值对要存放在哪一个桶里面。存储的是散列值的高八位值。 第二个数据结构是字节数组:存储数值对。字节数组,先优先存储了桶里面的所有键,在存储所有值。
创建和初始化
dicat := make(map[int]string)
dict := map[string]string {"REd" : "12123"}
包含切片,函数的结构类型不能作为映射的键,因为他们具有引用语义。 但是切片当然可以作为映射的值。
使用
基本和C的哈希表一样 nil映射不能存储数据
判断映射里是否有这个元素:
value,exits := colors["bue"]
if exits{
fmt.Println(values)
}
当键不存在,映射也会返回该类型的零值。
range关键字迭代映射返回的是键值对,而不再是索引和值。
删除关键字 表示从colors映射里删除red关键字
delete(colors,"red")
函数间传递映射
在函数间一般直接以值的形式传递,==注意传递映射并不会制造出该映射的一个副本==。 当传递映射到函数后,对这个函数进行了的修改,所有对这个映射的引用都能察觉到。