GO开发规范
GO开发规范
开发环境
Visual Code 与微软开发的专⽤ Go 插件:VS Code + Go
Jet Brains 出的专⽤ IDE:Goland
GOPATH
项⽬⽬录应该位于 $GOPATH/src 下。
项⽬专⽤的 GOPATH 设置可以使⽤软链技术来实现:
$ echo$GOPATH
/tmp/gopath
$ pwd
xxx/project
$ ln -s `pwd`$GOPATH
$ tree $GOPATH
/tmp/gopath (${GOPATH})
└── src
└── project -> xxx/project
└──
$ go build project
编码规范
Golang 官⽅认为统⼀的编码风格是为了减少开发⼈员间的时间浪费,但编码风格之间没 有统⼀定论,存在不少争议,因此 Golang 提倡的是使⽤特定⼯具来解决这类问题。
因此 Golang 提供了默认的格式化⼯具 ,命令:
go fmt [-n] [-x] [packages]
gofmt具体的标准详见
格式化
缩进:使⽤制表符(tab)
⾏长度:⽆限制
括号:控制结构语法上不需要括号
命名
所有命名应该简单清晰:
使⽤ ⽽不是 once.DoOrWaitUntilDone 。
包
不应该使⽤下划线和驼峰命名
包名和源码⽬录名应该⼀致
+因包内导出名称会在包名的命名空间下,导出名称不要以包名作为标识:
名称
可导出名称需要⼤写开头的驼峰命名⽅式
局部名称使⽤⼩写开头的驼峰命名⽅式
缩写使⽤全⼤写或全⼩写(变量开头)的命名⽅式
函数
函数设计应清晰简洁:
error 作为最后⼀个返回值
代表成功/失败的状态值要作为最后⼀个返回值
另外为了避免 goroutine 和数据的泄漏,同时为了测试的便利,尽量设计同步⽅法, 即:内部 goroutine ⽣存期和函数⽣存期相同
尽量直接返回结果,⽽不要以其他同步⽅式
⽅法
接收者不要⽤ 或者 这种笼统没有意义的名称
⼀般使⽤有代表性的单字母
构造函数
以 New + 类型名称的⽅式来命名
特别的,如果⼀个包中只有⼀个构造函数,可以直接使⽤ New
接⼝
单函数的接⼝以函数名 + er 的⽅式命名
Read与 Reader
Write与 Writer
注释
语法
Golang 注释语法上继承了 C/C++: 、
块注释: /* … */
⾏注释: //
Golang 会将特定位置的注释看做⽂档的⼀部分,类似于 Python 的 docstring,使⽤godoc 可以查询和导出对应的注释⽂档:
godoc package [name ...]
包注释(package comment )
包注释是在 package 声明语句之前的注释。
/*
Package regexp implements a simple library for regular
expressions.
The syntax of the regular expressions accepted is:
regexp:
concatenation { '|' concatenation }
concatenation:
{ closure }
closure:
term [ '*' | '+' | '?' ]
term: '^'
'$'
'.'
character
'[' [ '^' ] character-ranges ']'
'(' regexp ')'
*/
package regexp
⽂档注释(doc comment)
在包中所有的顶级声明前的注释将会作为该声明的⽂档注释,尤其对于可导出的声明,注
释应以该名称开头。
// Compile parses a regular expression and returns, if
successful, a Regexp
// object that can be used to match against text.
func Compile(str string)(regexp *Regexp, err error){
组合注释
对于有共性的声明,可以使⽤组合注释,常⽤在错误声明中。
// Error codes returned by failures to parse an expression.
var(
ErrInternal = errors.New("regexp: internal error")
ErrUnmatchedLpar = errors.New("regexp: unmatched '('")
ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")
...
)
控制结构
分号
Golang 的正式语法使⽤分号来结束语句,但是通常不需要⼿动输⼊,词法分析器会⾃动 处理。
但需要注意的是,所有控制结构的左⼤括号必须和关键字( 、 、 与 )位于同⼀⾏,另起⼀⾏会导致在左⼤括号前追加⼀个分号。同样的,⼤括号不能省略。
if
条件语句不需要加上圆括号
省略不必要的 else 语句
可以加上合适的初始化语句
result :=query()
if err :=check(result); err !=nil{
return err }
// 不需要 else doSomeThing(result)
for
Golang 只有 for ⼀种循环结构。
步进
for i :=0; i <10; i++{
...
}
Golang 没有逗号表达式,并且++和—操作是语句⽽⾮表达式。
##遍历
range可以遍历数组,切⽚,字典,管道和字符串。
for key, value :=range oldMap {
...
}
遍历字符串
⽀持 UTF-8 的字符串:
for pos, str :=range"SONY⼤法好"{
fmt.Printf("%q: %d\n", str, pos)
}
‘S’: 0 ‘O’: 1 ‘N’: 2 ‘Y’: 3 ‘⼤’: 6 ‘法’: 9 ‘好’: 12 switch
相⽐于 C,Golang 将 switch 改造得更为通⽤。
表达式不限制为常量或整数
case 可以使⽤逗号来列举多个条件
⽆需显式 break,但使⽤ break 可以提前结束
func Factory(name string, value interface{})interface{}{
var object interface{}
switch name {
case"A","AA":
object =NewA()
case"B":
object =newB()
if value ==nil{
break
}
object.SetValue(value)
}
return object
}
类型选择
对于接⼝变量,可以使⽤ switch 来判断其实际类型,这是⼀个很有⽤的技巧:
func ErrorWrap(e interface{})*TraceableError {
var message string
switch e := e.(type){
case TraceableError:
return&e
case*TraceableError:
return e
case error:
message = e.Error()
default:
message = fmt.Sprintf("%v", e)
}
return ErrorNew(message,2)
}
退出循环
因为 break 关键字在 switch 块中有特殊含义,因此⽆法直接⽤ break 退出循环, 需要借助标签:
package main
error parse new
import(
"fmt"
)
func main(){
Loop:
for index :=1; index <10; index++{
switch index %5{
case1:
break
case0:
break Loop
default:
fmt.Printf("%v\n", index)
}
}
}
2 3 4
select
select ⽤法类似于 switch ,专⽤于轮询多个管道的读取。
包
包需要在头部使⽤ package 关键字声明包名,⼀般包名和⽂件夹名称⼀致即可。
⽂件
包内所有⽂件都在同⼀个命名空间下,因此建议按照功能组织包内的⽂件代码,同时在多
⼈共同开发时分别编辑不同的⽂件,以减少冲突的可能。
单元测试
功能⽂件和单元测试⽂件放在同⼀个⽂件夹内,单元测试⽂件名带上 _test 后缀,其中
包名要声明成 + _test 的形式。
单元测试可以⽤ . 导⼊需要测试的包,除此之外都不要使⽤ . 导⼊。
Golang 推荐使⽤表驱动的测试⽅式:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论