diff --git a/.golangci.yml b/.golangci.yml index 823ab972..cde2ddaf 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,19 +1,135 @@ -# Refer to golangci-lint's example config file for more options and information: -# https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml - run: timeout: 5m - modules-download-mode: readonly +# The list of linter based on the v1.63.4 +# See the full list https://golangci-lint.run/usage/linters/ linters: + disable-all: true enable: - errcheck - - goimports - - golint + - gosimple - govet + - ineffassign - staticcheck + - unused + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - contextcheck + - cyclop + - dogsled + - dupl + - dupword + - durationcheck + - err113 + - errchkjson + - errname + - errorlint + - exptostd + - forbidigo + - forcetypeassert + - funlen + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + - gofmt + - goimports + - goprintffuncname + - gosec + - grouper + - iface + - importas + - ireturn + - lll + - loggercheck + - maintidx + - makezero + - mirror + - misspell + - mnd + - musttag + - nakedret + - nestif + - nilerr + - nilnesserr + - nilnil + - nlreturn + - noctx + - nolintlint + - perfsprint + - prealloc + - predeclared + - protogetter + - reassign + - recvcheck + - revive + - rowserrcheck + - sloglint + - sqlclosecheck + - stylecheck + - tagliatelle + - tenv + - testifylint + - unconvert + - unparam + - usestdlibvars + - usetesting + - wastedassign + - whitespace + +linters-settings: + goimports: + local-prefixes: github.com/example/repo + dupl: + threshold: 100 + funlen: + lines: 120 + statements: 60 + goconst: + min-len: 2 + min-occurrences: 2 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + gocyclo: + min-complexity: 20 + cyclop: + max-complexity: 20 + skip-tests: true + lll: + line-length: 140 + misspell: + locale: US + nolintlint: + allow-unused: false + require-explanation: false + require-specific: false + nestif: + min-complexity: 4 issues: - exclude-use-default: false - max-issues-per-linter: 0 - max-same-issues: 0 + #new-from-rev: HEAD + exclude-dirs: + - tilt_modules + - vendor + exclude-rules: + - path: _test\.go + linters: + - dupl + - mnd + - funlen + - gocyclo + - lll + - path: main\.go + linters: + - funlen + - forbidigo + - cyclop diff --git a/LINTER.md b/LINTER.md new file mode 100644 index 00000000..0122ecf3 --- /dev/null +++ b/LINTER.md @@ -0,0 +1,63 @@ +# Linter coverage + +| Section | Subsection | Coverage | +|-------------|----------------------------------------------------|--------------------| +| Guidelines | Pointers to Interfaces | :heavy_check_mark: | +| | Verify Interface Compliance | - | +| | Receivers and Interfaces | - | +| | Zero-value Mutexes are Valid | - | +| | Copy Slices and Maps at Boundaries | | +| | - Receiving Slices and Maps | - | +| | - Returning Slices and Maps | - | +| | - Always return a slice if a function modifies one | - | +| | Defer to Clean Up | - | +| | Channel Size is One or None | - | +| | Start Enums at One | - | +| | String() for enums | - | +| | Use `"time"` to handle time | - | +| | Errors | | +| | - Error Types | :heavy_check_mark: | +| | - Error Wrapping | - | +| | - Error Naming | :heavy_check_mark: | +| | - Handle Errors Once | - | +| | Handle Type Assertion Failures | :heavy_check_mark: | +| | Don't Panic | - | +| | Use go.uber.org/atomic | - | +| | Avoid Mutable Globals | - | +| | Avoid Embedding Types in Public Structs | - | +| | Avoid Using Built-In Names | :heavy_check_mark: | +| | Avoid `init()` | :heavy_check_mark: | +| | Exit in Main | - | +| | - Exit Once | - | +| | Use field tags in marshaled structs | :heavy_check_mark: | +| | Don't fire-and-forget goroutines | - | +| | - Wait for goroutines to exit | - | +| Performance | Prefer strconv over fmt | :heavy_check_mark: | +| | Avoid repeated string-to-byte conversions | :heavy_check_mark: | +| | Prefer Specifying Container Capacity | :heavy_check_mark: | +| Style | Avoid overly long lines | :heavy_check_mark: | +| | Be Consistent | - | +| | Group Similar Declarations | - | +| | Import Group Ordering | :heavy_check_mark: | +| | Package Names | :heavy_check_mark: | +| | Function Names | - | +| | Import Aliasing | - | +| | Function Grouping and Ordering | - | +| | Reduce Nesting | :heavy_check_mark: | +| | Unnecessary Else | :heavy_check_mark: | +| | Top-level Variable Declarations | - | +| | Prefix Unexported Globals with `_` | - | +| | Embedding in Structs | - | +| | Local Variable Declarations | - | +| | nil is a valid slice | - | +| | Reduce Scope of Variables | - | +| | Avoid Naked Parameters | - | +| | Use Raw String Literals to Avoid Escaping | - | +| | Initializing Structs | | +| | - Use Field Names to Initialize Structs | - | +| | - Omit Zero Value Fields in Structs | - | +| | - Use `var` for Zero Value Structs | - | +| | - Initializing Struct References | - | +| | Initializing Maps | - | +| | Format Strings outside Printf | - | +| | Naming Printf-style Functions | - | diff --git a/README.md b/README.md index 83fa99ad..b2e981bd 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,10 @@ patterns and conventions used in Go code at Velmie. This guide is based on the [ See [Velmie Go Style Guide](style.md) for the style guide. -## Contributing +### Contributing Make changes according to the [guide](CONTRIBUTING.md) and make a pull-request. The CI generates the result `style.md` file. + +## `golangci-lint` configuration + +See the `.golangci.yml` file and [linter coverage](LINTER.md). diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 2629eb1c..f69b2489 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -29,7 +29,6 @@ - [Use field tags in marshaled structs](struct-tag.md) - [Don't fire-and-forget goroutines](goroutine-forget.md) - [Wait for goroutines to exit](goroutine-exit.md) - - [No goroutines in `init()`](goroutine-init.md) - [Performance](performance.md) - [Prefer strconv over fmt](strconv.md) - [Avoid repeated string-to-byte conversions](string-byte-slice.md) diff --git a/src/goroutine-init.md b/src/goroutine-init.md deleted file mode 100644 index 3ffe3c94..00000000 --- a/src/goroutine-init.md +++ /dev/null @@ -1,77 +0,0 @@ -# No goroutines in `init()` - -`init()` functions should not spawn goroutines. -See also [Avoid init()](init.md). - -If a package has need of a background goroutine, -it must expose an object that is responsible for managing a goroutine's -lifetime. -The object must provide a method (`Close`, `Stop`, `Shutdown`, etc) -that signals the background goroutine to stop, and waits for it to exit. - - - - - - -
BadGood
- -```go -func init() { - go doWork() -} - -func doWork() { - for { - // ... - } -} -``` - - - -```go -type Worker struct{ /* ... */ } - -func NewWorker(...) *Worker { - w := &Worker{ - stop: make(chan struct{}), - done: make(chan struct{}), - // ... - } - go w.doWork() -} - -func (w *Worker) doWork() { - defer close(w.done) - for { - // ... - case <-w.stop: - return - } -} - -// Shutdown tells the worker to stop -// and waits until it has finished. -func (w *Worker) Shutdown() { - close(w.stop) - <-w.done -} -``` - -
- -Spawns a background goroutine unconditionally when the user exports this package. -The user has no control over the goroutine or a means of stopping it. - - - -Spawns the worker only if the user requests it. -Provides a means of shutting down the worker so that the user can free up -resources used by the worker. - -Note that you should use `WaitGroup`s if the worker manages multiple -goroutines. -See [Wait for goroutines to exit](goroutine-exit.md). - -
diff --git a/style.md b/style.md index b1f1ba50..dd4cd9d0 100644 --- a/style.md +++ b/style.md @@ -36,7 +36,6 @@ - [Use field tags in marshaled structs](#use-field-tags-in-marshaled-structs) - [Don't fire-and-forget goroutines](#dont-fire-and-forget-goroutines) - [Wait for goroutines to exit](#wait-for-goroutines-to-exit) - - [No goroutines in `init()`](#no-goroutines-in-init) - [Performance](#performance) - [Prefer strconv over fmt](#prefer-strconv-over-fmt) - [Avoid repeated string-to-byte conversions](#avoid-repeated-string-to-byte-conversions) @@ -2131,84 +2130,6 @@ There are two popular ways to do this: <-done ``` -#### No goroutines in `init()` - -`init()` functions should not spawn goroutines. -See also [Avoid init()](#avoid-init). - -If a package has need of a background goroutine, -it must expose an object that is responsible for managing a goroutine's -lifetime. -The object must provide a method (`Close`, `Stop`, `Shutdown`, etc) -that signals the background goroutine to stop, and waits for it to exit. - - - - - - -
BadGood
- -```go -func init() { - go doWork() -} - -func doWork() { - for { - // ... - } -} -``` - - - -```go -type Worker struct{ /* ... */ } - -func NewWorker(...) *Worker { - w := &Worker{ - stop: make(chan struct{}), - done: make(chan struct{}), - // ... - } - go w.doWork() -} - -func (w *Worker) doWork() { - defer close(w.done) - for { - // ... - case <-w.stop: - return - } -} - -// Shutdown tells the worker to stop -// and waits until it has finished. -func (w *Worker) Shutdown() { - close(w.stop) - <-w.done -} -``` - -
- -Spawns a background goroutine unconditionally when the user exports this package. -The user has no control over the goroutine or a means of stopping it. - - - -Spawns the worker only if the user requests it. -Provides a means of shutting down the worker so that the user can free up -resources used by the worker. - -Note that you should use `WaitGroup`s if the worker manages multiple -goroutines. -See [Wait for goroutines to exit](#wait-for-goroutines-to-exit). - -
- ## Performance ### Prefer strconv over fmt