构建完备的golang知识体系

1. Golang

Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。

Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。

与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。

2. Golang资料补给包

包含文章,书籍,作者论文,理论分析,开源框架,云原生,大佬视频,大厂实战分享ppt
Golang资料补给包

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 分析程序的运行时间

  1. time指令(linux系统下)
    time go run a.go

real:从程序开始到结束,实际上度过的时间
user:程序在用户态度过的时间
sys:程序在内核度过的时间
一般情况下,real>=user+sys

  1. /usr/bin/time 指令(linux系统下)
    /usr/bin/time -v go run a.go
    该指令下 可以看到 cpu占用率、 内存使用情况、 进程切换情况 、文件系统io、socket情况

6.2 golang下cpu性能分析

(1)在程序中引入 _ "net/http/pprof" ,并开启pprof监听

import _ "net/http/pprof"程序开始
http.ListenAndServe("0.0.0.0:10000", nil)
程序结束

通过浏览器查看 CPU的信息和状态。

import _ "net/http/pprof"

程序开始
http.ListenAndServe("0.0.0.0:10000", nil)
程序结束

通过浏览器查看 CPU的信息和状态

http://127.0.0.1:10000/debug/pprof

注意,等程序运⾏⼀定时间,再点击profile⽂件⽣成(⾄少是30s)

(2)使用pprof

go tool pprof [binary] [profile] //binary二进制文件 profile 要分析的文件
top //查看当前profile文件的cpu使用率
  • 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 进程名) 查看某个进程的内存占⽤情况

     mem 内存的总体情况

     free 空闲内存

     used 目前占用情况

(2)GODEBUG和gctrace来分析golang程序的内存使用情况

GODEBUG='gctrace=1' ./test2_Mem

输出的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标记的时间

0.007+0/0.053/33+0.007 ms cpu 垃圾回收占⽤的CPU时间
181->181->101 MB GC开始前堆内存181MB->GC结束后堆内存的181MB->当前的活跃的堆内存101MB
182 MB goal 全局堆内存的⼤⼩
2 P 本次GC使⽤了2个P(调度器中的Processer)

两次回收过程:

将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 对象来查看

runtime.ReadMemStats(&ms) 将当前的内存状态,加载到ms对象中

    访问Ms的属性来查看信息
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内存

import “net/http/pprof”

在被调试的程序中,提供⼀个 web端⼝ 在main函数中添加⼀个端⼝监听

http.ListenAndServe("0.0.0.0:10000", nil)

通过浏览器⽹⻚来查看内存的信息和状态

http://127.0.0.1:10000/debug/pprof/heap?debug=1
# runtime.MemStats
# Alloc = 158224
# TotalAlloc = 1293587304
# Sys = 1181335936
# Lookups = 0
# Mallocs = 972
# Frees = 212
# HeapAlloc = 158224
# HeapSys = 1140457472
# HeapIdle = 1139736576
# HeapInuse = 720896
# HeapReleased = 541925376
# HeapObjects = 760
# Stack = 393216 / 393216
# MSpan = 28288 / 32768
# MCache = 3472 / 16384
# BuckHashSys = 1449825
# GCSys = 38209928
# OtherSys = 776343
# NextGC = 4194304
# LastGC =
1586452032967855804

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的赋值
多态的三要素

  1. 有interface接⼝,并且有接⼝定义的⽅法。
  2. 有⼦类去重写interface的接⼝。
  3. 有⽗类指针指向⼦类的具体对象

如果People是⼀个interface类型 var peo People = Stduent{} 错误的
var peo People = &Student{} 正确的

(2)interface的内部构造
image.png

空接口:
image.png

非空接口:
image.png

(3)interface{} 和 interface{}
*interface{}本身不是万能指针, 就是eface结构体的地址。
如果以
interface{}作为形参,那么他只能够接收*interface{}类型的实参。

channel
channel出现的特殊情况总结
▪ 给⼀个 nil channel 发送数据,造成永远阻塞
▪ 从⼀个 nil channel 接收数据,造成永远阻塞
▪ 给⼀个已经关闭的 channel 发送数据,引起 panic
▪ 从⼀个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回⼀个零值
▪ ⽆缓冲的channel是同步的,⽽有缓冲的channel是⾮同步的

15字⼝诀: 空(nil)读写阻塞,写关闭异常,读关闭空零

WaitGroup

image.png

#学习路径#
全部评论

相关推荐

07-10 13:59
门头沟学院 Java
点赞 评论 收藏
分享
Twilight_m...:经典我朋友XXXX起手,这是那种经典的不知道目前行情搁那儿胡编乱造瞎指导的中年人,不用理这种**
点赞 评论 收藏
分享
评论
3
37
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务