分享一套Go編碼規範!歡迎收藏!
最近在專案中也 codereview 了不少 Go 語言的程式碼,有必要總結下程式碼規範,算是一個筆記記錄了。
說在前面,這只是我們團隊的一套規範而已。
今天我們聊聊 Go 的編碼規範,大概分成幾大模組,如註包/變數/常數命名、基本語法、函數、錯誤處理、心得等。 【推薦:golang教學】
1. 程式碼風格
1.1 程式碼格式
- 程式碼必須用gofmt 格式化,goland 可以配置,可以自行搜尋配置
- 我們寫的程式碼每行應該不超過120 個字符,超出部分用換行解決。
- 單一檔案最大行數最大不超過 800 行.
- 單一函數最大行數不超過 80 行。
- import 規範
- 不要使用相對路徑引入包,例如
import ../util/net
- 在導入包時,多個相同包名衝突時,必須使用匯入別名
- 不要使用相對路徑引入包,例如
// bad "github.com/google/uuid" // good uuid "github.com/google/uuid"
- 匯入的套件建議分組,引用匿名套件建議用一個新的分組,並加上註解方便後面小夥伴閱讀
import ( // Go 标准库 "fmt" //第三方包 "github.com/jinzhu/gorm" "github.com/google/uuid" "github.com/go-redis/redis/v8" // 匿名包 /import mysql driver _"github.com/jinzhu/gorm/dialects/mysql" // 内部包 slice "xxx.local/pkg/v1/goslice" meta "xxx.local/pkg/v1/meta" gomap "xxx.local/pkg/v2/gomap")
1.2 宣告、初始化和定義
- 一個函數需要使用多個變數時,可以在函數最開頭處使用var 宣告。在函數外部宣告的變數不能使用 :=,會踩坑,不知道的可以評論區留言(要評論不易呀)!
var ( port = 8081 metricServerPort = 2001)
- 在初始化結構體用 &struct 取代 new(struct),確保與結構體初始化一致,初始化結構體時換行。
// bad stu := new(S) stu.Name = "张三" // good stu := &S{ Name:"李四" }
- 使用 make 在聲明 map、array 等應該指定容器的容量,從而達到預先分配內容。
users := make(map[int]string, 10)tags := make([]int, 0, 10)
- 使用標準 var 關鍵字事,不要指定類型,除非它與表達式的類型不同。
// bad var _f string F() func F() string { return "hello world!" } // good var _f F() func F() string { return "hello world!" }
1.3 error 處理
- 若函數傳回 error, 必須對 error 進行處理,如果業務允許可以用 _ 接受忽略。對應 defer 可以不用明確處理。
// bad func InitConfig() error { ... } InitConfig() // good func InitConfig() error { ... } err := InitConfig() if err != nil { ... } // or _ := InitConfig()
- error 作為回傳值時必須作為最後一個參數傳回
// bad func InitConfig() (error,int) { ... } // good func InitConfig() (int, error) { ... }
- 錯誤需要單獨處理,盡量不要與其他的邏輯耦合在一起。
// bad res, err := InitConfig() if err != nil || res != nil { return err } // good res, err := InitConfig() if err != nil { return err } if res != nil { return fmt.Errorf("invalid result") }
1.4 panic處理
- 在業務程式碼中禁止拋出 panic 錯誤。
- panic 只允許出現在在服務啟動之前,例如讀取配置、連結儲存(redis、mysql 等)。
- 業務程式碼中建議用 error 而不是 panic 來傳遞。
1.5 單元測試
- 每個重要的函數都要寫測試案例,合併程式碼要自動化執行一下所有的 test。
- 檔案命名 xxx_test.go。
- 函數命名建議使用 Test函數名稱。
2. 命名規範
在每個語言中,命名規範在程式碼規範中非常重要,一個統一的、精確的命名不僅僅可以提高程式碼的可讀性,也可以讓人覺的這個同志真的會呀。牛!
2.1 包命名规范
- 包名必须与目录名一致(这和其他 php、Java 还是有一点不太一样的),尽量采取有意义、简短的包名,不要与 go 的标准库名称一样。
- 包名小写,没有下划线,可以使用中划线隔开,使用多级目录来划分目录。
- 包名不要出现复数命名。
- 包名命名尽量简单一目了然,ge:user、log。
2.2 文件命名规范
- 文件名要见名思义,尽量简而短
- 文件名小写,组合词用下划线分割
2.3 函数命名规范
- 与 php、Java 一样,必须遵循驼峰规范,Go 语言中需要根据访问的控制决定大驼峰还是小驼峰。
- 单元测试的函数用大驼峰,TestFunc。
2.4 结构体命名规范
- 与 php、Java 一样,必须遵循驼峰规范,Go 语言中需要根据访问的控制决定大驼峰还是小驼峰。
- 避免使用 info 、data 这种无意义的名称。
- 命名使用名词而非动词。
- 结构体在声明和初始化的时候需要换行,eg:
type Student struct{ Name string Age uint8}student := Student{ Name: "张三", Age: 18,}
2.5 变量命名规范
- 和 php、Java 一样,必须遵循驼峰规范,Go 语言中需要根据访问的控制决定大驼峰还是小驼峰。
- 若变量为私有时,可以使用小写命名。
- 局部变量可以简写,eg:i 表示 index。
- 若变量代表 bool 值,则可以使用 Is 、Can、Has 前缀命名,eg:
var isExit boolvar canReturn bool
2.6 常量命名规范
- 必须遵循驼峰规范,Go 语言中需要根据访问的控制决定大驼峰还是小驼峰。
- 若代表枚举值,需要先创建。
type Code intconst ( ErrNotFound Code = iota ErrFatal)
3. 类型
3.1 字符串
好像学过的语言中,都是从字符串开始说起的。就像写代码第一行都是从 Hello World!一样!同意的点赞哈。
- 字符串判空值
// bad if s == "" { ...} // good if len(s) == 0 { ...}
- 字符串去除前后子串。
// bad var s1 "hello world"var s2 "hello"var s3 strings.TrimPrefix(s1, s2) // good var s1 "hello world"var s2 "hello"var s3 stringif strings.HasPrefix(s1, s2){ s3 = s1[len(s2):]}
3.2 切片 slice
- 声明 slice。
// bad s := []string{}s := make([]string, 10) // good var s []string s := make([]string, 0, 10)
- 非空判断。
//bad if len(slice) >0 { ...} // good if slice != nil && len(slice) > 0 { ...}
- slice copy。
// badvar b1,b2 []bytefor i, v := range b1 { b2[i] = v}for i := range b1 { b2[i] = b1[i]}// goodcopy(b2,b1)
- slice 新增。
// bad var a,b []intfor _, v := range a { b = append(b,v)} // good var a, b []int b := append(b, a...)
3.4 结构体 struct
- 初始化需要多行。
type Student struct{ Name string Age uint8}student := Student{ Name: "张三", Age: 18,}
4. 控制语句
4.1 if
- if 可以用局部变量的方式初始化。
if err := InitConfig; err != nil { return err}
4.2 for
- 不允许在 for 中使用 defer, defer 只在函数结束时才会执行。
// bad for file := range files { fd, err := os.Open(file) if err != nil { return err } defer fd.close()} // good for file := range files{ func() { fd,err := os.open(file) if err!=nil { return err } defer fd.close() }()}
4.3 range
- 如果不需要 key 直接用 _ 忽略,value 也一样。
for _, v := range students { ...}for i, _ := range students { ...}for i, v := range students { ...}
注: 若操作指针时请注意不能直接用 s := v。想知道可以评论区告诉我哦!
4.4 switch
- 和其他语言不一样,必须要有 defalt
switch type { case 1: fmt.Println("type = 1") break case 2: fmt.Println("type = 2") break default : fmt.Println("unKnown type")}
4.5 goto
- 业务中不允许使用 goto。
- 框架和公共工具也不允许使用 goto。
5. 函数
- 传参和返回的变量小写字母。
- 传入参数时slice、map、interface、chan 禁止传递指针类型。
- 采用值传递,不用指针传值。
- 入参个数不能超出 5 个,超过的可以用 struct 传值。
5.1 函数参数
- 返回值超出 1 个时,需要用变量名返回。
- 多个返回值可以用 struct 传。
5.2 defer
- 当操作资源、或者事物需要提交回滚时,可以在创建开始下方就使用 defer 释放资源。
- 创建资源后判断 error,非 error 情况后在用 defer 释放。
5.3 代码嵌套
- 为了代码可读性,为了世界和平,尽量别用太多的嵌套,因为真的很难有人类能看懂。
6. 日常使用感悟
- 能不用全局变量就不用,可以用参数传值的方式,这样可以大大降低耦合,更有利于单元测试。
- 衣服开发中,在函数间多用 context 传递上下文,在请求开始时可以生成一个 request_id,便于链路、日志追踪。
6.1 提高性能
- 在业务开发中,尽量使用 strconv 来替代 fmt。
- 我们在使用 string 字符串类型时,当修改的场景较多,尽量在使用时用 []byte 来替代。因为每次对 string 的修改都需要重新在申请内存。
6.2 避免踩坑
- append 要小心自动扩容的情况,最好在申明时分配好容量,避免扩容所带来的性能上的损耗以及分配新的内存地址。若不能确定容量,应选择一个比较大一点的值。
- 并发场景下,map 非线程安全,需要加锁。还有一种评论区告诉我吧。
- interface 在编译期间无法被检查,使用上会出现 panic,需要注意
7. 总结
本篇很讲了 Go 语言的编码规范,当时想说的,规范是大家预定的东西,每个公司、团队都会有不一样的规范,只要大家一起遵循就好啦。你可以根据自己团队的需求,定一套属于自己团队的项目规范。如果想小伙伴一起遵循,可以借助一些工具来保障执行度。
讲了很多,虽然很基础,希望对于刚刚转 Go 语言,或者刚学习 Go 语言的同学有帮助吧。今天就到这里了。希望得到大家的一键三连。感谢!
本文系转载,原文链接:mp.weixin.qq.com/s/lfjP9DEia2WL4Ua...
以上是分享一套Go編碼規範!歡迎收藏!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

在Go中安全地讀取和寫入檔案至關重要。指南包括:檢查檔案權限使用defer關閉檔案驗證檔案路徑使用上下文逾時遵循這些準則可確保資料的安全性和應用程式的健全性。

如何為Go資料庫連線配置連線池?使用database/sql包中的DB類型建立資料庫連線;設定MaxOpenConns以控制最大並發連線數;設定MaxIdleConns以設定最大空閒連線數;設定ConnMaxLifetime以控制連線的最大生命週期。

Go框架憑藉高效能和並發性優勢脫穎而出,但也存在一些缺點,例如相對較新、開發者生態系統較小、缺乏某些功能。此外,快速變化和學習曲線可能因框架而異。 Gin框架以其高效路由、內建JSON支援和強大的錯誤處理而成為建立RESTfulAPI的熱門選擇。

GoLang框架與Go框架的差異體現在內部架構與外部特性。 GoLang框架基於Go標準函式庫,擴充其功能,而Go框架由獨立函式庫組成,以實現特定目的。 GoLang框架更靈活,Go框架更容易上手。 GoLang框架在效能上稍有優勢,Go框架的可擴充性更高。案例:gin-gonic(Go框架)用於建立RESTAPI,而Echo(GoLang框架)用於建立Web應用程式。

可以透過使用gjson函式庫或json.Unmarshal函數將JSON資料儲存到MySQL資料庫中。 gjson函式庫提供了方便的方法來解析JSON字段,而json.Unmarshal函數需要一個目標類型指標來解組JSON資料。這兩種方法都需要準備SQL語句和執行插入操作來將資料持久化到資料庫中。

最佳實踐:使用明確定義的錯誤類型(errors套件)建立自訂錯誤提供更多詳細資訊適當記錄錯誤正確傳播錯誤,避免隱藏或抑制根據需要包裝錯誤以添加上下文

如何在Go框架中解決常見的安全問題隨著Go框架在Web開發中的廣泛採用,確保其安全至關重要。以下是解決常見安全問題的實用指南,附帶範例程式碼:1.SQL注入使用預編譯語句或參數化查詢來防止SQL注入攻擊。例如:constquery="SELECT*FROMusersWHEREusername=?"stmt,err:=db.Prepare(query)iferr!=nil{//Handleerror}err=stmt.QueryR

FindStringSubmatch函數可找出正規表示式匹配的第一個子字串:此函數傳回包含匹配子字串的切片,第一個元素為整個匹配字串,後續元素為各個子字串。程式碼範例:regexp.FindStringSubmatch(text,pattern)傳回符合子字串的切片。實戰案例:可用於匹配電子郵件地址中的域名,例如:email:="user@example.com",pattern:=@([^\s]+)$獲取域名match[1]。
