Go 基本概念速记速查之指针、map、数组
date
Dec 15, 2022
slug
golang-start-pointer-map-array
status
Published
tags
Go
summary
Go 基本概念汇总速记
type
Post
指针
p = *int
定义一个指针,存的是 int 类型变量的地址。p = &i
将变量 i 的内存地址赋值给指针 p&i
取出变量 i 的内存地址*p
取出指针 p 指向的变量的数值,也称为间接引用 dereferencing 或重定向 indirecting*p
操作也可以称为取引用,然后对该引用做处理,直接反映到原始变量上map
使用 make 创建一个 map:
make(map[<key的类型>]<值的类型>)
映射的零值为
nil
。nil
映射既没有键,也不能添加键。map的增删查改
更新 m[k] = v
查询 m[k]
删除 delete(m, k)
查询一个key
如果key不存在,则返回map元素的0值,并且第二个返回值是false。
如果key已存在,则返回该值,并且第二个返回值是 true
数组
[n]T
是一个含有 n 个 T
类型元素的数组,var a [10]int
数组的长度是固定的,声明之后就不可改变。
切片 slice
定义
[]T
表示一个元素类型为 T
的切片。切片是数组的一个视角,可以动态从数组中切分出一块连续元素。切片初始化声明跟数组类似,只是不需要指定长度,或者使用 make 函数生成
make 三个参数
第一个指定创建的类型,这里指定的是切片类型,第二个指定切片的长度,第三个指定容量,没有指定容量则默认跟长度一样
a := make([]int, 5) // len(a)=5
a[low : high]
切片结果中包括 low 元素,排除 high 元素切片就像是数组的引用,通过切片做出的修改,会直接反映到数组以及其他切片上。
数组和切片的定义的区别
a := [3]bool{true, true, false}
指定长度就是数组b := []bool{true, true, false}
生成一个数组,然后用 b 作为这个数组的引用,不显式返回这个数组,而是直接用 b 这个切片。切片的默认边界,默认下界是 0,默认上界是该 slice 的长度,注意并不是 slice 下面的数组的长度
s[:] 相当于当前切片全都要。
涉及到长度,都跟切片有关。涉及到容量,都跟底层数组有关
长度与容量
长度是指当前切片中有几个元素
容量是指当前切片中第一个元素开始数,到底层数组最后一个元素的个数。这点需要注意。
- 长度:切片开始元素 至 切片末尾元素的元素个数,使用 len() 函数获取长度
- 容量:切片开始元素 至 数组末尾元素的元素个数,使用 cap() 函数获取容量
零值
nil 切片长度和容量都是 0,且没有底层数组
切片的切片,二维切片
append 追加
当切片底层的数组不够大时,会分配一个更大的数组,然后返回的 slice 会指向新的数组
数组和切片细节
a := [3]bool{true, true, false}
指定长度就是数组b := []bool{true, true, false}
没有长度就是切片数组是一个支持索引访问的 struct
Go’s arrays are values. An array variable denotes the entire array; it is not a pointer to the first array element (as would be the case in C). This means that when you assign or pass around an array value you will make a copy of its contents. (To avoid the copy you could pass a pointer to the array, but then that’s a pointer to an array, not an array.) One way to think about arrays is as a sort of struct but with indexed rather than named fields: a fixed-size composite value.
数组本身是一个整体,是一个完整的对象,而不是像 C 语言中,一个数组实际上是这段连续内存的第一个元素的开始地址。所以传递 go 的数组的时候,实际上传递的都是值,也就是会复制一份内容出来,这也就是所谓的值传递,为了避免出现数据的复制,可以手动获取指针并传递指针。
数组可以看作是一个 struct,是一个整体,是一个支持索引访问 struct。
数组的语法
切片是数组的描述符号
切片是数组的描述符号,他由一个指向底层数组的指针、长度和容量组成

在切片上再次切片

一个数组上的多个切片,修改数据,实际上都会反映到底层数组上,多个切片会互相看到修改。
所以在切片上再次切片,只是多了一个原底层数组的又一个切片。
下面切片 e 从切片 d 切分来,之后在 e 上修改,d 也能看到修改的数据,因为本质上修改的就是底层数组。

copy 操作细节
下面代码是申请一个更大容量的切片,把老切片内的数据复制到新切片里
这个过程跟内置的 copy 函数一样的过程。
append 操作细节
将一组数据,追加到切片末尾,过程就是把要追加的数据放入切片,前提是如果追加的元素个数超过了切片剩余容量,那么先扩容,再copy原有数据,最后追加新数据。
go 中内置的函数 append 就是干这个事儿的
使用 b… 解开切片 b
小切片持有大数组占用内存问题
切片是数组的描述符号,或引用,也就是说,只要数组还有切片在引用它,那么他就无法被 garbage collector 回收掉,即使切片只需要很少一部分数据,而整个数组都不能被回收,都需要完整的放在内存中。
比如加载一个大文件,然后寻找里面第一组连续的数字并返回。这段代码会导致这个大文件一直被引用,无法释放。
这时候就可以使用一个小的全新的切片来保存需要的数据,然后返回这个新切片。
至于写法,这里写的是用 copy 来做,也可以使用 append,是一样的。