1. Golang
Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。
Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。
与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。
2. Golang资料补给包
包含文章,书籍,作者论文,理论分析,开源框架,云原生,大佬视频,大厂实战分享ppt
3. Go 语言用途
Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。
对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。
4. golang适合做什么
- 1.云计算基础设施领域
代表项目:docker、kubernetes、etcd、consul、cloudflare cdn、七牛云存储等
- 2.基础后端软件
代表项目:tidb、influxdb,cockroachdb
- 3.微服务
代表项目: go-kit、micro、monzo bank的typhon、bilibili等
- 4.互联网基础设施
代表项目:以太坊、hyperledger等
- 5. golang的缺点有哪些?
1.包管理,大部分都在github上,私人账户维护,风险较大
2.无泛化类型,go 2.0计划加上
3.所有的exception都用Error来处理
4.对C的降级处理,并非无缝,没有C降级到asm那么完美(序列化问题)
- 6. golang cpu性能分析
6.1 分析程序的运行时间
time指令(linux系统下)
- real:从程序开始到结束,实际上度过的时间
- user:程序在用户态度过的时间
- sys:程序在内核度过的时间
一般情况下,real>=user+sys
/usr/bin/time 指令(linux系统下)
该指令下 可以看到 cpu占用率、 内存使用情况、 进程切换情况 、文件系统io、socket情况
6.2 golang下cpu性能分析
(1)在程序中引入 _ "net/http/pprof" ,并开启pprof监听
通过浏览器查看 CPU的信息和状态。
通过浏览器查看 CPU的信息和状态
注意,等程序运⾏⼀定时间,再点击profile⽂件⽣成(⾄少是30s)
(2)使用pprof
- flat 该函数⾃身代码的执⾏时⻓
- flat% 该函数⾃身代码的执⾏时⻓占⽤CPU的耗时百分⽐
- cum 代表的是该函数⾃身代码+所有调⽤的函数的执⾏时⻓
- cum% 代表的是该函数⾃身代码+所有调⽤的函数的执⾏时⻓,占⽤CPU的总耗时百分⽐
- sum% 每⼀⾏的flat%与上⾯所有⾏的flat%总和
(3)go tool pprof profile文件
启动要调试的程序,在另一个终端执行 go tool pprof http://localhost:10000/debug/pprof/profile?seconds=60
(4)可视化结构图
7. golang 程序内存分析方法
(1)内存的占⽤情况 top -p $(pidof 进程名) 查看某个进程的内存占⽤情况
(2)GODEBUG和gctrace来分析golang程序的内存使用情况
输出的GC数据 gc 17 @0.512s 2%: 0.003+33+0.003 ms clock, 0.007+0/0.053/33+0.007 ms cpu, 181->181->101 MB, 182 MB goal, 2 P
数据中每个的字段含义:
- gc 17 表示GC回收的次数编号,递增
- @0.512s 当前程序已经执⾏了0.512s
- 2% 0.512s中其中gc模块占⽤了2%的时间
- 0.003+33+0.003 ms clock 垃圾回收的时间,分别为STW(Stop the world)的时间+并发标记的时间+STW标记的时间
两次回收过程:
将444MB活跃的内存标记为⾮活跃内存, 全局堆内存增加到888MB gc 21 @0.465s 0%: 0.004+0.12+0.003 ms clock, 0.009+0/0.017/0.064+0.006 ms cpu, 444->444->0 MB, 888 MB goal, 2 P (forced)
将888MB的垃圾内存,全部的清除掉 gc 22 @121.396s 0%: 0.007+0.090+0.002 ms clock, 0.014+0/0.025/0.084+0.005 ms cpu, 0->0->0 MB, 4 MB goal, 2 P
(3)runtime.MemStats调试当前 golang程序内存的占⽤情况
在代码中定义runtime.MemStats 对象来查看
- 1. Alloc uint64 //golang语⾔框架堆空间分配的字节数
- 2. TotalAlloc uint64 //从服务开始运⾏⾄今分配器为分配的堆空间总 和,只有增加,释放的时候不减少
- 3. Sys uint64 //服务现在系统使⽤的内存
- 4. Lookups uint64 //被runtime监视的指针数
- 5. Mallocs uint64 //服务malloc heap objects的次数
- 6. Frees uint64 //服务回收的heap objects的次数
- 7. HeapAlloc uint64 //服务分配的堆内存字节数
- 8. HeapSys uint64 //系统分配的作为运⾏栈的内存
- 9. HeapIdle uint64 //申请但是未分配的堆内存或者回收了的堆内存(空闲)字节数
- 10. HeapInuse uint64 //正在使⽤的堆内存字节数
- 10. HeapReleased uint64 //返回给OS的堆内存,类似C/C++中的free。
- 11. HeapObjects uint64 //堆内存块申请的量
- 12. StackInuse uint64 //正在使⽤的栈字节数
- 13. StackSys uint64 //系统分配的作为运⾏栈的内存
- 14. MSpanInuse uint64 //⽤于测试⽤的结构体使⽤的字节数
- 15. MSpanSys uint64 //系统为测试⽤的结构体分配的字节数
- 16. MCacheInuse uint64 //mcache结构体申请的字节数(不会被视为垃圾回收)
- 17. MCacheSys uint64 //操作系统申请的堆空间⽤于mcache的字节数
- 18. BuckHashSys uint64 //⽤于剖析桶散列表的堆空间
- 19. GCSys uint64 //垃圾回收标记元信息使⽤的内存
- 20. OtherSys uint64 //golang系统架构占⽤的额外空间
- 21. NextGC uint64 //垃圾回收器检视的内存⼤⼩
- 22. LastGC uint64 // 垃圾回收器最后⼀次执⾏时间。
- 23. PauseTotalNs uint64 // 垃圾回收或者其他信息收集导致服务暂停的次数。
- 24. PauseNs [256]uint64 //⼀个循环队列,记录最近垃圾回收系统中断的时间
- 25. PauseEnd [256]uint64 //⼀个循环队列,记录最近垃圾回收系统中断的时间开始点。
- 26. NumForcedGC uint32 //服务调⽤runtime.GC()强制使⽤垃圾回收的次数。
- 27. GCCPUFraction float64 //垃圾回收占⽤服务CPU⼯作的时间总和。如果有100个goroutine,垃圾回收的时间为1S,那么就占⽤了
- 100S。
- 28. BySize //内存分配器使⽤情况
(4)pprof分析golang内存
在被调试的程序中,提供⼀个 web端⼝ 在main函数中添加⼀个端⼝监听
通过浏览器⽹⻚来查看内存的信息和状态
8. golang面试题知识点总结
数据定义
1.函数返回值问题:
在函数有多个返回值时,只要有⼀个返回值有名 称,那么其他返回值也⼀定要有名称
2.结构体的⽐较问题 :
结构体⽐较规则之⼀: 只有相同的类型的结构体才可以⽐较(1 结构体的属性类型, 2 属性的顺序)
结构体⽐较规则之⼆: 即使两个结构体的属性类型和顺序相同,但是⾥⾯存在不可⽐较类型,依然是不可以直接==⽐较的。 ⽐如 map,slice 可以参考⽤reflect.DeepEqual⽅法来进⾏⽐较
3.string与nil类型的问题
nil空值的赋值
空值, 空指针,所有Golang中的引⽤类型都可以⽤nil进⾏赋值 引⽤类型: interface , function, pointer, map, slice, channel.
string: 如果表示⼀个string的空值, ⽤空字符串来表示 ""
不能够将nil赋值给⼀个string类型
4.常量的问题
数据类型的本质 固定内存⼤⼩的别名
数据类型的作⽤ 编译器预算对象或变量分配内存空间的⼤⼩
内存四区:
(1)栈区
空间较⼩,要求数据读写性能⾼,数据存放时间较短暂。由编译器⾃动分配和释 放,存放函数的参数值、函数的调⽤流程⽅法地址、局部变量等(局部变量如果 产⽣逃逸现象,可能会挂在在堆区)
(2)堆区
空间充裕,数据存放时间较久。⼀般由开发者分配及释放(但是Golang中会根据 变量的逃逸现象来选择是否分配到栈上或堆上),启动Golang的GC由GC清除机 制⾃动回收。
(3)全局区
静态全局变量区 全局变量的开辟是在程序在main之前就已经放在内存中。⽽且对 外完全可⻅。即作⽤域在全部代码中,任何同包代码均可随时使 ⽤,在变量会搞混淆,⽽且在局部函数中如果同名称变量使⽤:=赋 值会出现编译错误。
常量区 常量区也归属于全局区,常量为存放数值字⾯值单位,即不 可修改。或者说的有的常量是直接挂钩字⾯值的。 const cl = 10 cl是字⾯量10的对等符号。
(4)代码区
存放代码逻辑的内存
数组与切⽚
(1)切⽚的初始化和追加:
slice在经过make初始化,默认的数据的值是0,append 是动态额外开辟内存。
(2)slice拼接问题:
两个slice在append的时候,记住需要进⾏将第⼆个slice进⾏...打散再拼接。s1 = append(s1, s2...)
(3)slice中new的使⽤问题
make只⽤于slice、map以及channel的初始化(⾮零值);make返回的还是这三个引⽤类型本身; ⽽new⽤于类型的内存分配,并且内存置为零;⽽new返回的是指向类型的指针。
不建议⽤new来开辟slice , map 和 channel
Map
(1)map的value赋值问题
定义map不推荐 map[string]Student map的value student⾥的属性是不可以修改的
推荐 map[string]*Student map的value student的属性是可以修改的
(2)map遍历问题
遍历map 不推荐 //将数组依次添加到map中 for _, stu := range stus { m[stu.Name] = &stu } //遍历map的时候,不要采⽤range的⽅式来遍历
推荐 //遍历整个slice数组,⼀次赋值给map for i := 0; i < len(stus); i++ { m[stus[i].Name] = &stus[i] }
interface
(1)interface的赋值
多态的三要素
有interface接⼝,并且有接⼝定义的⽅法。
有⼦类去重写interface的接⼝。
有⽗类指针指向⼦类的具体对象
如果People是⼀个interface类型 var peo People = Stduent{} 错误的
var peo People = &Student{} 正确的
(2)interface的内部构造
空接口:
非空接口:
(3)interface{} 和 interface{}
interface{}本身不是万能指针, 就是eface结构体的地址。
如果以interface{}作为形参,那么他只能够接收interface{}类型的实参。
channel
channel出现的特殊情况总结
- 给⼀个 nil channel 发送数据,造成永远阻塞
- 从⼀个 nil channel 接收数据,造成永远阻塞
- 给⼀个已经关闭的 channel 发送数据,引起 panic
- 从⼀个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回⼀个零值
- ⽆缓冲的channel是同步的,⽽有缓冲的channel是⾮同步的
15字⼝诀: 空(nil)读写阻塞,写关闭异常,读关闭空零
WaitGroup