Golang編碼規范指導原則04

      網友投稿 850 2022-05-29

      一 不要使用 panic

      在生產環境中運行的代碼必須避免出現 panic。panic 是 級聯失敗 的主要根源 。如果發生錯誤,該函數必須返回錯誤,并允許調用方決定如何處理它。

      Bad

      func run(args []string) { if len(args) == 0 { panic("an argument is required") } // ... } func main() { run(os.Args[1:]) }

      Good

      func run(args []string) error { if len(args) == 0 { return errors.New("an argument is required") } // ... return nil } func main() { if err := run(os.Args[1:]); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }

      panic/recover 不是錯誤處理策略。僅當發生不可恢復的事情(例如:nil 引用)時,程序才必須 panic。程序初始化是一個例外:程序啟動時應使程序中止的不良情況可能會引起 panic。

      var _statusTemplate = template.Must(template.New("name").Parse("_statusHTML"))

      即使在測試代碼中,也優先使用t.Fatal或者t.FailNow而不是 panic 來確保失敗被標記。

      Bad

      // func TestFoo(t *testing.T) f, err := ioutil.TempFile("", "test") if err != nil { panic("failed to set up test") }

      Good

      // func TestFoo(t *testing.T) f, err := ioutil.TempFile("", "test") if err != nil { t.Fatal("failed to set up test") }

      二 使用使用 atomic

      使用 sync/atomic 包的原子操作對原始類型 (int32, int64等)進行操作,因為很容易忘記使用原子操作來讀取或修改變量。

      go.uber.org/atomic 通過隱藏基礎類型為這些操作增加了類型安全性。此外,它包括一個方便的atomic.Bool類型。

      Bad

      type foo struct { running int32 // atomic } func (f* foo) start() { if atomic.SwapInt32(&f.running, 1) == 1 { // already running… return } // start the Foo } func (f *foo) isRunning() bool { return f.running == 1 // race! }

      Good

      type foo struct { running atomic.Bool } func (f *foo) start() { if f.running.Swap(true) { // already running… return } // start the Foo } func (f *foo) isRunning() bool { return f.running.Load() }

      三 避免可變全局變量

      使用選擇依賴注入方式避免改變全局變量。 既適用于函數指針又適用于其他值類型

      Bad

      // sign.go var _timeNow = time.Now func sign(msg string) string { now := _timeNow() return signWithTime(msg, now) } // sign_test.go func TestSign(t *testing.T) { oldTimeNow := _timeNow _timeNow = func() time.Time { return someFixedTime } defer func() { _timeNow = oldTimeNow }() assert.Equal(t, want, sign(give)) }

      Good

      // sign.go type signer struct { now func() time.Time } func newSigner() *signer { return &signer{ now: time.Now, } } func (s *signer) Sign(msg string) string { now := s.now() return signWithTime(msg, now) } // sign_test.go func TestSigner(t *testing.T) { s := newSigner() s.now = func() time.Time { return someFixedTime } assert.Equal(t, want, s.Sign(give)) }

      四 避免在公共結構中嵌入類型

      這些嵌入的類型泄漏實現細節、禁止類型演化和模糊的文檔。

      假設您使用共享的 AbstractList 實現了多種列表類型,請避免在具體的列表實現中嵌入 AbstractList。 相反,只需手動將方法寫入具體的列表,該列表將委托給抽象列表。

      type AbstractList struct {} // 添加將實體添加到列表中。 func (l *AbstractList) Add(e Entity) { // ... } // 移除從列表中移除實體。 func (l *AbstractList) Remove(e Entity) { // ... }

      Bad

      // ConcreteList 是一個實體列表。 type ConcreteList struct { *AbstractList }

      Good

      // ConcreteList 是一個實體列表。 type ConcreteList struct { list *AbstractList } // 添加將實體添加到列表中。 func (l *ConcreteList) Add(e Entity) { l.list.Add(e) } // 移除從列表中移除實體。 func (l *ConcreteList) Remove(e Entity) { l.list.Remove(e) }

      Go 允許 類型嵌入 作為繼承和組合之間的折衷。外部類型獲取嵌入類型的方法的隱式副本。默認情況下,這些方法委托給嵌入實例的同一方法。

      結構還獲得與類型同名的字段。 所以,如果嵌入的類型是 public,那么字段是 public。為了保持向后兼容性,外部類型的每個未來版本都必須保留嵌入類型。

      很少需要嵌入類型。 這是一種方便,可以幫助您避免編寫冗長的委托方法。

      即使嵌入兼容的抽象列表 interface,而不是結構體,這將為開發人員提供更大的靈活性來改變未來,但仍然泄露了具體列表使用抽象實現的細節。

      Bad

      Golang編碼規范之指導原則04

      // AbstractList 是各種實體列表的通用實現。 type AbstractList interface { Add(Entity) Remove(Entity) } // ConcreteList 是一個實體列表。 type ConcreteList struct { AbstractList }

      Good

      // ConcreteList 是一個實體列表。 type ConcreteList struct { list AbstractList } // 添加將實體添加到列表中。 func (l *ConcreteList) Add(e Entity) { l.list.Add(e) } // 移除從列表中移除實體。 func (l *ConcreteList) Remove(e Entity) { l.list.Remove(e) }

      無論是使用嵌入結構還是嵌入接口,都會限制類型的演化。

      向嵌入接口添加方法是一個破壞性的改變。

      從嵌入結構體刪除方法是一個破壞性改變。

      刪除嵌入類型是一個破壞性的改變。

      即使使用滿足相同接口的類型替換嵌入類型,也是一個破壞性的改變。

      盡管編寫這些委托方法是乏味的,但是額外的工作隱藏了實現細節,留下了更多的更改機會,還消除了在文檔中發現完整列表接口的間接性操作。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:云脈OCR紙質文檔管理長久地保存文檔信息
      下一篇:紙質文檔管理系統 實現文檔信息實時存儲管理!
      相關文章
      亚洲色精品aⅴ一区区三区| 亚洲桃色AV无码| 久久精品国产亚洲精品2020| 亚洲精品国产精品乱码视色 | 亚洲男人在线无码视频| 久久精品熟女亚洲av麻豆| 亚洲丰满熟女一区二区哦| 亚洲熟妇无码AV不卡在线播放 | 亚洲色无码专区在线观看| 中文字幕亚洲综合久久菠萝蜜| 亚洲国产成人精品女人久久久 | 亚洲视频一区在线播放| 亚洲美女视频网站| 亚洲日韩在线视频| 久久精品国产亚洲av麻豆蜜芽| 亚洲国产成人久久三区| 久久久久精品国产亚洲AV无码| 亚洲偷偷自拍高清| 亚洲性无码一区二区三区| 亚洲高清毛片一区二区| heyzo亚洲精品日韩| 亚洲中文字幕无码专区| 亚洲美女又黄又爽在线观看| 国产成A人亚洲精V品无码| 亚洲成人在线电影| 亚洲午夜在线一区| 亚洲色www永久网站| 在线亚洲v日韩v| 国产亚洲成归v人片在线观看| 亚洲性猛交XXXX| 一区二区三区亚洲| 亚洲国产成人精品电影| 亚洲人成色99999在线观看| 在线亚洲v日韩v| 亚洲乱码无码永久不卡在线| 亚洲人成电影亚洲人成9999网 | 精品亚洲成A人无码成A在线观看| 亚洲另类无码一区二区三区| 亚洲av区一区二区三| 亚洲欧洲∨国产一区二区三区| 亚洲一区二区三区日本久久九|