本篇文章,将讲解以下几点:如何编写更简洁清晰的代码、常用GO语言程序优化手段、熟悉GO程序性能分析工具、了解工程中性能优化的原则和流程。
首先高质量代码,指的是编写的代码能够达到正确可靠、简洁清晰的目标。同时还需要满足完备考虑各种边界条件、异常情况处理稳定性保证、易读易维护的条件。 实际应用场景干变万化,各种语言的特性和语法各不相同,但是高质量编程循的原则是相通的。
Go语言开发者DaveCheney提出了以下的编程原则:
简单性
- 消除“多余的复杂性”,以简单清晰的逻辑编写代码
- 不理解的代码无法修复改进
可读性
- 代码是写给人看的,而不是机器
- 编写可维护代码的第一步是确保代码可读
生产力
- 团队整体工作效率非常重要
编写高质量的Go代码应从以下几个方面考虑:
1、代码格式:推荐使用gofmt自动格式化代码,gofmt是Go语言官方提供的工具,能自动格式化Go语言代码为官方统一风格,常见IDE都支持方便的配置
2、注释:
①注释应该解释代码作用,例:
// Open opens the named file for reading. If successful,methods on
// the returned file can be used for reading; the associated file
// descriptor has mode 0_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string)(*File,error){
return OpenFile(name,0_RDONLY, 0)
}
②注释应该解释代码如何做的,例:
// Add the Referer header from the most recent
// request URL to the new one, if it's not https->http:
if ref := refererForURL(reqs[len(reqs)-1].URL,req.URL);ref !="" {
req.Header.Set("Referer", ref)
}
③注释应该解释代码实现的原因,例:
switch resp.StatusCode {
//..
case 307,308:
redirectMethod = reqMethod
shouldRedirect = true
includeBody = true
if treq.GetBody
nil && ireq.outgoingLength() != 0 {
// We had a request body, and 307/308 require
// re-sending it,but GetBody is not defined.So just
// return this response to the user instead of an
// error, like we did in Go 1.7 and earlier.
shouldRedirect = false
}
}
④注释应该解释代码什么情况会出错,例:
// parseTimeZone parses a time zone string and returns its length. Time zones
// are human-generated and unpredictable. We can't do precise error checking.
// On the other hand, for a correct parse there must be a time zone at the
//beginning of the string, so it's almost always true that there's one
// there. We look at the beginning of the string for a run of upper-case letters.
// If there are more than 5, it's an error.
// If there are 4 or 5 and the last is a T, it's a time zone. // If there are 3, it's a time zone.
// Otherwise, other than special cases, it's not a time zone.
// GMT is special because it can have an hour offset.
func parseTimeZone(value string) (length int, ok bool)
3、命名规范:
①简洁胜于元长
② 缩略词全大写,但当其位于变量开头且不需要导出时,使用全小写
- 例如使用ServeHTTP而不是ServeHttp
- 使用XMLHTTPReguest或者xmlHTTPRequest
③变量距离其被使用的地方越远,则需要携带越多的上下文信息
- 全局变量在其名字中需要更多的上下文信息,使得在不同地方可以轻易辩认出其含义
4、控制流程
- 线性原理,处理逻辑尽量走直线,避免复杂的嵌套分支
- 正常流程代码沿着屏幕向下移动
- 提升代码可维护性和可读性
- 故问题大多出现在复杂的条件语句和循环语句中
5、错误和异常处理
- error尽可能提供简明的上下文信息链,方便定位问题
- panic用于真正异常的情况
- recover生效范围,在当前goroutine的被defer的函数中生效