Go第三天上课

127 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天.

课程首先介绍了高质量代码的一些格式规范。介绍了代码的编写方式,代码的编写需要简单可靠,简明清晰,编写的代码需要更多的注释进行解释,但注释也并非越多越好。对于公共函数而言,一定需要注释函数作用,功能,具体用法以及可能会存在的错误等信息。

好的代码注释,对函数的具体解释 image.png

但是存在部分函数注释无法直接判断出有用信息,所以函数注释需要简洁明了,使用者可以在看完注释后能够直接调用该函数而不需要仔细查看实现。如若需要修改该函数也可以非常明确的知道需要修改的部分,所以好的注释在函数中起到十分关键性的作用。 image.png

在编码规范中有许多值得注意的地方,如当函数需要导出时首字母大写,不需要则小写,类似于java中的Public和Private关键字,命名时注意驼峰式编写,若声明的变量再次被使用时距离上次使用距离越远,则该变量名称需要附带上下文更多的信息以便更快的理解程序的含义。同时有些信息冗余则不需要过多的编写,如fmt,原英文format,但是该名称被定义为包名,其他函数调用时都会使用fmt.func()关键字,所以大多数文件都会使用fmt包,则fmt相比于format更方便简短。其次如包名为Http包,则定义函数命名Server()会比ServerHttp()更好,因为当其他包调用Http包时Http.Server()直接方便,而Http.ServerHttp()会存在一层重复的语义信息。在for循环中for i:=0;i<len(s);i++{}会优于for index:=0 ;index<len(s);index++{},因为局部变量i,index只在for循环语句内部使用,index并没有增加对程序的理解信息,所以使用i会更好。但是在参数内部,如下代码,当参数作为形参传入函数时,deadline比t更好,deadline拥有更多的语义信息,使得代码可读性更强。

// Good
func (c *Client) send( req *Request,deadline time.Time )
// Bad
func (c *Client) send( req *Request, t time.Time)

好的代码风格避免使用嵌套,嵌套会导致代码可读性差,而且后期更改时容易出错。尽量将嵌套代码进行拆分,如下代码2比代码1更易懂且更清晰。将具有相同属性功能的代码从内嵌式判断改为平行结构会更好,所以写代码前拥有良好的代码风格会大大提高开发效率,且更好的后期维护。

Bad 代码1
func OneFunc() err{
    err := doSomething()
    if err == nil{
        err = doAnotherSomething()
        if err == nil{
            return nil
        }
        return err
    }
    return err
}

Good 代码2
func OneFunc() err{ 
    if err := doSomething(); err!=nil {
        return err
    }
    if  err := doAnotherSomething();err!=nil {
        return err
    }
    return nil
}

Go代码优化之性能优化

之前视频一直围绕代码风格,以及代码命名对其进行优化,后阶段视频利用性能工具对代码CPU使用情况,内存分配情况进行优化。 主要使用工具pprof,可查看内存,cpu使用情况。并以github.com/wolfogre/go… 项目为例找出各种占用资源情况。 下载好文件后首先运行go文件,程序会一直运行。 image.png 当浏览器打开http://localhost:6060/debug/pprof/ 本地网址时会出现如下图所示,可以查看各种内存,锁机制,协程等问题清单。 image.png 在本地终端执行go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 命令可对数据进行10秒采样。采样结果为如下图,包含flat flat% sum% cum cum%信息,其中flat是自身函数本身执行时间,flat%是flat占总cpu时间比例,sum%是上面每一行的flat%总和,cum为自身函数和调用其他函数的时间总和,cum%为cum占cpu总运行时间比例image.png 只有当函数自身没有调用其他函数时flat==cum,当flat==0时函数中只有其他函数的调用,没有自身运行时间 所以在以上执行结果中发现Eat这个函数占用了99.7%的cpu资源。接下来对Eat函数进行查看,其命令是list Eat。在下图第24行发现循环了非常大的数却什么都没做,所以占用cpu资源,删除即可。 image.png

由于命令有时候会不方便,所以可以利用web的形式以图的方式更直观的感受内存等各方面性能的问题。 在终端运行命令go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap" 可以直接跳转到web界面,可以直接看到在Steal函数中出现占用内存问题,将VIEW切换到source状态即可获得具体函数语句信息 image.png 切换到source时图状态: image.png 可以发现在第50行有大量的数据进行堆叠,注释后即可解决。该web页面还可以切换其他视图,如top视图,如下图,类似于list命令: image.png 所以利用pprof工具可以对软件程序的性能进行分析,可以更好的解决一些资源问题。最后用类似命令查看了该源码的协程问题,协程数过多。只用将命令最后的信息换为够goroutine即可,命令为go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine" image.png

切换到Flame Graph视图状态,即可看到如下图所示,每一个小方块代表占用cpu时长 image.png 将视图切换到source下搜索wolf可以查看具体代码信息,在34行函数开启了10次协程,每个协程内部进行睡眠,一次造成了资源性能问题,所以通过pprof对代码进行性能分析与排查是一个不错的工具。 image.png

课程结束对此次代码性能规范问题感悟颇深,以及培养一个良好的代码习惯对以后的项目完善,改进都会十分的方便。本次学习的pprof性能分析只用到了一些基础的检测,自身还得进行细化,认真学习pprof其他功能模块,以便于能熟练上手,使代码更加高效优雅。