Kongsi satu set standard pengekodan Go! Selamat datang untuk mengumpul!

藏色散人
Lepaskan: 2022-12-09 17:10:05
ke hadapan
5603 orang telah melayarinya

Baru-baru ini, saya telah menyemak banyak kod bahasa Go dalam projek itu adalah perlu untuk meringkaskan spesifikasi kod, yang boleh dianggap sebagai rekod nota.

Seperti yang dinyatakan di atas, ini hanyalah satu set norma untuk pasukan kami.

Hari ini kita akan bercakap tentang piawaian pengekodan Go, yang dibahagikan secara kasar kepada beberapa modul utama, seperti suntikan pakej/pembolehubah/penamaan malar, sintaks asas, fungsi, pengendalian ralat, pengalaman, dsb. [Disyorkan: tutorial golang]

1. Gaya kod

1.1 Format kod

  • Kod mesti diformatkan dengan gofmt, goland can Configuration , anda boleh mencari konfigurasi sendiri
  • Setiap baris kod yang kami tulis tidak boleh melebihi 120 aksara, dan bahagian yang berlebihan harus diselesaikan dengan pemisah baris.
  • Bilangan maksimum baris dalam satu fail tidak melebihi 800 baris.
  • Bilangan maksimum baris dalam satu fungsi tidak melebihi 80 baris.
  • Spesifikasi import
    • Jangan gunakan laluan relatif untuk memperkenalkan pakej, seperti import ../util/net
    • Apabila mengimport pakej, apabila beberapa nama pakej yang sama bercanggah, anda mesti menggunakan import alias
// bad
"github.com/google/uuid"

// good
uuid "github.com/google/uuid"
Salin selepas log masuk
  • Pakej yang diimport disyorkan untuk dihimpunkan Rujukan pakej tanpa nama disyorkan untuk digunakan dalam kumpulan baharu, dan ulasan ditambahkan untuk memudahkan pembacaan oleh rakan seterusnya
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")
Salin selepas log masuk

1.2 Pengisytiharan, Permulaan dan Definisi

  • Apabila fungsi perlu menggunakan berbilang pembolehubah, anda boleh menggunakan perisytiharan var pada permulaan fungsi. Pembolehubah yang diisytiharkan di luar fungsi tidak boleh digunakan :=, yang mungkin membawa kepada perangkap Jika anda tidak tahu, anda boleh meninggalkan mesej di kawasan komen (tidak mudah untuk mengulas)!
var (
    port = 8081
    metricServerPort = 2001)
Salin selepas log masuk
  • Gunakan &struct dan bukannya new(struct) semasa memulakan struktur untuk memastikan ia konsisten dengan permulaan struktur, dan balut garisan apabila memulakan struktur.
// bad
stu := new(S)
stu.Name = "张三"

// good
stu := &S{
    Name:"李四"
}
Salin selepas log masuk
  • Menggunakan make harus menyatakan kapasiti bekas apabila mengisytiharkan peta, tatasusunan, dsb., untuk pra-peruntukkan kandungan.
users := make(map[int]string, 10)tags := make([]int, 0, 10)
Salin selepas log masuk
  • Gunakan kata kunci var standard dan jangan nyatakan jenis melainkan ia berbeza daripada jenis ungkapan.
// bad
var _f string F()

func F() string {
    return "hello world!"
}

// good 
var _f F()

func F() string {
    return "hello world!"
}
Salin selepas log masuk

1.3 Ralat pemprosesan

  • Jika fungsi mengembalikan ralat, ralat mesti diproses Jika perniagaan membenarkan, anda boleh menggunakan _ untuk menerima dan mengabaikan ia. Penangguhan yang sepadan boleh diproses tanpa pemprosesan yang jelas.
// bad
func InitConfig() error {
    ...
}
InitConfig()


// good
func InitConfig() error {
    ...
}
err := InitConfig()
if err != nil {
    ...
}
// or 
_ := InitConfig()
Salin selepas log masuk
  • ralat mesti dikembalikan sebagai parameter terakhir apabila digunakan sebagai nilai pulangan
// bad
func InitConfig() (error,int) {
    ...
}

// good 
func InitConfig() (int, error) {
    ...
}
Salin selepas log masuk
  • Ralat perlu dikendalikan. secara berasingan, cuba untuk tidak mencampurkannya dengan logik lain yang digabungkan bersama.
// 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")
}
Salin selepas log masuk

1.4 Pengendalian panik

  • Dilarang membuang ralat panik dalam kod perniagaan.
  • panik hanya dibenarkan muncul sebelum perkhidmatan dimulakan, seperti konfigurasi bacaan, storan pautan (redis, mysql, dll.).
  • Adalah disyorkan untuk menggunakan ralat dan bukannya panik dalam kod perniagaan.

Ujian Unit 1.5

  • Kes ujian mesti ditulis untuk setiap fungsi penting dan semua ujian mesti dijalankan secara automatik apabila menggabungkan kod.
  • Fail itu bernama xxx_test.go.
  • Adalah disyorkan untuk menggunakan nama fungsi Ujian untuk penamaan fungsi.

2. Konvensyen penamaan

Dalam setiap bahasa, konvensyen penamaan adalah sangat penting dalam spesifikasi kod Penamaan yang bersatu dan tepat bukan sahaja dapat Meningkatkan kebolehbacaan kod itu juga boleh membuatkan orang berasa bahawa rakan seperjuangan ini benar-benar tahu bagaimana untuk melakukannya. lembu!

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,}
Salin selepas log masuk
Salin selepas log masuk

2.5 变量命名规范

  • 和 php、Java 一样,必须遵循驼峰规范,Go 语言中需要根据访问的控制决定大驼峰还是小驼峰。
  • 若变量为私有时,可以使用小写命名。
  • 局部变量可以简写,eg:i 表示 index。
  • 若变量代表 bool 值,则可以使用 Is 、Can、Has 前缀命名,eg:
var isExit boolvar canReturn bool
Salin selepas log masuk

2.6 常量命名规范

  • 必须遵循驼峰规范,Go 语言中需要根据访问的控制决定大驼峰还是小驼峰。
  • 若代表枚举值,需要先创建。
type Code intconst (
    ErrNotFound Code = iota
    ErrFatal)
Salin selepas log masuk

3. 类型

3.1 字符串

好像学过的语言中,都是从字符串开始说起的。就像写代码第一行都是从 Hello World!一样!同意的点赞哈。

  • 字符串判空值
// bad
if s == "" {
    ...}
 // good
 if len(s) == 0 {
    ...}
Salin selepas log masuk
  • 字符串去除前后子串。
// 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):]}
Salin selepas log masuk

3.2 切片 slice

  • 声明 slice。
// bad
s := []string{}s := make([]string, 10)
// good
var s []string
s := make([]string, 0, 10)
Salin selepas log masuk
  • 非空判断。
//bad
if len(slice) >0 {
    ...}
 // good
 if slice != nil && len(slice) > 0 {
    ...}
Salin selepas log masuk
  • slice copy。
// badvar b1,b2 []bytefor i, v := range b1 {
    b2[i] = v}for i := range b1 {
    b2[i] = b1[i]}// goodcopy(b2,b1)
Salin selepas log masuk
  • slice 新增。
// bad
var a,b []intfor _, v := range a {
    b = append(b,v)}
// good
var a, b []int
b := append(b, a...)
Salin selepas log masuk

3.4 结构体 struct

  • 初始化需要多行。
type Student struct{
    Name string
    Age uint8}student := Student{
    Name: "张三",
    Age: 18,}
Salin selepas log masuk
Salin selepas log masuk

4. 控制语句

4.1 if

  • if 可以用局部变量的方式初始化。
if err := InitConfig; err != nil {
    return err}
Salin selepas log masuk

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()
    }()}
Salin selepas log masuk

4.3 range

  • 如果不需要 key 直接用 _ 忽略,value 也一样。
for _, v := range students {
    ...}for i, _ := range students {
    ...}for i, v := range students {
    ...}
Salin selepas log masuk

注: 若操作指针时请注意不能直接用 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")}
Salin selepas log masuk

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...

Atas ialah kandungan terperinci Kongsi satu set standard pengekodan Go! Selamat datang untuk mengumpul!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:learnku.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan