github.com/ethersphere/bee/v2@v2.2.0/CODINGSTYLE.md (about)

     1  # Go Style Guide
     2  
     3  - [Go Style Guide](#go-style-guide)
     4    - [Consistent Spelling and Naming](#consistent-spelling-and-naming)
     5    - [Code Formatting](#code-formatting)
     6    - [Unused Names](#unused-names)
     7    - [Naked returns and Named Parameters](#naked-returns-and-named-parameters)
     8    - [Testing](#testing)
     9      - [Parallel Test Execution](#parallel-test-execution)
    10      - [Naming Tests](#naming-tests)
    11    - [Group Declarations by Meaning](#group-declarations-by-meaning)
    12    - [Make Zero-value Useful](#make-zero-value-useful)
    13    - [Beware of Copying Mutexes in Go](#beware-of-copying-mutexes-in-go)
    14    - [Copy Slices and Maps at Boundaries](#copy-slices-and-maps-at-boundaries)
    15      - [Receiving Slices and Maps](#receiving-slices-and-maps)
    16      - [Returning Slices and Maps](#returning-slices-and-maps)
    17      - [Filtering in place](#filtering-in-place)
    18    - [Pointers to Interfaces](#pointers-to-interfaces)
    19      - [Verify Interface Compliance](#verify-interface-compliance)
    20    - [Receivers and Interfaces](#receivers-and-interfaces)
    21    - [Defer to Clean Up](#defer-to-clean-up)
    22    - [Channel Size is One or None](#channel-size-is-one-or-none)
    23    - [Start Enums at One](#start-enums-at-one)
    24    - [Use `"time"` to handle time](#use-time-to-handle-time)
    25      - [Use `time.Time` for instants of time](#use-timetime-for-instants-of-time)
    26      - [Use `time.Duration` for periods of time](#use-timeduration-for-periods-of-time)
    27      - [Use `time.Time` and `time.Duration` with external systems](#use-timetime-and-timeduration-with-external-systems)
    28    - [Error Types](#error-types)
    29      - [Error Wrapping](#error-wrapping)
    30      - [Handle Type Assertion Failures](#handle-type-assertion-failures)
    31      - [Panic with care](#panic-with-care)
    32    - [Avoid Mutable Globals](#avoid-mutable-globals)
    33    - [Avoid Embedding Types in Public Structs](#avoid-embedding-types-in-public-structs)
    34    - [Avoid Using Built-In Names](#avoid-using-built-in-names)
    35    - [Avoid `init()`](#avoid-init)
    36    - [Exit in Main](#exit-in-main)
    37      - [Exit Once](#exit-once)
    38    - [Performance](#performance)
    39      - [Prefer strconv over fmt](#prefer-strconv-over-fmt)
    40      - [Avoid string-to-byte conversion](#avoid-string-to-byte-conversion)
    41      - [Prefer Specifying Container Capacity](#prefer-specifying-container-capacity)
    42      - [Specifying Map Capacity Hints](#specifying-map-capacity-hints)
    43      - [Specifying Slice Capacity](#specifying-slice-capacity)
    44  
    45  ## Consistent Spelling and Naming
    46  
    47  Naming is difficult, but prefer the consistency of naming throughout the code base.
    48  If a naming pattern is already established in the codebase, follow it. If you are unsure, look in the Golang standard library for inspiration.
    49  It's similar to the `gofmt` tool, the formatting isn't to everyone's liking, but it is consistent.
    50  
    51  Prefer american spellings over British spellings, avoid Latin abbreviations.
    52  
    53  *Note:* `misspell` linter should take care of these, but it's good to keep in mind.
    54  
    55  <table>
    56  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
    57  <tbody>
    58  <tr><td>
    59  
    60  ```go
    61  // marshalling
    62  // unmarshalling
    63  // cancelling
    64  // cancelled
    65  // cancellation
    66  ```
    67  
    68  </td><td>
    69  
    70  ```go
    71  // marshaling
    72  // unmarshaling
    73  // canceling
    74  // canceled
    75  // cancellation
    76  ```
    77  
    78  </td></tr>
    79  </tbody></table>
    80  
    81  ## Code Formatting
    82  
    83  - Keep line length, argument count and function size reasonable.
    84  - Run `make lint-style` command to lint the codebase using a set of style linters.
    85  - Run `make format FOLDER=pkg/mypackage` to format the code using `gci` and `gfumpt` formatters.
    86  
    87  ## Unused Names
    88  
    89  Avoid unused method receiver names.
    90  
    91  <table>
    92  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
    93  <tbody>
    94  <tr><td>
    95  
    96  ```go
    97  func (f foo) method() {
    98  	// no references to f
    99  }
   100  
   101  func method(_ string) {
   102  	...
   103  }
   104  ```
   105  
   106  </td><td>
   107  
   108  ```go
   109  func (foo) method() {
   110  	...
   111  }
   112  
   113  func method(string) {
   114  	...
   115  }
   116  ```
   117  
   118  </td></tr>
   119  </tbody></table>
   120  
   121  Note: there might be a linter to take care of this
   122  
   123  ## Naked returns and Named Parameters
   124  
   125  Don't name result parameters just to avoid declaring a var inside the function; that trades off a minor implementation brevity at the cost of unnecessary API verbosity.
   126  
   127  Naked returns are okay if the function is a handful of lines. Once it's a medium sized function, be explicit with your return values.
   128  
   129  ```go
   130  func collect(birds ...byte) (ducks []byte) {
   131    for _, bird := range birds {
   132      if isDuck(bird) {
   133        ducks = append(ducks, bird)
   134      }
   135    }
   136  
   137    return
   138  }
   139  ```
   140  
   141  *Corollary:* it's not worth it to name result parameters just because it enables you to use naked returns. Clarity of docs is always more important than saving a line or two in your function.
   142  
   143  Finally, in some cases you need to name a result parameter in order to change it in a deferred closure. That is always OK.
   144  
   145  ```go
   146  func getID() (id int, err error) {
   147     defer func() {
   148        if err != nil {
   149           err = fmt.Errorf("some extra info: %v", err)
   150        }
   151     }
   152  
   153     id, err = /* call to db */
   154  
   155     return
   156  }
   157  ```
   158  ## Testing
   159  
   160  Use the Golang [testing package](https://pkg.go.dev/testing) from the standard library for writing tests.
   161  
   162  ### Parallel Test Execution
   163  
   164  Run tests in parallel where possible but don't forget about variable scope gotchas.
   165  
   166  ```go
   167  for tc := range tt {
   168    tc := tc // must not forget this
   169    t.Run(tc.name, func(t *testing.T) {
   170      t.Parallel()
   171      //execute
   172      // ...
   173      // assert
   174      if got != tt.want {
   175        // useful for human comparable values
   176        t.Errorf("wrong output\ngot:  %q\nwant: %q", got, want)
   177        // alternatively
   178        t.Errorf("Foo(%q) = %d; want %d", tt.in, got, tt.want)
   179      }
   180    })
   181  }
   182  ```
   183  
   184  ### Naming Tests
   185  
   186  Name tests with a compact name that reflects their scenario. Don't try to specify the scenario in the test name, that is not what it's for. Use the accompanying godoc to describe the test scenario.
   187  
   188  <table>
   189  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   190  <tbody>
   191  <tr><td>
   192  
   193  ```go
   194  func TestSomethingBySettingVarToFive(t *testing.T) {
   195    ...
   196  }
   197  ```
   198  
   199  </td><td>
   200  
   201  ```go
   202  // TestSomething tests that something works correctly by doing this and that.
   203  func TestSomething(t *testing.T) {
   204    ...
   205  }
   206  ```
   207  
   208  </td>
   209  </td></tr>
   210  </tbody></table>
   211  
   212  If needed, use an underscore to disambiguate tests that are hard to name:
   213  ```go
   214  func TestScenario_EdgeCase(t *testing.T) {
   215    ...
   216  }
   217  
   218  func TestScenario_CornerCase(t *testing.T) {
   219    ...
   220  }
   221  ```
   222  
   223  Ideally, try to use nested tests that would cause the test runner to automatically assemble the different test cases in separate entries:
   224  
   225  ```go
   226  func TestSomething(t *testing.T) {
   227    ...
   228    t.Run("edge case", func(t *testing.T) { ... })
   229  }
   230  ```
   231  
   232  Avoid using the word "fail" when naming tests. Since the go test runner uses the same keyword to denote failed tests, this just prolongs the search for relevant information when inspecting build artifacts.
   233  
   234  ## Group Declarations by Meaning
   235  
   236  Where possible, group declarations by their purpose.
   237  
   238  <table>
   239  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   240  <tbody>
   241  <tr><td>
   242  
   243  ```go
   244  const (
   245  	limitDays   = 90
   246  	warningDays = 0.9 * limitDays
   247  	sleepFor    = 30 * time.Minute
   248  )
   249  
   250  
   251  var (
   252    _                 Interface = (*Accounting)(nil)
   253    balancesPrefix    = "accounting_balance_"
   254    someOtherPrefix   = "some_other_balance_"
   255    ErrLimitExceeded  = errors.New("limit exceeded")
   256  )
   257  ```
   258  
   259  </td><td>
   260  
   261  ```go
   262  const (
   263    limitDays   = 90
   264    warningDays = 0.9 * limitDays
   265  )
   266  
   267  const sleepFor = 30 * time.Minute
   268  
   269  var _ Interface = (*Accounting)(nil)
   270  
   271  var ( // or const
   272    balancesPrefix  = "accounting_balance_"
   273    someOtherPrefix = "some_other_balance_"
   274  )
   275  
   276  var ErrLimitExceeded = errors.New("limit exceeded")
   277  ```
   278  
   279  </td></tr>
   280  </tbody></table>
   281  
   282  ## Make Zero-value Useful
   283  
   284  - The zero-value of `sync.Mutex` and `sync.RWMutex` is valid, so you almost never need a pointer to a mutex.
   285  
   286    <table>
   287    <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   288    <tbody>
   289    <tr><td>
   290  
   291    ```go
   292    mu := new(sync.Mutex)
   293    mu.Lock()
   294    ```
   295  
   296    </td><td>
   297  
   298    ```go
   299    var mu sync.Mutex
   300    mu.Lock()
   301    ```
   302  
   303    </td></tr>
   304    </tbody></table>
   305  
   306  - For the same reason, a struct field of `sync.Mutex` does not require explicit initialization.
   307  
   308    <table>
   309    <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   310    <tbody>
   311    <tr><td>
   312  
   313    ```go
   314    type Store struct {
   315      mu sync.Mutex
   316    }
   317  
   318    s := Store{
   319      mu: sync.Mutex{},
   320    }
   321  
   322    // use s
   323    ```
   324  
   325    </td><td>
   326  
   327    ```go
   328    type Store struct {
   329      mu sync.Mutext
   330    }
   331  
   332    var s Store
   333  
   334  
   335  
   336    // use s
   337    ```
   338  
   339    </td></tr>
   340    </tbody></table>
   341  
   342  - The zero value (a slice declared with `var`) is usable immediately without `make()`.
   343  
   344    <table>
   345    <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   346    <tbody>
   347    <tr><td>
   348  
   349    ```go
   350    nums := []int{}
   351    // or, nums := make([]int)
   352  
   353    if add1 {
   354      nums = append(nums, 1)
   355    }
   356  
   357    if add2 {
   358      nums = append(nums, 2)
   359    }
   360    ```
   361  
   362    </td><td>
   363  
   364    ```go
   365    var nums []int
   366  
   367    if add1 {
   368      nums = append(nums, 1)
   369    }
   370  
   371    if add2 {
   372      nums = append(nums, 2)
   373    }
   374  
   375    ```
   376  
   377    </td></tr>
   378    </tbody></table>
   379  
   380  `nil` is a valid slice of length 0. This means that,
   381  
   382  - You should not return a slice of length zero explicitly. Return `nil` instead.
   383  
   384    <table>
   385    <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   386    <tbody>
   387    <tr><td>
   388  
   389    ```go
   390    if x == "" {
   391      return []int{}
   392    }
   393    ```
   394  
   395    </td><td>
   396  
   397    ```go
   398    if x == "" {
   399      return nil
   400    }
   401    ```
   402  
   403    </td></tr>
   404    </tbody></table>
   405  *Note:* in the case of serialization it might make sense to use a zero length initialized slice. For instance the JSON representation of a _nil_ slice is `null`, however a zero length allocated slice would be translated to `[]`.
   406  
   407  - To check if a slice is empty, always use `len(s) == 0`. Do not check for `nil`.
   408  
   409    <table>
   410    <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   411    <tbody>
   412    <tr><td>
   413  
   414    ```go
   415    func isEmpty(s []string) bool {
   416      return s == nil
   417    }
   418    ```
   419  
   420    </td><td>
   421  
   422    ```go
   423    func isEmpty(s []string) bool {
   424      return len(s) == 0
   425    }
   426    ```
   427  
   428    </td></tr>
   429    </tbody></table>
   430  
   431  Remember that, while it is a valid slice, a `nil` slice is not equivalent to an allocated slice of length `0` - one is `nil` and the other is not - and the two may be treated differently in different situations (such as serialization and comparison).
   432  
   433  ## Beware of Copying Mutexes in Go
   434  
   435  The `sync.Mutex` is a value type so copying it is wrong. We're just creating a different mutex, so obviously the exclusion no longer works.
   436  
   437  <table>
   438  <thead><tr><th>Bad</th> <th>Good</th></tr></thead>
   439  <tbody>
   440  <tr>
   441  <td>
   442  
   443  ```go
   444  type Container struct {
   445    mu sync.Mutex
   446    counters map[string]int
   447  }
   448  
   449  func (c Container) inc(name string) { // the value receiver will make a copy of the mutex
   450    c.mu.Lock()
   451    defer c.mu.Unlock()
   452    c.counters[name]++
   453  }
   454  ```
   455  
   456  </td>
   457  <td>
   458  
   459  ```go
   460  type Container struct {
   461    my.sync.Mutex
   462    counters map[string]int
   463  }
   464  
   465  func (c *Container) inc(name string) {
   466    c.mu.Lock()
   467    defer c.mu.Unlock()
   468    c.counters[name]++
   469  }
   470  ```
   471  
   472  </td>
   473  </tr>
   474  
   475  </tbody>
   476  </table>
   477  
   478  ## Copy Slices and Maps at Boundaries
   479  
   480  Slices and maps contain pointers to the underlying data so be wary of scenarios when they need to be copied.
   481  
   482  ### Receiving Slices and Maps
   483  
   484  Keep in mind that users can modify a map or slice you received as an argument if you store a reference to it.
   485  
   486  <table>
   487  <thead><tr><th>Bad</th> <th>Good</th></tr></thead>
   488  <tbody>
   489  <tr>
   490  <td>
   491  
   492  ```go
   493  func (d *Driver) SetTrips(trips []Trip) {
   494    d.trips = trips
   495  }
   496  
   497  trips := ...
   498  d1.SetTrips(trips)
   499  
   500  // Did you mean to modify d1.trips?
   501  trips[0] = ...
   502  ```
   503  
   504  </td>
   505  <td>
   506  
   507  ```go
   508  func (d *Driver) SetTrips(trips []Trip) {
   509    d.trips = make([]Trip, len(trips))
   510    copy(d.trips, trips)
   511  }
   512  
   513  trips := ...
   514  d1.SetTrips(trips)
   515  
   516  // We can now modify trips[0] without affecting d1.trips.
   517  trips[0] = ...
   518  ```
   519  
   520  </td>
   521  </tr>
   522  
   523  </tbody>
   524  </table>
   525  
   526  ### Returning Slices and Maps
   527  
   528  Similarly, be wary of user modifications to maps or slices exposing internal state.
   529  
   530  <table>
   531  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   532  <tbody>
   533  <tr><td>
   534  
   535  ```go
   536  type Stats struct {
   537    mu sync.Mutex
   538    counters map[string]int
   539  }
   540  
   541  // Snapshot returns the current stats.
   542  func (s *Stats) Snapshot() map[string]int {
   543    s.mu.Lock()
   544    defer s.mu.Unlock()
   545  
   546    return s.counters
   547  }
   548  
   549  
   550  
   551  // snapshot is no longer protected by the mutex, so any
   552  // access to the snapshot is subject to data races.
   553  snapshot := stats.Snapshot()
   554  ```
   555  
   556  </td><td>
   557  
   558  ```go
   559  type Stats struct {
   560    mu sync.Mutex
   561    counters map[string]int
   562  }
   563  
   564  func (s *Stats) Snapshot() map[string]int {
   565    s.mu.Lock()
   566    defer s.mu.Unlock()
   567  
   568    result := make(map[string]int, len(s.counters))
   569    for k, v := range s.counters {
   570      result[k] = v
   571    }
   572    return result
   573  }
   574  
   575  // Snapshot is now a copy.
   576  snapshot := stats.Snapshot()
   577  ```
   578  
   579  </td></tr>
   580  </tbody></table>
   581  
   582  ### Filtering in place
   583  
   584  This trick uses the fact that a slice shares the same backing array and capacity as the original, so the storage is reused for the filtered slice. Of course, the original contents are modified, so be mindful. It is useful for the code in the 'hot path' where we want to minimize allocation.
   585  
   586  <table>
   587  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   588  <tbody>
   589  <tr><td>
   590  
   591  ```go
   592  var b []rune
   593  for _, x := range a {
   594    if f(x) {
   595      b = append(b, x) // will cause new allocations
   596    }
   597  }
   598  
   599  
   600  
   601  
   602  
   603  
   604  
   605  
   606  
   607  
   608  ```
   609  
   610  </td><td>
   611  
   612  ```go
   613  b := a[:0]
   614  for _, x := range a {
   615    if f(x) {
   616      b = append(b, x)  // will reuse the backing array
   617    }
   618  }
   619  
   620  // alternatively using index, a bit more verbose
   621  n := 0
   622  for _, x := range a {
   623    if f(x) {
   624      a[n] = x
   625      n++
   626    }
   627  }
   628  a = a[:n]
   629  ```
   630  
   631  </td></tr>
   632  </tbody></table>
   633  
   634  ## Pointers to Interfaces
   635  
   636  You almost never need a pointer to an interface. You should be passing interfaces as values—the underlying data can still be a pointer.
   637  
   638  ### Verify Interface Compliance
   639  
   640  Verify interface compliance at compile time *where appropriate*. This includes:
   641  
   642  - Exported types that are required to implement specific interfaces as part of their API contract
   643  - Exported or unexported types that are part of a collection of types implementing the same interface
   644  - Other cases where violating an interface would break users
   645  
   646  <table>
   647  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   648  <tbody>
   649  <tr><td>
   650  
   651  ```go
   652  type Handler struct {
   653    // ...
   654  }
   655  
   656  
   657  
   658  func (h *Handler) ServeHTTP(
   659    w http.ResponseWriter,
   660    r *http.Request,
   661  ) {
   662    ...
   663  }
   664  ```
   665  
   666  </td><td>
   667  
   668  ```go
   669  type Handler struct {
   670    // ...
   671  }
   672  
   673  var _ http.Handler = (*Handler)(nil)
   674  
   675  func (h *Handler) ServeHTTP(
   676    w http.ResponseWriter,
   677    r *http.Request,
   678  ) {
   679    // ...
   680  }
   681  ```
   682  
   683  </td></tr>
   684  </tbody></table>
   685  
   686  The statement `var _ http.Handler = (*Handler)(nil)` will fail to compile if `*Handler` ever stops matching the `http.Handler` interface.
   687  
   688  The right hand side of the assignment should be the zero value of the asserted type. This is `nil` for pointer types (like `*Handler`), slices, and maps, and an empty struct for struct types.
   689  
   690  ```go
   691  type LogHandler struct {
   692    h   http.Handler
   693    log *zap.Logger
   694  }
   695  
   696  var _ http.Handler = LogHandler{}
   697  
   698  func (h LogHandler) ServeHTTP(
   699    w http.ResponseWriter,
   700    r *http.Request,
   701  ) {
   702    // ...
   703  }
   704  ```
   705  
   706  ## Receivers and Interfaces
   707  
   708  Methods with value receivers can be called on pointers as well as values.
   709  Methods with pointer receivers can only be called on pointers or [addressable values].
   710  
   711    [addressable values]: https://golang.org/ref/spec#Method_values
   712  
   713  For example,
   714  
   715  ```go
   716  type S struct {
   717    data string
   718  }
   719  
   720  func (s S) Read() string {
   721    return s.data
   722  }
   723  
   724  func (s *S) Write(str string) {
   725    s.data = str
   726  }
   727  
   728  sVals := map[int]S{1: {"A"}}
   729  
   730  // You can only call Read using a value
   731  sVals[1].Read()
   732  
   733  // This will not compile:
   734  //  sVals[1].Write("test")
   735  
   736  sPtrs := map[int]*S{1: {"A"}}
   737  
   738  // You can call both Read and Write using a pointer
   739  sPtrs[1].Read()
   740  sPtrs[1].Write("test")
   741  ```
   742  
   743  Similarly, an interface can be satisfied by a pointer, even if the method has a value receiver.
   744  
   745  ```go
   746  type F interface {
   747    f()
   748  }
   749  
   750  type S1 struct{}
   751  
   752  func (s S1) f() {}
   753  
   754  type S2 struct{}
   755  
   756  func (s *S2) f() {}
   757  
   758  s1Val := S1{}
   759  s1Ptr := &S1{}
   760  s2Val := S2{}
   761  s2Ptr := &S2{}
   762  
   763  var i F
   764  i = s1Val
   765  i = s1Ptr
   766  i = s2Ptr
   767  
   768  // The following doesn't compile, since s2Val is a value, and there is no value receiver for f.
   769  //   i = s2Val
   770  ```
   771  
   772  Effective Go has a good write up on [Pointers vs. Values].
   773  
   774    [Pointers vs. Values]: https://golang.org/doc/effective_go.html#pointers_vs_values
   775  
   776  ## Defer to Clean Up
   777  
   778  Use defer to clean up resources such as files and locks.
   779  
   780  <table>
   781  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   782  <tbody>
   783  <tr><td>
   784  
   785  ```go
   786  p.Lock()
   787  if p.count < 10 {
   788    p.Unlock()
   789    return p.count
   790  }
   791  
   792  p.count++
   793  newCount := p.count
   794  p.Unlock()
   795  
   796  return newCount
   797  
   798  // easy to miss unlocks due to multiple returns
   799  ```
   800  
   801  </td><td>
   802  
   803  ```go
   804  p.Lock()
   805  defer p.Unlock()
   806  
   807  if p.count < 10 {
   808    return p.count
   809  }
   810  
   811  p.count++
   812  return p.count
   813  
   814  
   815  
   816  // more readable
   817  ```
   818  
   819  </td></tr>
   820  </tbody></table>
   821  
   822  Defer has an extremely small overhead and should be avoided only if you can prove that your function execution time is in the order of nanoseconds. The readability win of using defers is worth the minuscule cost of using them. This is especially true for larger methods that have more than simple memory accesses, where the other computations are more significant than the `defer`.
   823  
   824  Most importantly the deferred function is going to be executed even in the case of a panic, so we avoid leaving some mutex on 'lock' and potentially leaving the system in an inconsistent state.
   825  
   826  ## Channel Size is One or None
   827  
   828  Channels should usually have a size of one or be unbuffered. By default, channels are unbuffered and have a size of zero (blocking behaviour). Any other size must be subject to a high level of scrutiny. Consider how the size is determined, what prevents the channel from filling up under load and blocking writers, and what happens when this occurs.
   829  
   830  <table>
   831  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   832  <tbody>
   833  <tr><td>
   834  
   835  ```go
   836  // Ought to be enough for anybody!
   837  c := make(chan int, 64)
   838  
   839  
   840  ```
   841  
   842  </td><td>
   843  
   844  ```go
   845  // Size of one
   846  c := make(chan int, 1) // or
   847  // Unbuffered channel, size of zero
   848  c := make(chan int)
   849  ```
   850  
   851  </td></tr>
   852  </tbody></table>
   853  
   854  *Note:* in some places we use buffered channels to implement a semaphore as described [here](https://robreid.io/stupid-channel-tricks-p2-semaphores/)
   855  
   856  ## Start Enums at One
   857  
   858  The standard way of introducing enumerations in Go is to declare a custom type and a `const` group with `iota`. Since variables have a 0 default value, you should usually start your enums on a non-zero value.
   859  
   860  <table>
   861  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   862  <tbody>
   863  <tr><td>
   864  
   865  ```go
   866  type Operation int
   867  
   868  const (
   869    Add Operation = iota
   870    Subtract
   871    Multiply
   872  )
   873  
   874  // Add=0, Subtract=1, Multiply=2
   875  ```
   876  
   877  </td><td>
   878  
   879  ```go
   880  type Operation int
   881  
   882  const (
   883    Add Operation = iota + 1
   884    Subtract
   885    Multiply
   886  )
   887  
   888  // Add=1, Subtract=2, Multiply=3
   889  ```
   890  
   891  </td></tr>
   892  </tbody></table>
   893  
   894  *Note:* There are cases where using the zero value makes sense, for example when the zero value case is the desirable default behavior.
   895  
   896  ```go
   897  type LogOutput int
   898  
   899  const (
   900    LogToStdout LogOutput = iota
   901    LogToFile
   902    LogToRemote
   903  )
   904  
   905  // LogToStdout=0, LogToFile=1, LogToRemote=2
   906  ```
   907  
   908  ## Use `"time"` to handle time
   909  
   910  Time is complicated. Incorrect assumptions often made about time include the following.
   911  
   912  1. A day has 24 hours
   913  2. An hour has 60 minutes
   914  3. A week has 7 days
   915  4. A year has 365 days
   916  5. [And a lot more](https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time)
   917  
   918  For example, *1* means that adding 24 hours to a time instant will not always yield a new calendar day.
   919  
   920  Therefore, always use the [`"time"`] package when dealing with time because it helps deal with these incorrect assumptions in a safer, more accurate manner.
   921  
   922    [`"time"`]: https://golang.org/pkg/time/
   923  
   924  ### Use `time.Time` for instants of time
   925  
   926  Use [`time.Time`] when dealing with instants of time, and the methods on `time.Time` when comparing, adding, or subtracting time.
   927  
   928    [`time.Time`]: https://golang.org/pkg/time/#Time
   929  
   930  <table>
   931  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   932  <tbody>
   933  <tr><td>
   934  
   935  ```go
   936  func isActive(now, start, stop int) bool {
   937    return start <= now && now < stop
   938  }
   939  ```
   940  
   941  </td><td>
   942  
   943  ```go
   944  func isActive(now, start, stop time.Time) bool {
   945    return (start.Before(now) || start.Equal(now)) && now.Before(stop)
   946  }
   947  ```
   948  
   949  </td></tr>
   950  </tbody></table>
   951  
   952  ### Use `time.Duration` for periods of time
   953  
   954  Use [`time.Duration`] when dealing with periods of time.
   955  
   956    [`time.Duration`]: https://golang.org/pkg/time/#Duration
   957  
   958  <table>
   959  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
   960  <tbody>
   961  <tr><td>
   962  
   963  ```go
   964  func poll(delay int) {
   965    for {
   966      // ...
   967      time.Sleep(time.Duration(delay) * time.Millisecond)
   968    }
   969  }
   970  
   971  poll(10) // was it seconds or milliseconds?
   972  ```
   973  
   974  </td><td>
   975  
   976  ```go
   977  func poll(delay time.Duration) {
   978    for {
   979      // ...
   980      time.Sleep(delay)
   981    }
   982  }
   983  
   984  poll(10*time.Second)
   985  ```
   986  
   987  </td></tr>
   988  </tbody></table>
   989  
   990  Going back to the example of adding 24 hours to a time instant, the method we use to add time depends on intent. If we want the same time of the day, but on the next calendar day, we should use [`Time.AddDate`]. However, if we want an instant of time guaranteed to be 24 hours after the previous time, we should use [`Time.Add`].
   991  
   992    [`Time.AddDate`]: https://golang.org/pkg/time/#Time.AddDate
   993    [`Time.Add`]: https://golang.org/pkg/time/#Time.Add
   994  
   995  ```go
   996  newDay := t.AddDate(0 /* years */, 0 /* months */, 1 /* days */)
   997  maybeNewDay := t.Add(24 * time.Hour)
   998  ```
   999  
  1000  ### Use `time.Time` and `time.Duration` with external systems
  1001  
  1002  Use `time.Duration` and `time.Time` in interactions with external systems when possible. For example:
  1003  
  1004  - Command-line flags: [`flag`] supports `time.Duration` via [`time.ParseDuration`]
  1005  - JSON: [`encoding/json`] supports encoding `time.Time` as an [RFC 3339] string via its [`UnmarshalJSON` method]
  1006  - SQL: [`database/sql`] supports converting `DATETIME` or `TIMESTAMP` columns into `time.Time` and back if the underlying driver supports it
  1007  - YAML: [`gopkg.in/yaml.v2`] supports `time.Time` as an [RFC 3339] string, and `time.Duration` via [`time.ParseDuration`].
  1008  
  1009    [`flag`]: https://golang.org/pkg/flag/
  1010    [`time.ParseDuration`]: https://golang.org/pkg/time/#ParseDuration
  1011    [`encoding/json`]: https://golang.org/pkg/encoding/json/
  1012    [RFC 3339]: https://tools.ietf.org/html/rfc3339
  1013    [`UnmarshalJSON` method]: https://golang.org/pkg/time/#Time.UnmarshalJSON
  1014    [`database/sql`]: https://golang.org/pkg/database/sql/
  1015    [`gopkg.in/yaml.v2`]: https://godoc.org/gopkg.in/yaml.v2
  1016  
  1017  When it is not possible to use `time.Duration` in these interactions, use `int` or `float64` and include the unit in the name of the field. For example, since `encoding/json` does not support `time.Duration`, the unit is included in the name of the field.
  1018  
  1019  <table>
  1020  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1021  <tbody>
  1022  <tr><td>
  1023  
  1024  ```go
  1025  // {"interval": 2}
  1026  type Config struct {
  1027    Interval int `json:"interval"`
  1028  }
  1029  ```
  1030  
  1031  </td><td>
  1032  
  1033  ```go
  1034  // {"intervalMillis": 2000}
  1035  type Config struct {
  1036    IntervalMillis int `json:"intervalMillis"`
  1037  }
  1038  ```
  1039  
  1040  </td></tr>
  1041  </tbody></table>
  1042  
  1043  When it is not possible to use `time.Time` in these interactions, unless an alternative is agreed upon, use `string` and format timestamps as defined in [RFC 3339]. This format is used by default by [`Time.nmarshalText`] and is available for use in `Time.Format` and `time.Parse` via [`time.RFC3339`].
  1044  
  1045    [`Time.UnmarshalText`]: https://golang.org/pkg/time/#Time.UnmarshalText
  1046    [`time.RFC3339`]: https://golang.org/pkg/time/#RFC3339
  1047  
  1048  Although this tends to not be a problem in practice, keep in mind that the `"time"` package does not support parsing timestamps with leap seconds ([8728]), nor does it account for leap seconds in calculations ([15190]). If you compare two instants of time, the difference will not include the leap seconds that may have occurred between those two instants.
  1049  
  1050    [8728]: https://github.com/golang/go/issues/8728
  1051    [15190]: https://github.com/golang/go/issues/15190
  1052  
  1053  ## Error Types
  1054  
  1055  There are various options for declaring errors:
  1056  
  1057  - [`errors.New`] for errors with simple static strings
  1058  - [`fmt.Errorf`] for formatted error strings
  1059  - Custom types that implement an `Error()` method
  1060  - Wrapped errors using [`"pkg/errors".Wrap`]
  1061  
  1062  When returning errors, consider the following to determine the best choice:
  1063  
  1064  - Is this a simple error that needs no extra information? If so, [`errors.New`] should suffice.
  1065  - Do the clients need to detect and handle this error? If so, you should use a custom type, and implement the `Error()` method.
  1066  - Are you propagating an error returned by a downstream function? If so, check the [section on error wrapping](#error-wrapping).
  1067  - Otherwise, [`fmt.Errorf`] is okay.
  1068  
  1069    [`errors.New`]: https://golang.org/pkg/errors/#New
  1070    [`fmt.Errorf`]: https://golang.org/pkg/fmt/#Errorf
  1071    [`"pkg/errors".Wrap`]: https://godoc.org/github.com/pkg/errors#Wrap
  1072  
  1073  If the client needs to detect the error, and you have created a simple error
  1074  using [`errors.New`], use a var for the error.
  1075  
  1076  <table>
  1077  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1078  <tbody>
  1079  <tr><td>
  1080  
  1081  ```go
  1082  // package foo
  1083  
  1084  func Open() error {
  1085    return errors.New("could not open")
  1086  }
  1087  
  1088  // package bar
  1089  
  1090  func use() {
  1091    if err := foo.Open(); err != nil {
  1092      if err.Error() == "could not open" {
  1093        // handle
  1094      } else {
  1095        panic("unknown error")
  1096      }
  1097    }
  1098  }
  1099  ```
  1100  
  1101  </td><td>
  1102  
  1103  ```go
  1104  // package foo
  1105  
  1106  var ErrCouldNotOpen = errors.New("could not open")
  1107  
  1108  func Open() error {
  1109    return ErrCouldNotOpen
  1110  }
  1111  
  1112  // package bar
  1113  
  1114  if err := foo.Open(); err != nil {
  1115    if errors.Is(err, foo.ErrCouldNotOpen) {
  1116      // handle
  1117    } else {
  1118      panic("unknown error")
  1119    }
  1120  }
  1121  ```
  1122  
  1123  </td></tr>
  1124  </tbody></table>
  1125  
  1126  If you have an error that clients may need to detect, and you would like to add more information to it (e.g., it is not a static string), then you should use a custom type.
  1127  
  1128  <table>
  1129  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1130  <tbody>
  1131  <tr><td>
  1132  
  1133  ```go
  1134  func open(file string) error {
  1135    return fmt.Errorf("file %q not found", file)
  1136  }
  1137  
  1138  func use() {
  1139    if err := open("testfile.txt"); err != nil {
  1140      if strings.Contains(err.Error(), "not found") {
  1141        // handle
  1142      } else {
  1143        panic("unknown error")
  1144      }
  1145    }
  1146  }
  1147  
  1148  
  1149  
  1150  
  1151  
  1152  
  1153  
  1154  
  1155  ```
  1156  
  1157  </td><td>
  1158  
  1159  ```go
  1160  type errNotFound struct {
  1161    file string
  1162  }
  1163  
  1164  func (e errNotFound) Error() string {
  1165    return fmt.Sprintf("file %q not found", e.file)
  1166  }
  1167  
  1168  func open(file string) error {
  1169    return errNotFound{file: file}
  1170  }
  1171  
  1172  func use() {
  1173    if err := open("testfile.txt"); err != nil {
  1174      if _, ok := err.(errNotFound); ok {
  1175        // handle
  1176      } else {
  1177        panic("unknown error")
  1178      }
  1179    }
  1180  }
  1181  ```
  1182  
  1183  </td></tr>
  1184  </tbody></table>
  1185  
  1186  Be careful with exporting custom error types directly since they become part of the public API of the package. It is preferable to expose matcher functions to check the error instead.
  1187  
  1188  ```go
  1189  // package foo
  1190  
  1191  type errNotFound struct {
  1192    file string
  1193  }
  1194  
  1195  func (e errNotFound) Error() string {
  1196    return fmt.Sprintf("file %q not found", e.file)
  1197  }
  1198  
  1199  func IsNotFoundError(err error) bool {
  1200    return errors.Is(err, errNotFound)
  1201  }
  1202  
  1203  func Open(file string) error {
  1204    return errNotFound{file: file}
  1205  }
  1206  
  1207  // package bar
  1208  
  1209  if err := foo.Open("foo"); err != nil {
  1210    if foo.IsNotFoundError(err) {
  1211      // handle
  1212    } else {
  1213      panic("unknown error")
  1214    }
  1215  }
  1216  ```
  1217  
  1218  ### Error Wrapping
  1219  
  1220  There are three main options for propagating errors if a call fails:
  1221  
  1222  - Return the original error if there is no additional context to add and you want to maintain the original error type.
  1223  - Use [`fmt.Errorf`] if the callers do not need to detect or handle that specific error case.
  1224  - Use a custom type where you can detail the failure reason.
  1225  
  1226  It is recommended to add context where possible so that instead of a vague error such as "connection refused", you get more useful errors such as "call service foo: connection refused". When adding context to returned errors, keep the context succinct by avoiding phrases like "failed to", which state the obvious and pile up as the error percolates up through the stack:
  1227  
  1228  <table>
  1229  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1230  <tbody>
  1231  <tr><td>
  1232  
  1233  ```go
  1234  s, err := store.New()
  1235  if err != nil {
  1236      return fmt.Errorf("failed to create new store: %v", err)
  1237  }
  1238  ```
  1239  
  1240  </td><td>
  1241  
  1242  ```go
  1243  s, err := store.New()
  1244  if err != nil {
  1245      return fmt.Errorf("new store: %v", err)
  1246  }
  1247  ```
  1248  
  1249  <tr><td>
  1250  
  1251  ```
  1252  failed to x: failed to y: failed to create new store: the error
  1253  ```
  1254  
  1255  </td><td>
  1256  
  1257  ```
  1258  x: y: new store: the error
  1259  
  1260  ```
  1261  
  1262  </td></tr>
  1263  </tbody></table>
  1264  
  1265  However once the error is sent to another system, it should be clear the message is an error (e.g. an `err` tag or "Failed" prefix in logs).
  1266  
  1267  See also [Don't just check errors, handle them gracefully].
  1268  
  1269    [`"pkg/errors".Cause`]: https://godoc.org/github.com/pkg/errors#Cause
  1270    [Don't just check errors, handle them gracefully]: https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully
  1271  
  1272  ### Handle Type Assertion Failures
  1273  
  1274  The single return value form of a [type assertion] will panic on an incorrect type. Therefore, always use the "comma ok" idiom.
  1275  
  1276    [type assertion]: https://golang.org/ref/spec#Type_assertions
  1277  
  1278  <table>
  1279  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1280  <tbody>
  1281  <tr><td>
  1282  
  1283  ```go
  1284  t := i.(string)
  1285  
  1286  
  1287  
  1288  ```
  1289  
  1290  </td><td>
  1291  
  1292  ```go
  1293  t, ok := i.(string)
  1294  if !ok {
  1295    // handle the error gracefully
  1296  }
  1297  ```
  1298  
  1299  </td></tr>
  1300  </tbody></table>
  1301  
  1302  ### Panic with care
  1303  
  1304  Code running in production must avoid panics. Panics are a major source of [cascading failures]. If an error occurs, the function must return an error and allow the caller to decide how to handle it.
  1305  
  1306    [cascading failures]: https://en.wikipedia.org/wiki/Cascading_failure
  1307  
  1308  <table>
  1309  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1310  <tbody>
  1311  <tr><td>
  1312  
  1313  ```go
  1314  func run(args []string) {
  1315    if len(args) == 0 {
  1316      panic("an argument is required")
  1317    }
  1318    // ...
  1319  }
  1320  
  1321  func main() {
  1322    run(os.Args[1:])
  1323  }
  1324  
  1325  
  1326  
  1327  
  1328  ```
  1329  
  1330  </td><td>
  1331  
  1332  ```go
  1333  func run(args []string) error {
  1334    if len(args) == 0 {
  1335      return errors.New("an argument is required")
  1336    }
  1337    // ...
  1338    return nil
  1339  }
  1340  
  1341  func main() {
  1342    if err := run(os.Args[1:]); err != nil {
  1343      fmt.Fprintln(os.Stderr, err)
  1344      os.Exit(1)
  1345    }
  1346  }
  1347  ```
  1348  
  1349  </td></tr>
  1350  </tbody></table>
  1351  
  1352  Panic/recover is not an error handling strategy. A program must panic only when something irrecoverable happens such as a nil dereference. An exception to this is program initialization: bad things at program startup that should abort the program may cause panic.
  1353  
  1354  ```go
  1355  var _statusTemplate = template.Must(template.New("name").Parse("_statusHTML"))
  1356  ```
  1357  
  1358  Even in tests, prefer `t.Fatal` or `t.FailNow` over panics to ensure that the test is marked as failed.
  1359  
  1360  <table>
  1361  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1362  <tbody>
  1363  <tr><td>
  1364  
  1365  ```go
  1366  // func TestFoo(t *testing.T)
  1367  
  1368  f, err := os.CreateTemp("", "test")
  1369  if err != nil {
  1370    panic("failed to set up test")
  1371  }
  1372  ```
  1373  
  1374  </td><td>
  1375  
  1376  ```go
  1377  // func TestFoo(t *testing.T)
  1378  
  1379  f, err := os.CreateTemp("", "test")
  1380  if err != nil {
  1381    t.Fatal("failed to set up test")
  1382  }
  1383  ```
  1384  
  1385  </td></tr>
  1386  </tbody></table>
  1387  
  1388  ## Avoid Mutable Globals
  1389  
  1390  Avoid mutating global variables, instead opting for dependency injection. This applies to function pointers as well as other kinds of values.
  1391  
  1392  <table>
  1393  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1394  <tbody>
  1395  <tr><td>
  1396  
  1397  ```go
  1398  // sign.go
  1399  
  1400  var _timeNow = time.Now
  1401  
  1402  func sign(msg string) string {
  1403    now := _timeNow()
  1404    return signWithTime(msg, now)
  1405  }
  1406  
  1407  
  1408  
  1409  
  1410  
  1411  
  1412  
  1413  
  1414  ```
  1415  
  1416  </td><td>
  1417  
  1418  ```go
  1419  // sign.go
  1420  
  1421  type signer struct {
  1422    now func() time.Time
  1423  }
  1424  
  1425  func newSigner() *signer {
  1426    return &signer{
  1427      now: time.Now,
  1428    }
  1429  }
  1430  
  1431  func (s *signer) Sign(msg string) string {
  1432    now := s.now()
  1433    return signWithTime(msg, now)
  1434  }
  1435  ```
  1436  </td></tr>
  1437  <tr><td>
  1438  
  1439  ```go
  1440  // sign_test.go
  1441  
  1442  func TestSign(t *testing.T) {
  1443    oldTimeNow := _timeNow
  1444    _timeNow = func() time.Time {
  1445      return someFixedTime
  1446    }
  1447    defer func() { _timeNow = oldTimeNow }()
  1448  
  1449    assert.Equal(t, want, sign(give))
  1450  }
  1451  ```
  1452  
  1453  </td><td>
  1454  
  1455  ```go
  1456  // sign_test.go
  1457  
  1458  func TestSigner(t *testing.T) {
  1459    s := newSigner()
  1460    s.now = func() time.Time {
  1461      return someFixedTime
  1462    }
  1463  
  1464    assert.Equal(t, want, s.Sign(give))
  1465  }
  1466  
  1467  ```
  1468  
  1469  </td></tr>
  1470  </tbody></table>
  1471  
  1472  ## Avoid Embedding Types in Public Structs
  1473  
  1474  These embedded types leak implementation details, inhibit type evolution, and obscure documentation. Assuming you have implemented a variety of list types using a shared `AbstractList`, avoid embedding the `AbstractList` in your concrete list implementations. Instead, hand-write only the methods to your concrete list that will delegate to the abstract list.
  1475  
  1476  ```go
  1477  type AbstractList struct {}
  1478  
  1479  // Add adds an entity to the list.
  1480  func (l *AbstractList) Add(e Entity) {
  1481    // ...
  1482  }
  1483  
  1484  // Remove removes an entity from the list.
  1485  func (l *AbstractList) Remove(e Entity) {
  1486    // ...
  1487  }
  1488  ```
  1489  
  1490  <table>
  1491  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1492  <tbody>
  1493  <tr><td>
  1494  
  1495  ```go
  1496  // ConcreteList is a list of entities.
  1497  type ConcreteList struct {
  1498    *AbstractList
  1499  }
  1500  
  1501  
  1502  
  1503  
  1504  
  1505  
  1506  
  1507  
  1508  
  1509  
  1510  ```
  1511  
  1512  </td><td>
  1513  
  1514  ```go
  1515  // ConcreteList is a list of entities.
  1516  type ConcreteList struct {
  1517    list *AbstractList
  1518  }
  1519  
  1520  // Add adds an entity to the list.
  1521  func (l *ConcreteList) Add(e Entity) {
  1522    l.list.Add(e)
  1523  }
  1524  
  1525  // Remove removes an entity from the list.
  1526  func (l *ConcreteList) Remove(e Entity) {
  1527    l.list.Remove(e)
  1528  }
  1529  ```
  1530  
  1531  </td></tr>
  1532  </tbody></table>
  1533  
  1534  Go allows [type embedding] as a compromise between inheritance and composition. The outer type gets implicit copies of the embedded type's methods. These methods, by default, delegate to the same method of the embedded instance.
  1535  
  1536    [type embedding]: https://golang.org/doc/effective_go.html#embedding
  1537  
  1538  The struct also gains a field by the same name as the type. So, if the embedded type is public, the field is public. To maintain backward compatibility, every future version of the outer type must keep the embedded type.
  1539  
  1540  An embedded type is rarely necessary. It is a convenience that helps you avoid writing tedious delegate methods.
  1541  
  1542  Even embedding a compatible AbstractList *interface*, instead of the struct, would offer the developer more flexibility to change in the future, but still leak the detail that the concrete lists use an abstract implementation.
  1543  
  1544  <table>
  1545  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1546  <tbody>
  1547  <tr><td>
  1548  
  1549  ```go
  1550  // AbstractList is a generalized implementation
  1551  // for various kinds of lists of entities.
  1552  type AbstractList interface {
  1553    Add(Entity)
  1554    Remove(Entity)
  1555  }
  1556  
  1557  // ConcreteList is a list of entities.
  1558  type ConcreteList struct {
  1559    AbstractList
  1560  }
  1561  
  1562  
  1563  
  1564  
  1565  ```
  1566  
  1567  </td><td>
  1568  
  1569  ```go
  1570  // ConcreteList is a list of entities.
  1571  type ConcreteList struct {
  1572    list AbstractList
  1573  }
  1574  
  1575  // Add adds an entity to the list.
  1576  func (l *ConcreteList) Add(e Entity) {
  1577    l.list.Add(e)
  1578  }
  1579  
  1580  // Remove removes an entity from the list.
  1581  func (l *ConcreteList) Remove(e Entity) {
  1582    l.list.Remove(e)
  1583  }
  1584  ```
  1585  
  1586  </td></tr>
  1587  </tbody></table>
  1588  
  1589  Either with an embedded struct or an embedded interface, the embedded type places limits on the evolution of the type.
  1590  
  1591  - Adding methods to an embedded interface is a breaking change.
  1592  - Removing methods from an embedded struct is a breaking change.
  1593  - Removing the embedded type is a breaking change.
  1594  - Replacing the embedded type, even with an alternative that satisfies the same
  1595    interface, is a breaking change.
  1596  
  1597  Although writing these delegate methods is tedious, the additional effort hides an implementation detail, leaves more opportunities for change and also eliminates indirection for discovering the full List interface in documentation.
  1598  
  1599  ## Avoid Using Built-In Names
  1600  
  1601  The Go [language specification] outlines several built-in, [predeclared identifiers] that should not be used as names within Go programs.
  1602  
  1603  Depending on context, reusing these identifiers as names will either shadow the original within the current lexical scope (and any nested scopes) or make affected code confusing. In the best case, the compiler will complain; in the worst case, such code may introduce latent, hard-to-grep bugs.
  1604  
  1605    [language specification]: https://golang.org/ref/spec
  1606    [predeclared identifiers]: https://golang.org/ref/spec#Predeclared_identifiers
  1607  
  1608  <table>
  1609  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1610  <tbody>
  1611  <tr><td>
  1612  
  1613  ```go
  1614  var error string
  1615  // `error` shadows the builtin
  1616  
  1617  // or
  1618  
  1619  func handleErrorMessage(error string) {
  1620      // `error` shadows the builtin
  1621  }
  1622  ```
  1623  
  1624  </td><td>
  1625  
  1626  ```go
  1627  var errorMessage string
  1628  // `error` refers to the builtin
  1629  
  1630  // or
  1631  
  1632  func handleErrorMessage(msg string) {
  1633      // `error` refers to the builtin
  1634  }
  1635  ```
  1636  
  1637  </td></tr>
  1638  <tr><td>
  1639  
  1640  ```go
  1641  type Foo struct {
  1642      // While these fields technically don't
  1643      // constitute shadowing, grepping for
  1644      // `error` or `string` strings is now
  1645      // ambiguous.
  1646      error  error
  1647      string string
  1648  }
  1649  
  1650  func (f Foo) Error() error {
  1651      // `error` and `f.error` are
  1652      // visually similar
  1653      return f.error
  1654  }
  1655  
  1656  func (f Foo) String() string {
  1657      // `string` and `f.string` are
  1658      // visually similar
  1659      return f.string
  1660  }
  1661  ```
  1662  
  1663  </td><td>
  1664  
  1665  ```go
  1666  type Foo struct {
  1667      // `error` and `string` strings are
  1668      // now unambiguous.
  1669      err error
  1670      str string
  1671  }
  1672  
  1673  func (f Foo) Error() error {
  1674      return f.err
  1675  }
  1676  
  1677  func (f Foo) String() string {
  1678      return f.str
  1679  }
  1680  
  1681  
  1682  
  1683  
  1684  
  1685  
  1686  ```
  1687  </td></tr>
  1688  </tbody></table>
  1689  
  1690  *Note:* the compiler will not generate errors when using predeclared identifiers, but tools such as `go vet` should correctly point out these and other cases of shadowing.
  1691  
  1692  ## Avoid `init()`
  1693  
  1694  Avoid `init()` where possible. When `init()` is unavoidable or desirable, code should attempt to:
  1695  
  1696  1. Be completely deterministic, regardless of program environment or invocation.
  1697  2. Avoid depending on the ordering or side-effects of other `init()` functions. While `init()` ordering is well-known, code can change, and thus relationships between `init()` functions can make code brittle and   error-prone.
  1698  3. Avoid accessing or manipulating global or environment state, such as machine information, environment variables, working directory, program arguments/inputs, etc.
  1699  4. Avoid I/O, including both filesystem, network, and system calls.
  1700  
  1701  Code that cannot satisfy these requirements likely belongs as a helper to be called as part of `main()` (or elsewhere in a program's lifecycle), or be written as part of `main()` itself. In particular, libraries that are intended to be used by other programs should take special care to be completely deterministic and not perform "init magic".
  1702  
  1703  <table>
  1704  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1705  <tbody>
  1706  <tr><td>
  1707  
  1708  ```go
  1709  type Foo struct {
  1710      // ...
  1711  }
  1712  
  1713  var _defaultFoo Foo
  1714  
  1715  func init() {
  1716      _defaultFoo = Foo{
  1717          // ...
  1718      }
  1719  }
  1720  
  1721  
  1722  ```
  1723  
  1724  </td><td>
  1725  
  1726  ```go
  1727  var _defaultFoo = Foo{
  1728      // ...
  1729  }
  1730  
  1731  // or, better, for testability:
  1732  
  1733  var _defaultFoo = defaultFoo()
  1734  
  1735  func defaultFoo() Foo {
  1736      return Foo{
  1737          // ...
  1738      }
  1739  }
  1740  ```
  1741  
  1742  </td></tr>
  1743  <tr><td>
  1744  
  1745  ```go
  1746  type Config struct {
  1747      // ...
  1748  }
  1749  
  1750  var _config Config
  1751  
  1752  func init() {
  1753      // Bad: based on current directory
  1754      cwd, _ := os.Getwd()
  1755  
  1756      // Bad: I/O
  1757      raw, _ := os.ReadFile(
  1758          path.Join(cwd, "config", "config.yaml"),
  1759      )
  1760  
  1761      yaml.Unmarshal(raw, &_config)
  1762  }
  1763  ```
  1764  
  1765  </td><td>
  1766  
  1767  ```go
  1768  type Config struct {
  1769      // ...
  1770  }
  1771  
  1772  func loadConfig() Config {
  1773      cwd, err := os.Getwd()
  1774      // handle err
  1775  
  1776      raw, err := os.ReadFile(
  1777          path.Join(cwd, "config", "config.yaml"),
  1778      )
  1779      // handle err
  1780  
  1781      var config Config
  1782      yaml.Unmarshal(raw, &config)
  1783  
  1784      return config
  1785  }
  1786  ```
  1787  
  1788  </td></tr>
  1789  </tbody></table>
  1790  
  1791  Considering the above, some situations in which `init()` may be preferable or necessary might include:
  1792  
  1793  - Complex expressions that cannot be represented as single assignments.
  1794  - Pluggable hooks, such as `database/sql` dialects, encoding type registries, etc.
  1795  - Optimizations to [Google Cloud Functions] and other forms of deterministic precomputation.
  1796  
  1797    [Google Cloud Functions]: https://cloud.google.com/functions/docs/bestpractices/tips#use_global_variables_to_reuse_objects_in_future_invocations
  1798  
  1799  ## Exit in Main
  1800  
  1801  Go programs use [`os.Exit`] or [`log.Fatal*`] to exit immediately. (Panicking is not a good way to exit programs, please [Panic with care](#panic-with-care).)
  1802  
  1803    [`os.Exit`]: https://golang.org/pkg/os/#Exit
  1804    [`log.Fatal*`]: https://golang.org/pkg/log/#Fatal
  1805  
  1806  Call one of `os.Exit` or `log.Fatal*` **only in `main()`**. All other functions should return errors to signal failure.
  1807  
  1808  <table>
  1809  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1810  <tbody>
  1811  <tr><td>
  1812  
  1813  ```go
  1814  func main() {
  1815    body := readFile(path)
  1816    fmt.Println(body)
  1817  }
  1818  
  1819  func readFile(path string) string {
  1820    f, err := os.Open(path)
  1821    if err != nil {
  1822      log.Fatal(err)
  1823    }
  1824  
  1825    b, err := io.ReadAll(f)
  1826    if err != nil {
  1827      log.Fatal(err)
  1828    }
  1829  
  1830    return string(b)
  1831  }
  1832  
  1833  
  1834  
  1835  ```
  1836  
  1837  </td><td>
  1838  
  1839  ```go
  1840  func main() {
  1841    body, err := readFile(path)
  1842    if err != nil {
  1843      log.Fatal(err)
  1844    }
  1845    fmt.Println(body)
  1846  }
  1847  
  1848  func readFile(path string) (string, error) {
  1849    f, err := os.Open(path)
  1850    if err != nil {
  1851      return "", err
  1852    }
  1853  
  1854    b, err := io.ReadAll(f)
  1855    if err != nil {
  1856      return "", err
  1857    }
  1858  
  1859    return string(b), nil
  1860  }
  1861  ```
  1862  
  1863  </td></tr>
  1864  </tbody></table>
  1865  
  1866  Rationale: Programs with multiple functions that exit present a few issues:
  1867  
  1868  - Non-obvious control flow: Any function can exit the program so it becomes difficult to reason about the control flow.
  1869  - Difficult to test: A function that exits the program will also exit the test calling it. This makes the function difficult to test and introduces risk of skipping other tests that have not yet been run by `go test`.
  1870  - Skipped cleanup: When a function exits the program, it skips function calls enqueued with `defer` statements. This adds risk of skipping important cleanup tasks.
  1871  
  1872  ### Exit Once
  1873  
  1874  If possible, prefer to call `os.Exit` or `log.Fatal` **at most once** in your `main()`. If there are multiple error scenarios that halt program execution, put that logic under a separate function and return errors from it.
  1875  
  1876  This has the effect of shortening your `main()` function and putting all key business logic into a separate, testable function.
  1877  
  1878  <table>
  1879  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1880  <tbody>
  1881  <tr><td>
  1882  
  1883  ```go
  1884  package main
  1885  
  1886  func main() {
  1887    args := os.Args[1:]
  1888    if len(args) != 1 {
  1889      log.Fatal("missing file")
  1890    }
  1891    name := args[0]
  1892  
  1893    f, err := os.Open(name)
  1894    if err != nil {
  1895      log.Fatal(err)
  1896    }
  1897    defer f.Close()
  1898  
  1899    // If we call log.Fatal after this line,
  1900    // f.Close will not be called.
  1901  
  1902    b, err := io.ReadAll(f)
  1903    if err != nil {
  1904      log.Fatal(err)
  1905    }
  1906  
  1907    // ...
  1908  }
  1909  
  1910  
  1911  
  1912  ```
  1913  
  1914  </td><td>
  1915  
  1916  ```go
  1917  package main
  1918  
  1919  func main() {
  1920    if err := run(); err != nil {
  1921      log.Fatal(err)
  1922    }
  1923  }
  1924  
  1925  func run() error {
  1926    args := os.Args[1:]
  1927    if len(args) != 1 {
  1928      return errors.New("missing file")
  1929    }
  1930    name := args[0]
  1931  
  1932    f, err := os.Open(name)
  1933    if err != nil {
  1934      return err
  1935    }
  1936    defer f.Close()
  1937  
  1938    b, err := io.ReadAll(f)
  1939    if err != nil {
  1940      return err
  1941    }
  1942  
  1943    // ...
  1944  }
  1945  ```
  1946  
  1947  </td></tr>
  1948  </tbody></table>
  1949  
  1950  ## Performance
  1951  
  1952  Performance-specific guidelines apply only to the hot path.
  1953  
  1954  ### Prefer strconv over fmt
  1955  
  1956  When converting primitives to/from strings, `strconv` is faster than `fmt`.
  1957  
  1958  <table>
  1959  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1960  <tbody>
  1961  <tr><td>
  1962  
  1963  ```go
  1964  for i := 0; i < b.N; i++ {
  1965    s := fmt.Sprint(rand.Int())
  1966  }
  1967  ```
  1968  
  1969  </td><td>
  1970  
  1971  ```go
  1972  for i := 0; i < b.N; i++ {
  1973    s := strconv.Itoa(rand.Int())
  1974  }
  1975  ```
  1976  
  1977  </td></tr>
  1978  <tr><td>
  1979  
  1980  ```
  1981  BenchmarkFmtSprint-4    143 ns/op    2 allocs/op
  1982  ```
  1983  
  1984  </td><td>
  1985  
  1986  ```
  1987  BenchmarkStrconv-4    64.2 ns/op    1 allocs/op
  1988  ```
  1989  
  1990  </td></tr>
  1991  </tbody></table>
  1992  
  1993  ### Avoid string-to-byte conversion
  1994  
  1995  Do not create byte slices from a fixed string repeatedly. Instead, perform the conversion once and capture the result.
  1996  
  1997  <table>
  1998  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  1999  <tbody>
  2000  <tr><td>
  2001  
  2002  ```go
  2003  for i := 0; i < b.N; i++ {
  2004    w.Write([]byte("Hello world"))
  2005  }
  2006  
  2007  ```
  2008  
  2009  </td><td>
  2010  
  2011  ```go
  2012  data := []byte("Hello world")
  2013  for i := 0; i < b.N; i++ {
  2014    w.Write(data)
  2015  }
  2016  ```
  2017  
  2018  </tr>
  2019  <tr><td>
  2020  
  2021  ```
  2022  BenchmarkBad-4   50000000   22.2 ns/op
  2023  ```
  2024  
  2025  </td><td>
  2026  
  2027  ```
  2028  BenchmarkGood-4  500000000   3.25 ns/op
  2029  ```
  2030  
  2031  </td></tr>
  2032  </tbody></table>
  2033  
  2034  ### Prefer Specifying Container Capacity
  2035  
  2036  Specify container capacity where possible in order to allocate memory for the container up front. This minimizes subsequent allocations (by copying and resizing of the container) as elements are added.
  2037  
  2038  ### Specifying Map Capacity Hints
  2039  
  2040  Where possible, provide capacity hints when initializing maps with `make()`.
  2041  
  2042  ```go
  2043  make(map[T1]T2, hint)
  2044  ```
  2045  
  2046  Providing a capacity hint to `make()` tries to right-size the map at initialization time, which reduces the need for growing the map and allocations as elements are added to the map.
  2047  
  2048  *Note:* unlike slices, map capacity hints do not guarantee complete, preemptive allocation, but are used to approximate the number of hashmap buckets required. Consequently, allocations may still occur when adding elements to the map, even up to the specified capacity.
  2049  
  2050  <table>
  2051  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  2052  <tbody>
  2053  <tr><td>
  2054  
  2055  ```go
  2056  m := make(map[string]os.FileInfo)
  2057  
  2058  files, _ := os.ReadDir("./files")
  2059  for _, f := range files {
  2060      m[f.Name()] = f
  2061  }
  2062  
  2063  ```
  2064  
  2065  </td><td>
  2066  
  2067  ```go
  2068  
  2069  files, _ := os.ReadDir("./files")
  2070  
  2071  m := make(map[string]os.FileInfo, len(files))
  2072  for _, f := range files {
  2073      m[f.Name()] = f
  2074  }
  2075  ```
  2076  
  2077  </td></tr>
  2078  <tr><td>
  2079  
  2080  `m` is created without a size hint; there may be more allocations at assignment time.
  2081  
  2082  </td><td>
  2083  
  2084  `m` is created with a size hint; there may be fewer allocations at assignment time.
  2085  
  2086  </td></tr>
  2087  </tbody></table>
  2088  
  2089  ### Specifying Slice Capacity
  2090  
  2091  Where possible, provide capacity hints when initializing slices with `make()`, particularly when appending.
  2092  
  2093  ```go
  2094  make([]T, length, capacity)
  2095  ```
  2096  
  2097  Unlike maps, slice capacity is not a hint: the compiler will allocate enough memory for the capacity of the slice as provided to `make()`, which means that subsequent `append()` operations will incur zero allocations (until the length of the slice matches the capacity, after which any appends will require a resize to hold additional elements).
  2098  
  2099  <table>
  2100  <thead><tr><th>Bad</th><th>Good</th></tr></thead>
  2101  <tbody>
  2102  <tr><td>
  2103  
  2104  ```go
  2105  for n := 0; n < b.N; n++ {
  2106    data := make([]int, 0)
  2107    for k := 0; k < size; k++{
  2108      data = append(data, k)
  2109    }
  2110  }
  2111  ```
  2112  
  2113  </td><td>
  2114  
  2115  ```go
  2116  for n := 0; n < b.N; n++ {
  2117    data := make([]int, 0, size)
  2118    for k := 0; k < size; k++{
  2119      data = append(data, k)
  2120    }
  2121  }
  2122  ```
  2123  
  2124  </td></tr>
  2125  <tr><td>
  2126  
  2127  ```
  2128  BenchmarkBad-4    100000000    2.48s
  2129  ```
  2130  
  2131  </td><td>
  2132  
  2133  ```
  2134  BenchmarkGood-4   100000000    0.21s
  2135  ```
  2136  
  2137  </td></tr>
  2138  </tbody></table>