go知识简单整理
2023-02-03 14:37:53 28 举报
AI智能生成
go知识简单整理
作者其他创作
大纲/内容
println:不支持格式化输出,所有参数以%v(默认格式)输出
printf:支持格式化输出
fmt
Sizeof:求变量所占字节大小
unsafe
Marshal
Unmarshal
json
获取一些系统属性和手动调用gc
runtime
bufio
os
sync
常用包
详解博文
gmp: g 代表协程,m代表系统线程,p代表调度器
变量逃逸:go不像c++,new不一定是在堆上分配内存 ,如果分配的对象不会在此函数作用域外被引用,则会分配在栈上,否则分配在堆上。
模型及概念
用于chan,slice,map的创建并返回其引用
make
为一个变量声明空间,并返回其地址,保存在指针中
new
delete
切片复制, 深拷贝
copy()
函数
指定执行过程,在退出当前函数体时执行。当声明了多个defer操作后,defer的执行过程是和栈一样,后进先出
若函数内声明了defer操作,又发生了异常,那么也会先将defer操作执行完后,才抛出异常
捕获的变量在捕获时确定
defer
定义方式:type error interface { Error() string }
若某个结构体实现了一个接口定义的方法,那么该接口变量即可指向该结构体,类似基类子类的关系
接口
可以获得变量的类型和值,没怎么用过
反射 reflect
协程的时候只需要保存寄存器值和栈指针以及栈大小,这就是切换时的上下文,类似c++中的context库实现
go协程
m线程
p队列
gmp
流程式,编译式语言
使用静态库,某些依赖第三方库的情况下也会链接动态库
如果一个函数结束之后外部没有引用,那么优先分配到栈中(如果申请的内存过大,栈区存不下,会分配到堆)。
如果一个函数结束之后外部还有引用,那么必定分配到堆中
申请大内存变量可能会逃逸到堆上
编译期间不确定变量类型的话,那么也会发生逃逸
堆上动态内存分配的开销比栈要大很多,所以有时我们传递值比传递指针更有效率。因为复制是栈上完成的操作,开销要比变量逃逸到堆上再分配内存要少的多
通过go build -gcflags '-m -m -l'命令查看到逃逸分析的结果
为了减少gc压力,一些传参可以用值传递,以空间换时间
内存逃逸
GODEBUG=gctrace=1 GODEBUG是控制runtime包的一个环境变量 gctrace=1表示每次进行gc时进行信息打印
\"runtime/trace\"
观测
当有一个全局对象时,可能不经意间将某个变量附着在其上,且忽略的将其进行释放,则该内存永远不会得到释放。
goroutine一直不退出泄露
有了 GC,为什么还会发生内存泄露?
GOGC
引用计数法
比标记清扫多一个灰色节点的步骤,主要是解决stw长时间挂起的问题
三色标记法
标记清扫
根节点:全局变量,函数栈,寄存器值指针
追踪式垃圾回收
主流回收方法
gc
特性
string内部数据结构是一个指向值字符串的指针ptr和字符串长度len
string内的字符串是一个不可改变的字节序列,string间的拷贝只是ptr和len的拷贝
string的第i个字节不一定是第i个字符,因为对于非ASCII字符的UTF8编码会是2个及以上字节
string
go的字符类型可不是char!
rune
常量
go语言中,数组类型包括值类型和数组长度,二者缺一不可
数组
数据结构:指向底层数组的指针ptr,切片的长度len,从此切片头部到底层数组尾部的长度cap
寻值:切片只能寻找len范围内的值,即使是在cap范围内也不行,否则会引起panic异常
操作:len()函数取切片长度,cap函数取容量,append函数向末尾添加值
删除切片内元素只能以[X:Y]的方式,创建子切片
小切片按照2倍扩容,大切片按照1.25倍扩容
扩容: append() 当扩容超出原有容量时,会生成新切片,原来的切片会被丢弃
数组编译时确定大小
切片动态扩容
数组和切片有什么区别
切片数据结构只是包含三个成员:ptr,len,cap,拷贝只是复制这三个成员,所以不一定
拷贝大切片一定比拷贝小切片代价大吗?
copy:深拷贝
=操作符 : 浅拷贝
[:]下标的方式复制: 浅拷贝
切片的深浅拷贝
面试问题
切片
声明方式:m := make(map[string]int)
map中的元素不可取地址:禁止对map元素取址的原因是map可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效。
map的遍历是无序的,因为其在遍历开始前会生成一个随机数作为hash后桶的起点
对map求长度,使用len函数
删除map中元素,用delete
map
声明方式:type test struct {}
因为go中的传参都是以拷贝的方式进行的,所以对于大结构体,可以用指针进行传参
如果结构体内的所有成员都是可以比较的,那么结构体本身也可以比较
结构体
基础类型
寻址容易,需要大片内存,管理简单
连续堆栈
寻址复杂,对于大片内存要求不高,管理复杂
分段堆栈
在未超出最大容量之前按照两倍系数增加
一个 goroutine 的栈只占几 KB,但这个栈空间也是可以伸缩的
用作go协程之间通信的通道,分为有缓存通道和无缓存通道
当通道内无值或者空间已满,发送协程或者接收协程会被阻塞
当需要从多个chan获取数据,可以使用select
协程对chan的访问默认是阻塞的,想要非阻塞的访问就把chan放在select中,条件不满足就会从select退出,既不会阻塞
mutex还存在RW锁,和其他语言提供的一样
互斥锁
读写锁
var wg sync.WaitGroup
go不支持可重入锁,trylock,以及自旋锁,要自己实现
cas
mutex
子主题
等待协程退出
常用函数:Add,Done,Wait
WaitGroup
保证函数在程序内只执行一次,调用Do方法
sync.Once
用于父子协程里共享上下文变量和父子协程同步
Context
chan
goroutine
匿名函数(闭包)
panic & recover
可基于类型断言识别错误类型
类型断言
pperf
go性能分析优化
gdb
dlv
调试手段
调试命令很像,gdb需要可执行文件,dlv不需要
go
0 条评论
回复 删除
下一页