内容简介:初学者使用 Go 语言开发项目的时候,首先需要熟悉一下该语言的编码规范,逐渐养成良好的编码习惯,提高自己的编码质量,对自己,对项目团队都受益匪浅。**【强制】程序内部命名方式**,一律采用驼峰命名方式。常量、变量、函数名都统一采用驼峰命名,公用对象首字母需大写,私有对象首字母可小写。有些特定名词或缩写名词,建议全部大写,如 HTML、XML、JSON、ID、UID、API、POST 等,但不是特定名词,请不要全部大写,包括常量和变量,避免全部大写,或者全部大写和下划线组合。正例:
初学者使用 Go 语言开发项目的时候,首先需要熟悉一下该语言的编码规范,逐渐养成良好的编码习惯,提高自己的编码质量,对自己,对项目团队都受益匪浅。
**【强制】程序内部命名方式**,一律采用驼峰命名方式。常量、变量、函数名都统一采用驼峰命名,公用对象首字母需大写,私有对象首字母可小写。有些特定名词或缩写名词,建议全部大写,如 HTML、XML、JSON、ID、UID、API、POST 等,但不是特定名词,请不要全部大写,包括常量和变量,避免全部大写,或者全部大写和下划线组合。
正例:
const ( UserID = 100001 DefaultCharset = "utf-8" ApplicationJSON = "application/json" TextHTML = "text/html" TextXML = "text/xml" ) var ( Expiration = 15 * time.Minute ) func init() { ... } func MyProduct() { ... }
反例:
// 以下都是不规范的命名 const ( UserId = 100001 USERID = 100001 DefaultCharset = "utf-8" ApplicationJson = "application/json" TextHtml = "text/html" Text_Html = "text/html" TEXTXML = "text/xml" TEXT_XML = "text/xml" ) var ( EXPIRATION = 15 * time.Minute ) func INIT() { ... } func My_product() { ... }
**【强制】项目名、包名、文件名命名不采用驼峰命名方式** ,项目名和包名优先采用小写名词命名方式,避免动词和下划线;文件名同理也优先采用小写名词命名方式,有时候可以适当采用下划线,尽量使用单数形式,避免复数名词。都规避采用 Go 关键字和预定的标识符。
正例:
// 项目名 project // 包名 project/src/controller project/src/model project/src/util // 文件名 article.go article_test.go
反例:
// 项目名 Project // 包名 Project/src/Controller project/src/Models project/src/utils // 文件名 Article.go ArticleTest.go
**【建议】多行方式导入包**,导入包分为: Go 标准包,第三方包,项目内部包,建议按照分类空一行分组导入包,包尽量按照字母排序。
正例:
import ( "fmt" "time" "github.com/urfave/negroni" "project/src/common" "project/src/controller" )
反例:
import "fmt" import "time" import "github.com/urfave/negroni" import "project/src/common" import "project/src/controller" import ( "fmt" "time" "github.com/urfave/negroni" "project/src/common" "project/src/controller" )
**【强制】注释两种方式,可以两个斜杠 // 和 /* ... */**。// 之后应该有个空格,注释如果很长可以分多行,可以带逗号、句号等符号;/* *... */ 开始和结束分别占一行,中间是注释句子。一般双斜杠注释比较常见,代码首先是给人看的,所以配合一些必要的注释是良好的做法,但一些函数即使注释了也于事无补,要尽早重构。
正例:
// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // EOF is the error returned by Read when no more input is available. // If the EOF occurs unexpectedly in a structured data stream, // the appropriate error is either ErrUnexpectedEOF or some other error // giving more detail. /** * ErrShortWrite means that a write accepted fewer bytes than requested * but failed to return an explicit error. */ // Seek whence values. const ( SeekStart = 0 // seek relative to the origin of the file )
反例:
//Copyright 2009 The Go Authors. All rights reserved. //Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. //EOF is the error returned by Read when no more input is available. // If the EOF occurs unexpectedly in a structured data stream,the appropriate error is either ErrUnexpectedEOF or some other error //giving more detail. /**ErrShortWrite means that a write accepted fewer bytes than requested * but failed to return an explicit error.*/ //Seek whence values. const ( SeekStart = 0//seek relative to the origin of the file )
**【建议】函数注释开头写上函数的名称,再进行对函数注释。**
正例:
// SelectOneUser 获取一个用户记录 func SelectOneUser() (*model.User, error) { ... }
反例:
//获取一个用户记录 func SelectOneUser() (*model.User, error) { ... }
**【建议】一行代码长度不要超过120个字符,如果超过,请换行。**
**【建议】循环遍历,不要放在循环体内计算集合的长度。**
正例:
for i, s := 0, len(slice); i < s; i++ { ... } // 或另外外部定义 s := len(slice) for i := 0; i < s; i++ { ... }
反例:
for i := 0; i < len(slice); i++ { ... }
**【建议】结构体初始化的时候,按照顺序标出属性名**
正例:
// BaseField 定义基类结构体 type BaseField struct { ID int64 Created time.Time } // BaseField 初始化 u := BaseField { ID : 1, Created : time.Now(), }
反例:
// BaseField 初始化 u := BaseField {1, time.Now()} // BaseField 初始化 u := BaseField { 1, time.Now(), }
**【建议】函数如果返回一个结构体实例,建议返回指针对象,因为指针可以是空指针,上层调用时可以进一步判断数据的完整性。**
正例:
func SelectOneUser() (*model.User, error) { ... }
反例:
func SelectOneUser() (model.User, error) { ... }
**【建议】空字符串判断,直接使用 ==,而不是 len 或 nil**
正例:
if name == "" { ... }
反例:
if len(name) == 0 { ... } if s == nil || s == "" { ... }
**【建议】空 slice 判断,直接使用 len,而不是 nil**
正例:
```go
if len(slc) > 0 {
...
}
```
反例:
```go
if slc != nil && len(slc) > 0 {
...
}
```
**【建议】布朗值判断,直接判断,而不是 ==**
正例:
```go
if b {
...
}
if !b {
...
}
```
反例:
```go
if b == true {
...
}
if b == false {
...
}
```
**【建议】缩短 if 判断语句,省略没必要的分支或代码**
正例:
```go
a, c := 1, 3
return a > c
if b {
return true
}
return false
```
反例:
```go
a, c := 1, 3
if a > c {
return true
} else {
return false
}
if b {
return true
} else {
return false
}
```
**【建议】append 两个 slice ,避免循环遍历**
正例:
```go
a := [1,3,5,7,9]
b := [2,4,6,8.10]
a = append(b, a...)
```
反例:
```go
a := [1,3,5,7,9]
b := [2,4,6,8.10]
for _,v := a {
append(b, v)
}
```
**【建议】涉及到 IO 文件流打开,数据库游标等操作,使用后一定记得 Close 关闭**
正例:
```go
// 打开 IO 文件流
file, err := os.Open("/path/file_name.txt")
if err != nil {
...
}
defer file.Close()
// 数据库游标操作
stmt, err := db.Prepare(`select * from user where status=?`)
if err != nil {
return err
}
defer stmt.Close()
rows, err := stmt.Query(1)
if err != nil {
return err
}
defer rows.Close()
```
反例:
```go
// 打开 IO 文件流
_, err := os.Open("/path/file_name.txt")
if err != nil {
...
}
// 数据库游标操作
stmt, err := db.Prepare(`select * from user where status=?`)
if err != nil {
return err
}
rows, err := stmt.Query(1)
if err != nil {
return err
}
```
**【建议】错误字符串不要大写,请全部小写,尽量说清楚错误特征,结尾不带结束符**
正例:
```go
file, err := os.Open("/path/file_name.txt")
if err != nil {
return errors.New("open file_name.txt fail")
}
...
```
反例:
```go
file, err := os.Open("/path/file_name.txt")
if err != nil {
return errors.New("Open file_name.txt Fail.")
// or
return err
}
...
```
**【建议】不要忽略 error ,在底层返回 error,在上层打印 error 日志**
正例:
```go
// 底层返回 error
var name string
_, err := stmt.QueryRow("select name from user where id=? limit 1",id).Scan(&name)
if err != nil {
return err
}
// 上层打印 error 日志
name, err := getUserName(id)
if err != nil {
log.Println(err)
}
```
反例:
```go
// 底层忽略了 error
var name string
stmt.QueryRow("select name from user where id=? limit 1",id).Scan(&name)
// 上层未打印 error 日志
name, _ := getUserName(id)
```
**【建议】方法接收器命名勿用 this、self 这些词,可以用结构体的缩写名,或首字母小写的全名**
正例:
```go
func (foo *Foo) sayHello() {
...
}
func (upf *UserProfile) sayHello() {
...
}
func (userProfile *UserProfile) sayHello() {
...
}
```
反例:
```go
func (this *Foo) sayHello() {
...
}
func (self *Foo) sayHello() {
...
}
```
**【建议】字符串和文件的处理,尽量使用 strings,io/ioutil 内置 工具 包的函数,减少造轮子**
**【建议】if 语句尽量避免多层嵌套,及时返回 **
正例:
```go
userId, err := selectUserId()
if err != nil {
return 0, err
}
if userId <= 0 {
return 0, errors.New("userId le zero")
}
return userId, nil
```
反例:
```go
userId, err := selectUserId()
if err == nil {
if userId > 0 {
return userId, nil
} else {
return 0, errors.New("userId le zero")
}
}
return 0, err
```
**小结**
Go 语言编码规范需尽早去学习,越早越好,否则开发项目之后,回头再看,自己肯定走了很多弯路。另外优秀的 IDE 工具有时候也会提示你按照规范去写,一边开发一边积累这些有用的规范。以上编码规范若有问题或有不详尽之处,请另行补充通知我。
以上所述就是小编给大家介绍的《用 Go 开发接口服务--Go 语言编码规范》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 编码最佳实践——接口分离原则
- 编码、摘要和加密(一)——字节编码
- 新媒体编码时代的技术:编码与传输
- MySQL数据库字符编码总结--数据传输编码
- PHP 开发者学 Golang 之 URL 编码 (Urlencode)、解编码 (Urldecode)
- ios平台实现视频H264硬编码及软编码(附完整demo)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
WebWork in Action
Jason Carreira、Patrick Lightbody / Manning / 01 September, 2005 / $44.95
WebWork helps developers build well-designed applications quickly by creating re-usable, modular, web-based applications. "WebWork in Action" is the first book to focus entirely on WebWork. Like a tru......一起来看看 《WebWork in Action》 这本书的介绍吧!