<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] ## 規范 ### sync.Mutex 無需設置指針 Bad ``` mu := new(sync.Mutex) mu.Lock() ``` Good ``` var mu sync.Mutex mu.Lock() ``` ### 在邊界處拷貝 Slices 和 Maps,禁止外部修改引用 #### 接收 Slices 和 Maps 當 map 或 slice 作為函數參數傳入時,如果您存儲了對它們的引用,則用戶可以對其進行修改 Bad ``` func (d *Driver) SetTrips(trips []Trip) { d.trips = trips } trips := ... d1.SetTrips(trips) // 你是要修改 d1.trips 嗎? trips[0] = ... ``` Good ``` func (d *Driver) SetTrips(trips []Trip) { d.trips = make([]Trip, len(trips)) copy(d.trips, trips) } trips := ... d1.SetTrips(trips) // 這里我們修改 trips[0],但不會影響到 d1.trips trips[0] = ... ``` #### 返回 slices 或 maps 同樣,請注意用戶對暴露內部狀態的 map 或 slice 的修改。 Bad ``` type Stats struct { mu sync.Mutex counters map[string]int } // Snapshot 返回當前狀態。 func (s *Stats) Snapshot() map[string]int { s.mu.Lock() defer s.mu.Unlock() return s.counters } // snapshot 不再受互斥鎖保護 // 因此對 snapshot 的任何訪問都將受到數據競爭的影響 // 影響 stats.counters snapshot := stats.Snapshot() ``` Good ``` type Stats struct { mu sync.Mutex counters map[string]int } func (s *Stats) Snapshot() map[string]int { s.mu.Lock() defer s.mu.Unlock() result := make(map[string]int, len(s.counters)) for k, v := range s.counters { result[k] = v } return result } // snapshot 現在是一個拷貝 snapshot := stats.Snapshot() ``` ### Channel 的 size 要么是 1,要么是無緩沖的 channel 通常 size 應為 1 或是無緩沖的。默認情況下,channel 是無緩沖的,其 size 為零。任何其他尺寸都必須經過嚴格的審查。考慮如何確定大小,是什么阻止了 channel 在負載下被填滿并阻止寫入,以及發生這種情況時發生了什么。 ### 枚舉從 1 開始 Bad ``` type Operation int const ( Add Operation = iota Subtract Multiply ) // Add=0, Subtract=1, Multiply=2 ``` Good ``` type Operation int const ( Add Operation = iota + 1 Subtract Multiply ) // Add=1, Subtract=2, Multiply=3 ``` 在某些情況下,使用零值是有意義的(枚舉從零開始),例如,當零值是理想的默認行為時。 ``` type LogOutput int const ( LogToStdout LogOutput = iota LogToFile LogToRemote ) // LogToStdout=0, LogToFile=1, LogToRemote=2 ``` ### 錯誤類型 客戶端需要檢測錯誤,并且您已使用創建了一個簡單的錯誤 errors.New,請使用一個錯誤變量 Bad ``` // package foo func Open() error { return errors.New("could not open") } // package bar func use() { if err := foo.Open(); err != nil { if err.Error() == "could not open" { // handle } else { panic("unknown error") } } } ``` Good ``` // package foo var ErrCouldNotOpen = errors.New("could not open") func Open() error { return ErrCouldNotOpen } // package bar if err := foo.Open(); err != nil { if err == foo.ErrCouldNotOpen { // handle } else { panic("unknown error") } } ``` ### 處理類型斷言失敗 Bad ``` t := i.(string) ``` Good ``` t, ok := i.(string) if !ok { // 優雅地處理錯誤 } ``` ### 對于未導出的頂層常量和變量,使用_作為前綴 Bad ``` // foo.go const ( defaultPort = 8080 defaultUser = "user" ) // bar.go func Bar() { defaultPort := 9090 ... fmt.Println("Default port", defaultPort) // We will not see a compile error if the first line of // Bar() is deleted. } ``` Good ``` // foo.go const ( _defaultPort = 8080 _defaultUser = "user" ) ``` ### 結構體中的嵌入 Bad ``` type Client struct { version int http.Client } ``` Good ``` type Client struct { http.Client version int } ``` ### 本地變量聲明 Bad ``` var s = "foo" ``` Good ``` s := "foo" ``` 在某些情況下,var 使用關鍵字時默認值會更清晰。例如,聲明空切片 Bad ``` func f(list []int) { filtered := []int{} for _, v := range list { if v > 10 { filtered = append(filtered, v) } } } ``` Good ``` func f(list []int) { var filtered []int for _, v := range list { if v > 10 { filtered = append(filtered, v) } } } ``` ### nil 是一個有效的 slice nil 是一個有效的長度為 0 的 slice 您不應明確返回長度為零的切片。應該返回nil 來代替 Bad ``` if x == "" { return []int{} } ``` Good ``` if x == "" { return nil } ``` 要檢查切片是否為空,請始終使用len(s) == 0。而非 nil Bad ``` func isEmpty(s []string) bool { return s == nil } ``` Good ``` func isEmpty(s []string) bool { return len(s) == 0 } ``` 零值切片(用var聲明的切片)可立即使用,無需調用make()創建 Bad ``` nums := []int{} // or, nums := make([]int) if add1 { nums = append(nums, 1) } if add2 { nums = append(nums, 2) } ``` Good ``` var nums []int if add1 { nums = append(nums, 1) } if add2 { nums = append(nums, 2) } ``` ### 小變量作用域 如果有可能,盡量縮小變量作用范圍。除非它與 減少嵌套的規則沖突。 Bad ``` err := ioutil.WriteFile(name, data, 0644) if err != nil { return err } ``` Good ``` if err := ioutil.WriteFile(name, data, 0644); err != nil { return err } ``` ### 使用原始字符串字面值,避免轉義 Bad ``` wantError := "unknown name:\"test\"" ``` Good ``` wantError := `unknown error:"test"` ``` ### 初始化 Struct 引用 在初始化結構引用時,請使用&T{}代替new(T),以使其與結構體初始化一致。 Bad ``` sval := T{Name: "foo"} // inconsistent sptr := new(T) sptr.Name = "bar" ``` Good ``` sval := T{Name: "foo"} sptr := &T{Name: "bar"} ``` ### 使用 fmt.Errorf 代替 errors.New()
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看