欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go code review 代碼調(diào)試

 更新時間:2022年11月02日 14:50:40   作者:洛天楓  
這篇文章主要為大家介紹了go code review 代碼調(diào)試方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

Examples

在添加新包時,包括預期使用的示例:

  • 一個可運行的示例
  • 或一個演示完整調(diào)用序列的簡單測試

Goroutine Lifetimes

當你使用 goroutines 時,要明確它們何時退出或者是否退出。

goroutine 可以通過阻塞通道發(fā)送或接收而泄漏: 即使阻塞的通道不可達,垃圾收集器也不會終止 goroutine。

即使 goroutine 沒有泄漏,當它們不再被需要時,將它們留在空中也會導致其他微妙和難以診斷的問題。發(fā)送在已關(guān)閉的通道時會引發(fā) panic。“在結(jié)果不需要之后”修改仍在使用的輸入仍然會導致數(shù)據(jù)競爭。并且讓 goroutines 在運行中停留任意長的時間會導致不可預測的內(nèi)存使用。

盡量保持并發(fā)代碼足夠簡單,這樣 goroutine 的生存期就很明顯了。如果這是不可行的,記錄下 goroutines 退出的時間和原因。

有些時候我們使用 goroutine 的時候,會忘記捕獲 panic,這里提供一個封裝好了的 go 方法:

// GoSafe runs the given fn using another goroutine, recovers if fn panics.
func GoSafe(log *log.Logger, fn func()) {
   go RunSafe(log, fn)
}
// RunSafe runs the given fn, recovers if fn panics.
func RunSafe(log *log.Logger, fn func()) {
   defer Recover(log)
   fn()
}
// Recover is used with defer catch panics.
func Recover(log *log.Logger) {
   if p := recover(); p != nil {
      log.Error("%s\n%s", p, debug.Stack())
   }
}

Handle Errors

不要使用 _ 變量丟棄錯誤。如果函數(shù)返回錯誤,請檢查它以確保函數(shù)成功。處理錯誤,返回錯誤,或者,在真正異常的情況下,拋出 panic。

可以參考官方文檔中優(yōu)雅的做法:Effective Go

import

避免重命名導入,除非是為了避免名稱沖突

好的包名不需要重命名。如果發(fā)生沖突,最好重命名、本地的或特定于項目的導入。

導入按組區(qū)分,組與組之間有空白行。標準庫包總是在第一組中。

package main
import (
	"fmt"
	"hash/adler32"
	"os"
	"appengine/foo"
	"appengine/user"
	"github.com/foo/bar"
	"rsc.io/goversion/version"
)

使用 goimport 能幫助到您,所以在項目中配置 goimport 是必要的。

Import Blank

僅為其副作用而導入的包(使用import _ "pkg"語法)應該只在程序的主包中導入,或在需要它們的測試中導入。

類似使用其他包的 init 函數(shù)

Import Dot

import . 在解決循環(huán)依賴時較為好用的方式,但是不能濫用:

package foo_test
import (
	"bar/testutil" // also imports "foo"
	. "foo"
)

在這種情況下,測試文件不能在包 foo 中,因為它使用 bar/testutil,它導入 foo。所以我們使用 'import .' 形式讓文件假裝是包 foo 的一部分,即使它不是。除了這種情況,不要使用import .在你的項目中。它使程序更加難以閱讀,因為不清楚像 Quux 這樣的名稱是當前包還是導入包中的頂級標識符。

In-Band Errors

C 和類似的語言中,函數(shù)通常會返回 -1 或 null 這樣的值來表示錯誤或默認結(jié)果:

// Lookup returns the value for key or "" if there is no mapping for key.
func Lookup(key string) string
// Failing to check for an in-band error value can lead to bugs:
Parse(Lookup(key))  // returns "parse failure for value" instead of "no value for key"

Go 對多個返回值的支持提供了更好的解決方案。與其要求客戶端檢查帶內(nèi)錯誤值,函數(shù)應該返回一個額外的值來指示它的其他返回值是否有效。這個返回值可能是一個錯誤,也可能是一個不需要解釋的布爾值。它應該是最終的返回值。

// Lookup returns the value for key or ok=false if there is no mapping for key.
func Lookup(key string) (value string, ok bool)

這可以防止調(diào)用者錯誤地使用返回值:

Parse(Lookup(key))  // compile-time error

并鼓勵更健壯和可讀的代碼:

value, ok := Lookup(key)
if !ok {
	return fmt.Errorf("no value for %q", key)
}
return Parse(value)

該規(guī)則適用于導出函數(shù),但也適用于私有函數(shù)。

當它們是函數(shù)的有效結(jié)果時,像 nil、""、0 和 -1 這樣的值是可以的,也就是說,當調(diào)用者不需要以不同于其他值的方式處理它們時。

一些標準庫函數(shù),比如包 strings 中的函數(shù),返回帶內(nèi)錯誤值。這極大地簡化了字符串操作代碼,但代價是需要程序員付出更多努力。一般來說,Go代碼應該返回額外的錯誤值。

Indent Error Flow

盡量將正常的代碼路徑縮進到最小,并縮進錯誤處理,首先處理它。這通過允許快速視覺掃描正常路徑提高了代碼的可讀性。例如,不要寫:

if err != nil {
	// error handling
} else {
	// normal code
}

相反,寫:

if err != nil {
	// error handling
	return // or continue, etc.
}
// normal code

如果語句中有初始化語句,例如:if

if x, err := f(); err != nil {
	// error handling
	return
} else {
	// use x
}

然后,這可能需要將短變量聲明移動到它自己的行:

x, err := f()
if err != nil {
	// error handling
	return
}
// use x

Initialisms

名字中屬于首字母縮寫或首字母縮寫的詞(例如:"URL""NATO")的大小寫是一致的。例如,"URL"應該顯示為 "URL""url" (如"urlPony""URLPony"),而不是"Url"。例如:ServeHTTP而不是ServeHttp。對于具有多個初始化“單詞”的標識符,可以使用例如"xmlHTTPRequest""XMLHTTPRequest"。

"ID""identifier"的縮寫時,這個規(guī)則也適用于"ID"(在大多數(shù)情況下,它不是"ego""superego"中的"ID"),所以寫"appID"而不是"appId"。

protobuf 生成的代碼不受此規(guī)則約束。人類編寫的代碼要比機器編寫的代碼具有更高的標準。

Interfaces

Go 接口通常屬于使用接口類型值的包,而不是實現(xiàn)這些值的包。實現(xiàn)包應該返回具體的(通常是指針或結(jié)構(gòu))類型:這樣,新的方法就可以添加到實現(xiàn)中,而不需要大量的重構(gòu)。

不要在API的實現(xiàn)者端定義 "mock" 接口;相反,應該設(shè)計API,以便可以使用實際實現(xiàn)的公共API進行測試。

不要在使用之前定義接口:沒有一個實際的使用示例,很難判斷接口是否必要,更不用說它應該包含哪些方法了。(有點重構(gòu)的意思,將已有的方法抽象起來)

package consumer  // consumer.go
type Thinger interface { Thing() bool }
func Foo(t Thinger) string { … }
package consumer // consumer_test.go
type fakeThinger struct{ … }
func (t fakeThinger) Thing() bool { … }
…
if Foo(fakeThinger{…}) == "x" { … }
// DO NOT DO IT!!!
package producer
type Thinger interface { Thing() bool }
type defaultThinger struct{ … }
func (t defaultThinger) Thing() bool { … }
func NewThinger() Thinger { return defaultThinger{ … } }

相反,返回一個具體類型,并讓使用者模擬生產(chǎn)者實現(xiàn)。

package producer
type Thinger struct{ … }
func (t Thinger) Thing() bool { … }
func NewThinger() Thinger { return Thinger{ … } }

Line Length

在Go代碼中沒有嚴格的行長限制,但是要避免令人不舒服的長行。類似地,當行更長的時候,不要添加換行符以保持行短——例如,如果它們是重復的。

大多數(shù)情況下,當人們“不自然地”換行時(或多或少地在函數(shù)調(diào)用或函數(shù)聲明中換行,盡管存在一些異常),如果它們有合理數(shù)量的參數(shù)和合理較短的變量名,換行將是不必要的。較長的行似乎和較長的名字聯(lián)系在一起,去掉長名字會有很大幫助。

換句話說,斷行是因為你所寫的內(nèi)容的語義(作為一般規(guī)則),而不是因為行長。如果您發(fā)現(xiàn)這產(chǎn)生了太長行,那么更改名稱或語義,您可能會得到一個好的結(jié)果。

實際上,這與函數(shù)的長度是完全相同的。沒有“函數(shù)永遠不會超過N行的規(guī)則”,但確實存在過長的函數(shù),以及重復過小的函數(shù),解決方法是改變函數(shù)的邊界,而不是開始計數(shù)行數(shù)。

Mixed Caps

Effective Go

Named Result Parameters

想想在 godoc 中會是什么樣子。命名結(jié)果參數(shù)如下:

func (n *Node) Parent1() (node *Node) {}
func (n *Node) Parent2() (node *Node, err error) {}

將在 godoc 中重復;更好的使用:

func (n *Node) Parent1() *Node {}
func (n *Node) Parent2() (*Node, error) {}

另一方面,如果函數(shù)返回兩個或三個相同類型的參數(shù),或者如果從上下文不清楚結(jié)果的含義,添加名稱在某些上下文中可能是有用的。不要為了避免在函數(shù)內(nèi)部聲明 var 而命名結(jié)果參數(shù);以不必要的API冗長為代價來換取較小的實現(xiàn)簡便性。

func (f *Foo) Location() (float64, float64, error)

不如:

// Location returns f's latitude and longitude.
// Negative values mean south and west, respectively.
func (f *Foo) Location() (lat, long float64, err error)

如果函數(shù)只有幾行,裸返回是可以的。一旦它是一個中等大小的函數(shù),就要顯式地顯示返回值。推論:僅僅因為結(jié)果參數(shù)允許使用裸返回而命名結(jié)果參數(shù)是不值得的。清晰的文檔總是比在函數(shù)中節(jié)省一兩行更重要。

最后,在某些情況下,您需要命名結(jié)果參數(shù),以便在延遲閉包中更改它。這總是可以的。

Naked Returns

沒有參數(shù)的語句返回指定的返回值。這就是所謂的“裸返回”。

func split(sum int) (x, y int) {
	x = sum * 4 / 9
	y = sum - x
	return
}

Package Comments

包注釋,像 godoc 提供的所有注釋一樣,必須出現(xiàn)在 package 的上面,不能有空行。

// Package math provides basic constants and mathematical functions.
package math
/*
Package template implements data-driven templates for generating textual
output such as HTML.
....
*/
package template

對于 "package main" 注釋,其他風格的注釋在二進制名稱之后也可以(如果它在前面,則可以大寫),例如,對于您可以編寫的目錄中的

// Binary seedgen ...
package main
// Command seedgen ...
package main
// Program seedgen ...
package main
// The seedgen command ...
package main
// The seedgen program ...
package main
// Seedgen ..
package main

這些都是例子,合理的變體也是可以接受的。

注意,以小寫單詞開頭的句子不屬于包注釋的可接受選項,因為它們是公開可見的,應該用正確的英語編寫,包括句子的第一個單詞大寫。當二進制名稱是第一個單詞時,即使它與命令行調(diào)用的拼寫不嚴格匹配,也需要將其大寫。

Effective Go

struct

每個結(jié)構(gòu)體必須有自己的構(gòu)造函數(shù),并且使用 options 模式來構(gòu)建新的參數(shù)。

以上就是go code review 代碼調(diào)試的詳細內(nèi)容,更多關(guān)于go code review的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文詳解kubernetes?中資源分配的那些事

    一文詳解kubernetes?中資源分配的那些事

    這篇文章主要為大家介紹了kubernetes?中資源分配的那些事,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • Go語言結(jié)構(gòu)體定義和使用方法

    Go語言結(jié)構(gòu)體定義和使用方法

    這篇文章主要介紹了Go語言結(jié)構(gòu)體定義和使用方法,以實例形式分析了Go語言中結(jié)構(gòu)體的定義和使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 詳解如何使用Bazel構(gòu)建Golang程序

    詳解如何使用Bazel構(gòu)建Golang程序

    這篇文章主要為大家介紹了如何使用Bazel構(gòu)建Golang程序?qū)嵗斀猓行枰呐笥芽梢越梃b參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Go語言錯誤處理異常捕獲+異常拋出

    Go語言錯誤處理異常捕獲+異常拋出

    這篇文章主要介紹了Go語言錯誤處理異常捕獲和異常拋出,Go語言的作者認為java等語言的錯誤處理底層實現(xiàn)較為復雜,就實現(xiàn)了函數(shù)可以返回錯誤類型以及簡單的異常捕獲,雖然簡單但是也非常精妙,大大的提高了運行效率,下文需要的朋友可以參考一下
    2022-02-02
  • Golang logrus 日志包及日志切割的實現(xiàn)

    Golang logrus 日志包及日志切割的實現(xiàn)

    這篇文章主要介紹了Golang logrus 日志包及日志切割的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • 詳解Go語言中配置文件使用與日志配置

    詳解Go語言中配置文件使用與日志配置

    這篇文章主要為大家詳細講解一下Go語言中調(diào)整項目目錄結(jié)構(gòu)、增加配置文件使用和增加日志配置的方法,文中示例代碼講解詳細,需要的可以參考一下
    2022-06-06
  • Go解析不定JSON數(shù)據(jù)的方法詳解

    Go解析不定JSON數(shù)據(jù)的方法詳解

    在開發(fā)中常常會碰到很多JSON類型的數(shù)據(jù)進行交互,而其中有很多JSON數(shù)據(jù)你是不能確定它的字段和結(jié)構(gòu)的,而Go語言是一門靜態(tài)強類型的語言,在進行JSON解析的時候必須要確定字段的類型,本文給大家介紹了Go如何解析不定JSON數(shù)據(jù),需要的朋友可以參考下
    2024-03-03
  • go語言實現(xiàn)兩個協(xié)程交替打印

    go語言實現(xiàn)兩個協(xié)程交替打印

    這篇文章主要介紹了go語言實現(xiàn)兩個協(xié)程交替打印,文章主要分享了兩種方法使用兩個channel和使用一個channel,內(nèi)容介紹詳細具有一定的參考價值,需要的小伙伴可以參考一下
    2022-03-03
  • golang常用庫之gorilla/mux-http路由庫使用詳解

    golang常用庫之gorilla/mux-http路由庫使用詳解

    這篇文章主要介紹了golang常用庫之gorilla/mux-http路由庫使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • GO日志打印如何添加goroutineid

    GO日志打印如何添加goroutineid

    今天想給日志添加一個前綴,以區(qū)分不同goroutine的日志,方便做并發(fā)問題的排查,做日志跟蹤,下面給大家分享GO日志打印如何添加goroutineid,感興趣的朋友跟隨小編一起看看吧
    2024-05-05

最新評論