AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

十個令人驚嘆的Go語言技巧,讓你的代碼更加優雅

來源: 責編: 時間:2023-11-18 09:36:07 321觀看
導讀在開發生產項目的過程中,我注意到經常會發現自己在重復編寫代碼,使用某些技巧時沒有意識到,直到后來回顧工作時才意識到。為了解決這個問題,我開發了一種解決方案,對我來說非常有幫助,我覺得對其他人也可能有用。以下是一些

在開發生產項目的過程中,我注意到經常會發現自己在重復編寫代碼,使用某些技巧時沒有意識到,直到后來回顧工作時才意識到。qbI28資訊網——每日最新資訊28at.com

為了解決這個問題,我開發了一種解決方案,對我來說非常有幫助,我覺得對其他人也可能有用。qbI28資訊網——每日最新資訊28at.com

以下是一些從我的實用程序庫中隨機挑選的有用且多功能的代碼片段,沒有特定的分類或特定于系統的技巧。qbI28資訊網——每日最新資訊28at.com

1. 追蹤執行時間的技巧

如果你想追蹤 Go 中函數的執行時間,有一個簡單高效的技巧可以用一行代碼實現,使用 defer 關鍵字即可。你只需要一個 TrackTime 函數:qbI28資訊網——每日最新資訊28at.com

// Utilityfunc TrackTime(pre time.Time) time.Duration {  elapsed := time.Since(pre)  fmt.Println("elapsed:", elapsed)  return elapsed}func TestTrackTime(t *testing.T) {  defer TrackTime(time.Now()) // <--- THIS  time.Sleep(500 * time.Millisecond)}// 輸出:// elapsed: 501.11125ms

1.5. 兩階段延遲執行

Go 的 defer 不僅僅是用于清理任務,還可以用于準備任務,考慮以下示例:qbI28資訊網——每日最新資訊28at.com

func setupTeardown() func() {    fmt.Println("Run initialization")    return func() {        fmt.Println("Run cleanup")    }}func main() {    defer setupTeardown()() // <--------    fmt.Println("Main function called")}// 輸出:// Run initialization// Main function called// Run cleanup

這種模式的美妙之處在于,只需一行代碼,你就可以完成諸如以下任務:qbI28資訊網——每日最新資訊28at.com

  • 打開數據庫連接,然后關閉它。
  • 設置模擬環境,然后拆除它。
  • 獲取分布式鎖,然后釋放它。
  • ...

"嗯,這似乎很聰明,但它在現實中有什么用處呢?"qbI28資訊網——每日最新資訊28at.com

還記得追蹤執行時間的技巧嗎?我們也可以這樣做:qbI28資訊網——每日最新資訊28at.com

func TrackTime() func() {  pre := time.Now()  return func() {    elapsed := time.Since(pre)    fmt.Println("elapsed:", elapsed)  }}func main() {  defer TrackTime()()  time.Sleep(500 * time.Millisecond)}

注意!如果我連接到數據庫時出現錯誤怎么辦?qbI28資訊網——每日最新資訊28at.com

確實,像 defer TrackTime() 或 defer ConnectDB() 這樣的模式不會妥善處理錯誤。這種技巧最適合用于測試或者當你愿意冒著致命錯誤的風險時使用,參考下面這種面向測試的方法:qbI28資訊網——每日最新資訊28at.com

func TestSomething(t *testing.T) {  defer handleDBConnection(t)()  // ...}func handleDBConnection(t *testing.T) func() {  conn, err := connectDB()  if err != nil {    t.Fatal(err)  }  return func() {    fmt.Println("Closing connection", conn)  }}

這樣,在測試期間可以處理數據庫連接的錯誤。qbI28資訊網——每日最新資訊28at.com

2. 預分配切片

根據文章《Go 性能提升技巧》中的見解,預分配切片或映射可以顯著提高 Go 程序的性能。qbI28資訊網——每日最新資訊28at.com

但是值得注意的是,如果我們不小心使用 append 而不是索引(如 a[i]),這種方法有時可能導致錯誤。你知道嗎,我們可以在不指定數組長度(為零)的情況下使用預分配的切片,就像在上述文章中解釋的那樣?這使我們可以像使用 append 一樣使用預分配的切片:qbI28資訊網——每日最新資訊28at.com

// 與其a := make([]int, 10)a[0] = 1// 不如這樣使用b := make([]int, 0, 10)b = append(b, 1)

3. 鏈式調用

鏈式調用技術可以應用于函數(指針)接收器。為了說明這一點,讓我們考慮一個 Person 結構,它有兩個函數 AddAge 和 Rename,用于對其進行修改。qbI28資訊網——每日最新資訊28at.com

type Person struct {  Name string  Age  int}func (p *Person) AddAge() {  p.Age++}func (p *Person) Rename(name string) {  p.Name = name}

如果你想給一個人增加年齡然后給他們改名字,常規的方法是:qbI28資訊網——每日最新資訊28at.com

func main() {  p := Person{Name: "Aiden", Age: 30}  p.AddAge()  p.Rename("Aiden 2")}

或者,我們可以修改 AddAge 和 Rename 函數接收器,使其返回修改后的對象本身,即使它們通常不返回任何內容。qbI28資訊網——每日最新資訊28at.com

func (p *Person) AddAge() *Person {  p.Age++  return p}func (p *Person) Rename(name string) *Person {  p.Name = name  return p}

通過返回修改后的對象本身,我們可以輕松地將多個函數接收器鏈在一起,而無需添加不必要的代碼行:qbI28資訊網——每日最新資訊28at.com

p = p.AddAge().Rename("Aiden 2")

4. Go 1.20 允許將切片解析為數組或數組指針

當我們需要將切片轉換為固定大小的數組時,不能直接賦值,例如:qbI28資訊網——每日最新資訊28at.com

a := []int{0, 1, 2, 3, 4, 5}var b [3]int = a[0:3]// 在變量聲明中不能將 a[0:3](類型為 []int 的值)賦值給 [3]int 類型的變量// (不兼容的賦值)

為了將切片轉換為數組,Go 團隊在 Go 1.17 中更新了這個特性。隨著 Go 1.20 的發布,借助更方便的字面量,轉換過程變得更加簡單:qbI28資訊網——每日最新資訊28at.com

// Go 1.20func Test(t *testing.T) {   a := []int{0, 1, 2, 3, 4, 5}   b := [3]int(a[0:3])  fmt.Println(b) // [0 1 2]}// Go 1.17func TestM2e(t *testing.T) {  a := []int{0, 1, 2, 3, 4, 5}  b := *(*[3]int)(a[0:3])  fmt.Println(b) // [0 1 2]}

只是一個快速提醒:你可以使用 a[:3] 替代 a[0:3]。我提到這一點是為了更清晰地說明。qbI28資訊網——每日最新資訊28at.com

5. 使用 "import _" 進行包初始化

有時,在庫中,你可能會遇到結合下劃線 (_) 的導入語句,如下所示:qbI28資訊網——每日最新資訊28at.com

import (  _ "google.golang.org/genproto/googleapis/api/annotations")

這將執行包的初始化代碼(init 函數),而無需為其創建名稱引用。這允許你在運行代碼之前初始化包、注冊連接和執行其他任務。qbI28資訊網——每日最新資訊28at.com

讓我們通過一個示例來更好地理解它的工作原理:qbI28資訊網——每日最新資訊28at.com

// 下劃線package underscorefunc init() {  fmt.Println("init called from underscore package")}// mainpackage mainimport (  _ "lab/underscore")func main() {}// 輸出:init called from underscore package

6. 使用 "import ." 進行導入

在了解了如何使用下劃線進行導入后,讓我們看看如何更常見地使用點 (.) 運算符。qbI28資訊網——每日最新資訊28at.com

作為開發者,點 (.) 運算符可用于在不必指定包名的情況下使用導入包的導出標識符,這對于懶惰的開發者來說是一個有用的快捷方式。qbI28資訊網——每日最新資訊28at.com

很酷,對吧?這在處理項目中的長包名時特別有用,比如 externalmodel 或 doingsomethinglonglib。qbI28資訊網——每日最新資訊28at.com

為了演示,這里有一個簡單的例子:qbI28資訊網——每日最新資訊28at.com

package mainimport (  "fmt"  . "math")func main() {  fmt.Println(Pi) // 3.141592653589793  fmt.Println(Sin(Pi / 2)) // 1}

7. Go 1.20 允許將多個錯誤合并為單個錯誤

Go 1.20 引入了對錯誤包的新功能,包括對多個錯誤的支持以及對 errors.Is 和 errors.As 的更改。qbI28資訊網——每日最新資訊28at.com

在 errors 中添加的一個新函數是 Join,我們將在下面詳細討論它:qbI28資訊網——每日最新資訊28at.com

var (  err1 = errors.New("Error 1st")  err2 = errors.New("Error 2nd"))func main() {  err := err1  err = errors.Join(err, err2)  fmt.Println(errors.Is(err, err1)) // true  fmt.Println(errors.Is(err, err2)) // true}

如果有多個任務導致錯誤,你可以使用 Join 函數而不是手動管理數組。這簡化了錯誤處理過程。qbI28資訊網——每日最新資訊28at.com

8. 檢查接口是否為真正的 nil

即使接口持有的值為 nil,也不意味著接口本身為 nil。這可能導致 Go 程序中的意外錯誤。因此,重要的是要知道如何檢查接口是否為真正的 nil。qbI28資訊網——每日最新資訊28at.com

func main() {  var x interface{}  var y *int = nil  x = y  if x != nil {    fmt.Println("x != nil") // <-- 實際輸出  } else {    fmt.Println("x == nil")  }  fmt.Println(x)}// 輸出:// x != nil// <nil>

我們如何確定 interface{} 值是否為 nil 呢?幸運的是,有一個簡單的工具可以幫助我們實現這一點:qbI28資訊網——每日最新資訊28at.com

func IsNil(x interface{}) bool {  if x == nil {    return true  }  return reflect.ValueOf(x).IsNil()}

9. 在 JSON 中解析 time.Duration

當解析 JSON 時,使用 time.Duration 可能是一個繁瑣的過程,因為它需要在一秒的后面添加 9 個零(即 1000000000)。為了簡化這個過程,我創建了一個名為 Duration 的新類型:qbI28資訊網——每日最新資訊28at.com

type Duration time.Duration

為了將字符串(如 "1s" 或 "20h5m")解析為 int64 類型的持續時間,我還為這個新類型實現了自定義的解析邏輯:qbI28資訊網——每日最新資訊28at.com

func (d *Duration) UnmarshalJSON(b []byte) error {  var s string  if err := json.Unmarshal(b, &s); err != nil {    return err  }  dur, err := time.ParseDuration(s)  if err != nil {    return err  }  *d = Duration(dur)  return nil}

但是,需要注意的是,變量 'd' 不應為 nil,否則可能會導致編組錯誤。或者,你還可以在函數開頭對 'd' 進行檢查。qbI28資訊網——每日最新資訊28at.com

10. 避免裸參數

當處理具有多個參數的函數時,僅通過閱讀其用法來理解每個參數的含義可能會令人困惑。考慮以下示例:qbI28資訊網——每日最新資訊28at.com

printInfo("foo", true, true)

如果不檢查 printInfo 函數,那么第一個 'true' 和第二個 'true' 的含義是什么呢?當你有一個具有多個參數的函數時,僅通過閱讀其用法來理解參數的含義可能會令人困惑。qbI28資訊網——每日最新資訊28at.com

但是,我們可以使用注釋使代碼更易讀。例如:qbI28資訊網——每日最新資訊28at.com

// func printInfo(name string, isLocal, done bool)printInfo("foo", true /* isLocal */, true /* done */)

有些 IDE 也支持這個功能,可以在函數調用建議中顯示注釋,但可能需要在設置中啟用。qbI28資訊網——每日最新資訊28at.com

以上是我分享的一些實用技巧,但我不想讓文章過長,難以跟進,因為這些技巧與特定主題無關,涵蓋了各種類別。qbI28資訊網——每日最新資訊28at.com

如果你覺得這些技巧有用,或有自己的見解要分享,請隨時留言。我重視你的反饋,并樂于在回應此文章時點贊或推薦你的想法。qbI28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-28347-0.html十個令人驚嘆的Go語言技巧,讓你的代碼更加優雅

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 突發!OpenAI的CEO被開了...

下一篇: 微信支付V3版本集成詳解【避坑指南】

標簽:
  • 熱門焦點
  • 6月安卓手機性能榜:vivo/iQOO霸占旗艦排行榜前三

    2023年上半年已經正式過去了,我們也迎來了安兔兔V10版本,在新的驍龍8Gen3和天璣9300發布之前,性能榜的榜單大體會以驍龍8Gen2和天璣9200+為主,至于那顆3.36GHz的驍龍8Gen2領先
  • Python異步IO編程的進程/線程通信實現

    這篇文章再講3種方式,同時講4中進程間通信的方式一、 Python 中線程間通信的實現方式共享變量共享變量是多個線程可以共同訪問的變量。在Python中,可以使用threading模塊中的L
  • JVM優化:實戰OutOfMemoryError異常

    一、Java堆溢出堆內存中主要存放對象、數組等,只要不斷地創建這些對象,并且保證 GC Roots 到對象之間有可達路徑來避免垃 圾收集回收機制清除這些對象,當這些對象所占空間超過
  • 本地生活這塊肥肉,拼多多也想吃一口

    出品/壹覽商業 作者/李彥編輯/木魚拼多多也看上本地生活這塊蛋糕了。近期,拼多多在App首頁&ldquo;充值中心&rdquo;入口上線了本機生活界面。壹覽商業發現,該界面目前主要
  • “又被陳思誠騙了”

    作者|張思齊 出品|眾面(ID:ZhongMian_ZM)如今的國產懸疑電影,成了陳思誠的天下。最近大爆電影《消失的她》票房突破30億斷層奪魁暑期檔,陳思誠再度風頭無兩。你可以說陳思誠的
  • 阿里大調整

    來源:產品劉有媒體報道稱,近期淘寶天貓集團啟動了近年來最大的人力制度改革,涉及員工績效、層級體系等多個核心事項,目前已形成一個初步的&ldquo;征求意見版&rdquo;:1、取消P序列
  • 信通院:小米、華為等11家應用商店基本完成APP簽名及驗簽工作

    中國信通院表示,目前,小米、華為、OPPO、vivo、360手機助手、百度手機助手、應用寶、豌豆莢和努比亞等9家應用商店,以及抖音和快手2家新型應用分發平
  • 華為Mate 60保護殼曝光:碩大后置相機模組 凸起程度有驚喜

    這段時間以來,關于華為新旗艦的爆料日漸密集。據此前多方爆料,今年華為將開始恢復一年雙旗艦戰略,除上半年推出的P60系列外,往年下半年的Mate系列也將
  • 支持aptX Lossless無損傳輸 iQOO TWS 1賽道版發布限時優惠價369元

    2023年7月4日,“無損音質,聲動人心”iQOO TWS 1正式發布,支持aptX Lossless無損傳輸,限時優惠價369元。iQOO TWS 1耳機率先支持端到端aptX Lossless無
Top