-
Star
(355)
You must be signed in to star a gist -
Fork
(40)
You must be signed in to fork a gist
-
-
Save maratori/47a4d00457a92aa426dbd48a18776322 to your computer and use it in GitHub Desktop.
# This file is licensed under the terms of the MIT license https://opensource.org/license/mit | |
# Copyright (c) 2021-2025 Marat Reymers | |
## Golden config for golangci-lint v2.1.2 | |
# | |
# This is the best config for golangci-lint based on my experience and opinion. | |
# It is very strict, but not extremely strict. | |
# Feel free to adapt it to suit your needs. | |
# If this config helps you, please consider keeping a link to this file (see the next comment). | |
# Based on https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322 | |
version: "2" | |
issues: | |
# Maximum count of issues with the same text. | |
# Set to 0 to disable. | |
# Default: 3 | |
max-same-issues: 50 | |
formatters: | |
enable: | |
- goimports # checks if the code and import statements are formatted according to the 'goimports' command | |
- golines # checks if code is formatted, and fixes long lines | |
## you may want to enable | |
#- gci # checks if code and import statements are formatted, with additional rules | |
#- gofmt # checks if the code is formatted according to 'gofmt' command | |
## disabled | |
#- gofumpt # [replaced by goimports, gofumports is not available yet] checks if code and import statements are formatted, with additional rules | |
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml | |
settings: | |
goimports: | |
# A list of prefixes, which, if set, checks import paths | |
# with the given prefixes are grouped after 3rd-party packages. | |
# Default: [] | |
local-prefixes: | |
- github.com/my/project | |
golines: | |
# Target maximum line length. | |
# Default: 100 | |
max-len: 120 | |
linters: | |
enable: | |
- asasalint # checks for pass []any as any in variadic func(...any) | |
- asciicheck # checks that your code does not contain non-ASCII identifiers | |
- bidichk # checks for dangerous unicode character sequences | |
- bodyclose # checks whether HTTP response body is closed successfully | |
- canonicalheader # checks whether net/http.Header uses canonical header | |
- copyloopvar # detects places where loop variables are copied (Go 1.22+) | |
- cyclop # checks function and package cyclomatic complexity | |
- depguard # checks if package imports are in a list of acceptable packages | |
- dupl # tool for code clone detection | |
- durationcheck # checks for two durations multiplied together | |
- errcheck # checking for unchecked errors, these unchecked errors can be critical bugs in some cases | |
- errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error | |
- errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13 | |
- exhaustive # checks exhaustiveness of enum switch statements | |
- exptostd # detects functions from golang.org/x/exp/ that can be replaced by std functions | |
- fatcontext # detects nested contexts in loops | |
- forbidigo # forbids identifiers | |
- funcorder # checks the order of functions, methods, and constructors | |
- funlen # tool for detection of long functions | |
- gocheckcompilerdirectives # validates go compiler directive comments (//go:) | |
- gochecknoglobals # checks that no global variables exist | |
- gochecknoinits # checks that no init functions are present in Go code | |
- gochecksumtype # checks exhaustiveness on Go "sum types" | |
- gocognit # computes and checks the cognitive complexity of functions | |
- goconst # finds repeated strings that could be replaced by a constant | |
- gocritic # provides diagnostics that check for bugs, performance and style issues | |
- gocyclo # computes and checks the cyclomatic complexity of functions | |
- godot # checks if comments end in a period | |
- gomoddirectives # manages the use of 'replace', 'retract', and 'excludes' directives in go.mod | |
- goprintffuncname # checks that printf-like functions are named with f at the end | |
- gosec # inspects source code for security problems | |
- govet # reports suspicious constructs, such as Printf calls whose arguments do not align with the format string | |
- iface # checks the incorrect use of interfaces, helping developers avoid interface pollution | |
- ineffassign # detects when assignments to existing variables are not used | |
- intrange # finds places where for loops could make use of an integer range | |
- loggercheck # checks key value pairs for common logger libraries (kitlog,klog,logr,zap) | |
- makezero # finds slice declarations with non-zero initial length | |
- mirror # reports wrong mirror patterns of bytes/strings usage | |
- mnd # detects magic numbers | |
- musttag # enforces field tags in (un)marshaled structs | |
- nakedret # finds naked returns in functions greater than a specified function length | |
- nestif # reports deeply nested if statements | |
- nilerr # finds the code that returns nil even if it checks that the error is not nil | |
- nilnesserr # reports that it checks for err != nil, but it returns a different nil value error (powered by nilness and nilerr) | |
- nilnil # checks that there is no simultaneous return of nil error and an invalid value | |
- noctx # finds sending http request without context.Context | |
- nolintlint # reports ill-formed or insufficient nolint directives | |
- nonamedreturns # reports all named returns | |
- nosprintfhostport # checks for misuse of Sprintf to construct a host with port in a URL | |
- perfsprint # checks that fmt.Sprintf can be replaced with a faster alternative | |
- predeclared # finds code that shadows one of Go's predeclared identifiers | |
- promlinter # checks Prometheus metrics naming via promlint | |
- protogetter # reports direct reads from proto message fields when getters should be used | |
- reassign # checks that package variables are not reassigned | |
- recvcheck # checks for receiver type consistency | |
- revive # fast, configurable, extensible, flexible, and beautiful linter for Go, drop-in replacement of golint | |
- rowserrcheck # checks whether Err of rows is checked successfully | |
- sloglint # ensure consistent code style when using log/slog | |
- spancheck # checks for mistakes with OpenTelemetry/Census spans | |
- sqlclosecheck # checks that sql.Rows and sql.Stmt are closed | |
- staticcheck # is a go vet on steroids, applying a ton of static analysis checks | |
- testableexamples # checks if examples are testable (have an expected output) | |
- testifylint # checks usage of github.com/stretchr/testify | |
- testpackage # makes you use a separate _test package | |
- tparallel # detects inappropriate usage of t.Parallel() method in your Go test codes | |
- unconvert # removes unnecessary type conversions | |
- unparam # reports unused function parameters | |
- unused # checks for unused constants, variables, functions and types | |
- usestdlibvars # detects the possibility to use variables/constants from the Go standard library | |
- usetesting # reports uses of functions with replacement inside the testing package | |
- wastedassign # finds wasted assignment statements | |
- whitespace # detects leading and trailing whitespace | |
## you may want to enable | |
#- decorder # checks declaration order and count of types, constants, variables and functions | |
#- exhaustruct # [highly recommend to enable] checks if all structure fields are initialized | |
#- ginkgolinter # [if you use ginkgo/gomega] enforces standards of using ginkgo and gomega | |
#- godox # detects usage of FIXME, TODO and other keywords inside comments | |
#- goheader # checks is file header matches to pattern | |
#- inamedparam # [great idea, but too strict, need to ignore a lot of cases by default] reports interfaces with unnamed method parameters | |
#- interfacebloat # checks the number of methods inside an interface | |
#- ireturn # accept interfaces, return concrete types | |
#- prealloc # [premature optimization, but can be used in some cases] finds slice declarations that could potentially be preallocated | |
#- tagalign # checks that struct tags are well aligned | |
#- varnamelen # [great idea, but too many false positives] checks that the length of a variable's name matches its scope | |
#- wrapcheck # checks that errors returned from external packages are wrapped | |
#- zerologlint # detects the wrong usage of zerolog that a user forgets to dispatch zerolog.Event | |
## disabled | |
#- containedctx # detects struct contained context.Context field | |
#- contextcheck # [too many false positives] checks the function whether use a non-inherited context | |
#- dogsled # checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) | |
#- dupword # [useless without config] checks for duplicate words in the source code | |
#- err113 # [too strict] checks the errors handling expressions | |
#- errchkjson # [don't see profit + I'm against of omitting errors like in the first example https://github.com/breml/errchkjson] checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted | |
#- forcetypeassert # [replaced by errcheck] finds forced type assertions | |
#- gomodguard # [use more powerful depguard] allow and block lists linter for direct Go module dependencies | |
#- gosmopolitan # reports certain i18n/l10n anti-patterns in your Go codebase | |
#- grouper # analyzes expression groups | |
#- importas # enforces consistent import aliases | |
#- lll # [replaced by golines] reports long lines | |
#- maintidx # measures the maintainability index of each function | |
#- misspell # [useless] finds commonly misspelled English words in comments | |
#- nlreturn # [too strict and mostly code is not more readable] checks for a new line before return and branch statements to increase code clarity | |
#- paralleltest # [too many false positives] detects missing usage of t.Parallel() method in your Go test | |
#- tagliatelle # checks the struct tags | |
#- thelper # detects golang test helpers without t.Helper() call and checks the consistency of test helpers | |
#- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines | |
# All settings can be found here https://github.com/golangci/golangci-lint/blob/HEAD/.golangci.reference.yml | |
settings: | |
cyclop: | |
# The maximal code complexity to report. | |
# Default: 10 | |
max-complexity: 30 | |
# The maximal average package complexity. | |
# If it's higher than 0.0 (float) the check is enabled. | |
# Default: 0.0 | |
package-average: 10.0 | |
depguard: | |
# Rules to apply. | |
# | |
# Variables: | |
# - File Variables | |
# Use an exclamation mark `!` to negate a variable. | |
# Example: `!$test` matches any file that is not a go test file. | |
# | |
# `$all` - matches all go files | |
# `$test` - matches all go test files | |
# | |
# - Package Variables | |
# | |
# `$gostd` - matches all of go's standard library (Pulled from `GOROOT`) | |
# | |
# Default (applies if no custom rules are defined): Only allow $gostd in all files. | |
rules: | |
"deprecated": | |
# List of file globs that will match this list of settings to compare against. | |
# By default, if a path is relative, it is relative to the directory where the golangci-lint command is executed. | |
# The placeholder '${base-path}' is substituted with a path relative to the mode defined with `run.relative-path-mode`. | |
# The placeholder '${config-path}' is substituted with a path relative to the configuration file. | |
# Default: $all | |
files: | |
- "$all" | |
# List of packages that are not allowed. | |
# Entries can be a variable (starting with $), a string prefix, or an exact match (if ending with $). | |
# Default: [] | |
deny: | |
- pkg: github.com/golang/protobuf | |
desc: Use google.golang.org/protobuf instead, see https://developers.google.com/protocol-buffers/docs/reference/go/faq#modules | |
- pkg: github.com/satori/go.uuid | |
desc: Use github.com/google/uuid instead, satori's package is not maintained | |
- pkg: github.com/gofrs/uuid$ | |
desc: Use github.com/gofrs/uuid/v5 or later, it was not a go module before v5 | |
"non-test files": | |
files: | |
- "!$test" | |
deny: | |
- pkg: math/rand$ | |
desc: Use math/rand/v2 instead, see https://go.dev/blog/randv2 | |
"non-main files": | |
files: | |
- "!**/main.go" | |
deny: | |
- pkg: log$ | |
desc: Use log/slog instead, see https://go.dev/blog/slog | |
errcheck: | |
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`. | |
# Such cases aren't reported by default. | |
# Default: false | |
check-type-assertions: true | |
exhaustive: | |
# Program elements to check for exhaustiveness. | |
# Default: [ switch ] | |
check: | |
- switch | |
- map | |
exhaustruct: | |
# List of regular expressions to exclude struct packages and their names from checks. | |
# Regular expressions must match complete canonical struct package/name/structname. | |
# Default: [] | |
exclude: | |
# std libs | |
- ^net/http.Client$ | |
- ^net/http.Cookie$ | |
- ^net/http.Request$ | |
- ^net/http.Response$ | |
- ^net/http.Server$ | |
- ^net/http.Transport$ | |
- ^net/url.URL$ | |
- ^os/exec.Cmd$ | |
- ^reflect.StructField$ | |
# public libs | |
- ^github.com/Shopify/sarama.Config$ | |
- ^github.com/Shopify/sarama.ProducerMessage$ | |
- ^github.com/mitchellh/mapstructure.DecoderConfig$ | |
- ^github.com/prometheus/client_golang/.+Opts$ | |
- ^github.com/spf13/cobra.Command$ | |
- ^github.com/spf13/cobra.CompletionOptions$ | |
- ^github.com/stretchr/testify/mock.Mock$ | |
- ^github.com/testcontainers/testcontainers-go.+Request$ | |
- ^github.com/testcontainers/testcontainers-go.FromDockerfile$ | |
- ^golang.org/x/tools/go/analysis.Analyzer$ | |
- ^google.golang.org/protobuf/.+Options$ | |
- ^gopkg.in/yaml.v3.Node$ | |
funcorder: | |
# Checks if the exported methods of a structure are placed before the non-exported ones. | |
# Default: true | |
struct-method: false | |
funlen: | |
# Checks the number of lines in a function. | |
# If lower than 0, disable the check. | |
# Default: 60 | |
lines: 100 | |
# Checks the number of statements in a function. | |
# If lower than 0, disable the check. | |
# Default: 40 | |
statements: 50 | |
gochecksumtype: | |
# Presence of `default` case in switch statements satisfies exhaustiveness, if all members are not listed. | |
# Default: true | |
default-signifies-exhaustive: false | |
gocognit: | |
# Minimal code complexity to report. | |
# Default: 30 (but we recommend 10-20) | |
min-complexity: 20 | |
gocritic: | |
# Settings passed to gocritic. | |
# The settings key is the name of a supported gocritic checker. | |
# The list of supported checkers can be found at https://go-critic.com/overview. | |
settings: | |
captLocal: | |
# Whether to restrict checker to params only. | |
# Default: true | |
paramsOnly: false | |
underef: | |
# Whether to skip (*x).method() calls where x is a pointer receiver. | |
# Default: true | |
skipRecvDeref: false | |
govet: | |
# Enable all analyzers. | |
# Default: false | |
enable-all: true | |
# Disable analyzers by name. | |
# Run `GL_DEBUG=govet golangci-lint run --enable=govet` to see default, all available analyzers, and enabled analyzers. | |
# Default: [] | |
disable: | |
- fieldalignment # too strict | |
# Settings per analyzer. | |
settings: | |
shadow: | |
# Whether to be strict about shadowing; can be noisy. | |
# Default: false | |
strict: true | |
inamedparam: | |
# Skips check for interface methods with only a single parameter. | |
# Default: false | |
skip-single-param: true | |
mnd: | |
# List of function patterns to exclude from analysis. | |
# Values always ignored: `time.Date`, | |
# `strconv.FormatInt`, `strconv.FormatUint`, `strconv.FormatFloat`, | |
# `strconv.ParseInt`, `strconv.ParseUint`, `strconv.ParseFloat`. | |
# Default: [] | |
ignored-functions: | |
- args.Error | |
- flag.Arg | |
- flag.Duration.* | |
- flag.Float.* | |
- flag.Int.* | |
- flag.Uint.* | |
- os.Chmod | |
- os.Mkdir.* | |
- os.OpenFile | |
- os.WriteFile | |
- prometheus.ExponentialBuckets.* | |
- prometheus.LinearBuckets | |
nakedret: | |
# Make an issue if func has more lines of code than this setting, and it has naked returns. | |
# Default: 30 | |
max-func-lines: 0 | |
nolintlint: | |
# Exclude following linters from requiring an explanation. | |
# Default: [] | |
allow-no-explanation: [ funlen, gocognit, golines ] | |
# Enable to require an explanation of nonzero length after each nolint directive. | |
# Default: false | |
require-explanation: true | |
# Enable to require nolint directives to mention the specific linter being suppressed. | |
# Default: false | |
require-specific: true | |
perfsprint: | |
# Optimizes into strings concatenation. | |
# Default: true | |
strconcat: false | |
reassign: | |
# Patterns for global variable names that are checked for reassignment. | |
# See https://github.com/curioswitch/go-reassign#usage | |
# Default: ["EOF", "Err.*"] | |
patterns: | |
- ".*" | |
rowserrcheck: | |
# database/sql is always checked. | |
# Default: [] | |
packages: | |
- github.com/jmoiron/sqlx | |
sloglint: | |
# Enforce not using global loggers. | |
# Values: | |
# - "": disabled | |
# - "all": report all global loggers | |
# - "default": report only the default slog logger | |
# https://github.com/go-simpler/sloglint?tab=readme-ov-file#no-global | |
# Default: "" | |
no-global: all | |
# Enforce using methods that accept a context. | |
# Values: | |
# - "": disabled | |
# - "all": report all contextless calls | |
# - "scope": report only if a context exists in the scope of the outermost function | |
# https://github.com/go-simpler/sloglint?tab=readme-ov-file#context-only | |
# Default: "" | |
context: scope | |
staticcheck: | |
# SAxxxx checks in https://staticcheck.dev/docs/configuration/options/#checks | |
# Example (to disable some checks): [ "all", "-SA1000", "-SA1001"] | |
# Default: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022"] | |
checks: | |
- all | |
# Incorrect or missing package comment. | |
# https://staticcheck.dev/docs/checks/#ST1000 | |
- -ST1000 | |
# Use consistent method receiver names. | |
# https://staticcheck.dev/docs/checks/#ST1016 | |
- -ST1016 | |
# Omit embedded fields from selector expression. | |
# https://staticcheck.dev/docs/checks/#QF1008 | |
- -QF1008 | |
usetesting: | |
# Enable/disable `os.TempDir()` detections. | |
# Default: false | |
os-temp-dir: true | |
exclusions: | |
# Log a warning if an exclusion rule is unused. | |
# Default: false | |
warn-unused: true | |
# Predefined exclusion rules. | |
# Default: [] | |
presets: | |
- std-error-handling | |
- common-false-positives | |
# Excluding configuration per-path, per-linter, per-text and per-source. | |
rules: | |
- source: 'TODO' | |
linters: [ godot ] | |
- text: 'should have a package comment' | |
linters: [ revive ] | |
- text: 'exported \S+ \S+ should have comment( \(or a comment on this block\))? or be unexported' | |
linters: [ revive ] | |
- text: 'package comment should be of the form ".+"' | |
source: '// ?(nolint|TODO)' | |
linters: [ revive ] | |
- text: 'comment on exported \S+ \S+ should be of the form ".+"' | |
source: '// ?(nolint|TODO)' | |
linters: [ revive, staticcheck ] | |
- path: '_test\.go' | |
linters: | |
- bodyclose | |
- dupl | |
- errcheck | |
- funlen | |
- goconst | |
- gosec | |
- noctx | |
- wrapcheck |
@k-kurikuri Done
@maratori
Thank you for the quick update with the copyright notice!
Your work is much appreciated.
Hi @maratori, love this config. Just wondering your thoughts on adding flag.Int
to the ignored-functions
for gomnd
? I often find myself adding this in for each project, but I'm unsure if I should be doing this a better way? Thanks
@Broderick-Westrope, thanks for your contribution. I'd appreciate it if you had more ideas on how to improve the config.
I've added functions from the flag
package to the ignored-functions
list. As this is a regexp, it will work for github.com/spf13/pflag
as well.
Note:
Unfortunately, gomnd
uses spelling from the code to match ignored-functions
(see gomd) instead of fully specified names. So the config will not work if you use dot import or import alias. Also, it doesn't work for methods of flag.FlagSet
.
@maratori that's awesome, thankyou.
@maratori possibly another for gomnd
ignored-functions
. I was using the NewWriter
function (Init
also has a similar signature and more documentation) from text/tabwriter
today and I haven't added it to my config yet but I think I will. I'm interested to hear your thoughts (and others) on whether things like formatting tab widths should be stored as a variable or if they are okay to hard code. The suggested changes are below. Thanks.
gomnd:
...
ignored-functions:
...
- tabwriter.NewWriter
- tabwriter.Init
@Broderick-Westrope, I think tabwriter
isn't used frequently. I'd prefer not to add it to the config.
No worries :)
https://github.com/ultraware/funlen
funlen
does not seem to have the option ignore-comments
to ignore counting of lines
Thank you very much for this @maratori ! That's the perfect config for me 👍
gomodguard:
blocked:
modules:
- github.com/gofrs/uuid:
recommendations:
- github.com/google/uuid
reason: "gofrs' package is not go module"
Looks like it is a go module already https://github.com/gofrs/uuid/releases/tag/v5.0.0
@shashkin thanks, removed from the config
@maratori The module is actually referenced as github.com/gofrs/uuid/v5
so I think it would be better to keep it in config but change the recommendation like this
gomodguard:
blocked:
modules:
- github.com/gofrs/uuid:
recommendations:
- github.com/gofrs/uuid/v5
reason: "gofrs' package was not go module before v5"
@shashkin good catch, updated
Hi, first of all thanks for the great work. It looks like https://golangci-lint.run/usage/linters/#perfsprint doesn't accept the strconcat
argument any longer.
gomodguard dont't work with standard library.
depguard work with standard library, for example
deny:
- pkg: $log
desc: "use slog or internal"
@skosovsky do you want me to enable depguard
instead of gomodguard
in this config?
@skosovsky do you want me to enable
depguard
instead ofgomodguard
in this config?
yes, depguard
also has versioning support for external packages, from docs:
A Prefix List just means that a package will match a value, if the value is a prefix of the package. Example github.com/OpenPeeDeeP/depguard package will match a value of github.com/OpenPeeDeeP but won't match github.com/OpenPeeDeeP/depguard/v2.
exportloopref
should disable since Go 1.22 because this problem no longer occurs and fixed by Go team
@chenyanchen thanks, disabled exportloopref
and copyloopvar
@maratori do you think copyloopvar
should be enabled by default? it allows us to clean the codebase where we copy the loop variables like n := n
pre-1.22
@brlala you are right. It was a mistake to disable it. Now, it's enabled.
@maratori long time to see!
Do you think it's finally time to update year in Copyright Notice? :D https://gist.github.com/maratori/47a4d00457a92aa426dbd48a18776322#file-golangci-yml-L2
Jokes aside, what do you think about providing default, maybe commented out, config for tagliatelle
? It's pretty nice linter (unless you need to make something compatible with some weird existing naming schemes). But its default parameters are not so clear to comprehend — I need to remember to change json: "snake"
every damn time. Is my chose optioned? Yes. But let's make it clear on how it can be changed.
WDYT?
Thanks a lot
Very grateful!
Thanks a lot!
it's time to update.
Thanks a lot.
Hi @maratori
I've been using your configuration files from GIST, and I really appreciate your regular updates. I noticed that the files are under the MIT license, but there isn't a full license text or copyright notice.
Would you mind adding the following details to the GIST? It would help make everything clearer for users like me.