天天看點

golang 編碼規範

  • 命名規則
  1. 常量
* 常量應遵循首字母大寫的駝峰命名法,同時盡可能言簡意赅
如:const PayChannelBank = 1
不建議使用全部大寫字母組成,并以下劃線分詞
如: const PAY_CHANNEL_BANK = 1

* 相關的常量應盡可能的放在一起定義,也可以全部放在 const.go 檔案中
           
  1. 變量
* 變量命名應遵循駝峰命名法,同時盡可能言簡意赅
如:var orderId int64

* 若變量為 `bool` 類型,則名稱應以 `has` `is` `can` `allow` 等開頭
如: var isExist bool
    var hasConflict bool
           
  1. 函數與方法
* 函數與方法命名應遵循駝峰命名法,同時盡可能言簡意赅
如:func GetOrder(ctx context, orderId int64) (*order, error) {...}

* 若函數或方法為判斷類型(傳回值主要為 bool 類型),則名稱應以 Has, Is, Can 或 Allow 等判斷性動詞開頭
如: func HasPrefix(name string, prefixes []string) bool {...}
    func IsEntry(name string, entries []string) bool {...}

* 函數聲明應盡可能提高代碼使用率
如: func QueryLegalPerson(db *gorm.DB, where map[string]interface{}) ([]*LegalPerson, int32, error)
不建議一種查詢條件聲明一個方法:
如: func QueryLegalPersonById(db *gorm.DB, id int64) ([]*LegalPerson, int32, error)
           
  1. 檔案名
* 檔案名應全部小寫并通過下劃線連接配接,同時盡可能言簡意赅
如:bank_pay.go
不建議: bank_pay_service.go 
是 service 還是 model 可以通過上層目錄判斷
           
  1. 包名
* 應全部小寫。沒有大寫或下劃線
* 大多數使用命名導入的情況下,不需要重命名
* 應簡短而簡潔,不可用複數,如: net/url,而不是net/urls
           
  • 聲明語句
  1. 常量
* 常量聲明應盡可能在 /internal/common/const.go 檔案中

* 若不在上述檔案中,應放在導包之後,定義全局變量之前
           
  1. 變量
* 全局變量應放在常量之後,定義結構體之前

* 對于比較重要的局部變量建議通過 `var` 來聲明,其他的應盡可能使用 `:=` 短變量聲明

* 零值切片可立即使用,無需調用 `make` 建立,如:
var nums []int

if add1 {
  nums = append(nums, 1)
}

* 使用字段名初始化結構體,如:
k := User{
    FirstName: "John"
}
           
  1. 函數與方法
* 入參一定要指定參數名與類型,出參一定不要指定參數名,如:
func PublishPayAccountAddEvt(ctx context.Context, req *proto.CreatePayAccountRecordReq, accountId int64) error

* 對于有error出參函數或方法,一般習慣性将error放在最後一個出參位置,如:
func CreatePayAccount(db *gorm.DB, data map[string]interface{}) (int64, error)

* 函數與函數,方法與方法之間應留一行空白
           
  • 注釋
* 注釋應使用//+空格+注釋資訊,注意描述資訊前留白格

* 函數或方法注釋,應以函數或方法名開頭,并配有描述資訊,如:
// OnlinePayment 銀企線上支付
func (s *bankPaymentService) OnlinePayment(ctx context.Context, in *proto.OnlinePaymentReq, out *proto.OnlinePaymentRsp) error {...}

* 對于未實作的功能,可以先用 `// TODO 描述資訊` 辨別,以待後期調整

* 注釋要盡可能的言簡意赅,避免無意義注釋,對于複雜的邏輯可以直接貼tapd需求連結。
           
  • 日志
* 對于錯誤日志應統一使用 `log.ErrorS` 記錄,其他日志應統一使用  `log.InfoS` 記錄

* 對于日志中要列印的複雜參數,盡可能用 `%#v` 格式化輸出,如:
log.InfoS(req.GetHead().GetSeq(), "[UpdatePayAccountRecord] rsp[%#v]", rsp.String())

* 錯誤日志除記錄錯誤資訊外,應記錄目前方法以及抛出錯誤的函數或方法,如:
log.ErrorS(seq, "[TransferCallback] models.UpdatePayBatchByBatchNo batch_no: %v, err: %v", batchNo, err)

* 在handle層,每個請求的入參與出參必須要記錄日志,如:
log.InfoS(req.GetHead().GetSeq(), "[QueryPayAccountRecord] receive req[%s]", req.String())
log.InfoS(req.GetHead().GetSeq(), "[QueryPayAccountRecord] rsp[%#v]", rsp.String())

* 對于依賴的第三方請求,入參與出參必須要記錄日志,如:
log.InfoS(seq, "[TransferBatch] req %v", param)
log.InfoS(seq,"[TransferBatch] rsp %#v", *result)
           
  • 雜項
* 應減少使用 else,可優化成,如:
a := 10
if b {
  a = 100
}

* 方法或函數若有傳回值,則必須接收。若傳回值對業務無關緊要,可以使用`_`忽略,如:
_ = event.PublishPayAccountDeleteEvt(context.Background(), in)

* 檔案修改後,必須使用gofmt等工具格式化代碼
           
  • 項目結構(建議)
cmd/                    // 入口函數
    main.go         
dbsql/                  // sql備份
    tb_pay_order.sql
    ...
internal/               // 内部服務
    common/             // 公共檔案目錄
        common.go       // 通用幫助函數
        const.go        // 常量檔案
        ...
    config/             // 配置
        config.go       // 讀取xconf配置并聲明全局變量
    event/              // 事件
        event.go
    handle/             // server層
        handle.go
        ...
    model/              // 模型層
        pay_order.go
        ...
    queue/              // 隊列服務
        queue.go
        ...
    service/            // service 層
        service.go      
        ...
    task/               // 定時任務
        task.go
        ...