Skip to content

Instantly share code, notes, and snippets.

Created March 28, 2023 07:01
Show Gist options
  • Save cristaloleg/f1610a9ca73ac420cda170fadd21b944 to your computer and use it in GitHub Desktop.
Save cristaloleg/f1610a9ca73ac420cda170fadd21b944 to your computer and use it in GitHub Desktop.
Go linters configuration, the right version.
# See:
# Depends on your hardware, my laptop can survive 8 threads.
concurrency: 8
# I really care about the result, so I'm fine to wait for it.
timeout: 30m
# Fail if the error was met.
issues-exit-code: 1
# This is very important, bugs in tests are not acceptable either.
tests: true
# In most cases this can be empty but there is a popular pattern
# to keep integration tests under this tag. Such tests often require
# additional setups like Postgres, Redis etc and are run separately.
# (to be honest I don't find this useful but I have such tags)
- integration
# Up to you, good for a big enough repo with no-Go code.
# - src/external_libs
# When enabled linter will skip directories: vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
# Skipping `examples` sounds scary to me but skipping `testdata` sounds ok.
skip-dirs-use-default: false
# Autogenerated files can be skipped (I'm looking at you gRPC).
# AFAIK autogen files are skipped but skipping the whole directory should be somewhat faster.
# - "protobuf/.*.go"
# With the read-only mode linter will fail if go.mod file is outdated.
modules-download-mode: readonly
# Till today I didn't know this param exists, never ran 2 golangci-lint at once.
allow-parallel-runners: false
# Keep this empty to use the Go version from the go.mod file.
go: ""
# Set to true runs only fast linters.
# Good option for 'lint on save', pre-commit hook or CI.
fast: false
# Check for pass []any as any in variadic func(...any).
# Rare case but saved me from debugging a few times.
- asasalint
# I prefer plane ASCII identifiers.
# Symbol `∆` instead of `delta` looks cool but no thanks.
- asciicheck
# Checks for dangerous unicode character sequences.
# Super rare but why not to be a bit paranoid?
- bidichk
# Checks whether HTTP response body is closed successfully.
- bodyclose
# Check whether the function uses a non-inherited context.
- contextcheck
# Check for two durations multiplied together.
- durationcheck
# Forces to not skip error check.
- errcheck
# Checks `Err-` prefix for var and `-Error` suffix for error type.
- errname
# Suggests to use `%w` for error-wrapping.
- errorlint
# Checks for pointers to enclosing loop variables.
- exportloopref
# As you already know I'm a co-author. It would be strange to not use
# one of my warmly loved projects.
- gocritic
# Forces to put `.` at the end of the comment. Code is poetry.
- godot
# Might not be that important but I prefer to keep all of them.
# `gofumpt` is amazing, kudos to Daniel Marti
- gofmt
- gofumpt
- goimports
# Allow or ban replace directives in go.mod
# or force explanation for retract directives.
- gomoddirectives
# Powerful security-oriented linter. But requires some time to
# configure it properly, see
- gosec
# Linter that specializes in simplifying code.
- gosimple
# Official Go tool. Must have.
- govet
# Detects when assignments to existing variables are not used
# Last week I caught a bug with it.
- ineffassign
# Even with deprecation notice I find it useful.
# There are situations when instead of io.ReaderCloser
# I can use io.Reader. A small but good improvement.
- interfacer
# Fix all the misspells, amazing thing.
- misspell
# Finds naked/bare returns and requires change them.
- nakedret
# Both require a bit more explicit returns.
- nilerr
- nilnil
# Finds sending HTTP request without context.Context.
- noctx
# Forces comment why another check is disabled.
# Better not to have //nolint: at all ;)
- nolintlint
# Finds slices that could potentially be pre-allocated.
# Small performance win + cleaner code.
- prealloc
# Finds shadowing of Go's predeclared identifiers.
# I hear a lot of complaints from junior developers.
# But after some time they find it very useful.
- predeclared
# Lint your Prometheus metrics name.
- promlinter
# Checks that package variables are not reassigned.
# Super rare case but can catch bad things (like `io.EOF = nil`)
- reassign
# Drop-in replacement of `golint`.
- revive
# Somewhat similar to `bodyclose` but for `database/sql` package.
- rowserrcheck
- sqlclosecheck
# I have found that it's not the same as staticcheck binary :\
- staticcheck
# Is a replacement for `golint`, similar to `revive`.
- stylecheck
# Check struct tags.
- tagliatelle
# Test-related checks. All of them are good.
- tenv
- testableexamples
- thelper
- tparallel
# Remove unnecessary type conversions, make code cleaner
- unconvert
# Might be noisy but better to know what is unused
- unparam
# Must have. Finds unused declarations.
- unused
# Detect the possibility to use variables/constants from stdlib.
- usestdlibvars
# Finds wasted assignment statements.
- wastedassign
# Detects struct contained context.Context field. Not a problem.
- containedctx
# Checks function and package cyclomatic complexity.
# I can have a long but trivial switch-case.
# Cyclomatic complexity is a measurement, not a goal.
# (c) Bryan C. Mills /
- cyclop
# Abandoned, replaced by `unused`.
- deadcode
# Check declaration order of types, consts, vars and funcs.
# I like it but I don't use it.
- decorder
# Checks if package imports are in a list of acceptable packages.
# I'm very picky about what I import, so no automation.
- depguard
# Checks assignments with too many blank identifiers. Very rare.
- dogsled
# Tool for code clone detection.
- dupl
# Find duplicate words, rare.
- dupword
# I'm fine to check the error from json.Marshal ¯\_(ツ)_/¯
- errchkjson
# All SQL queries MUST BE covered with tests.
- execinquery
# Forces to handle more cases. Cool but noisy.
- exhaustive
- exhaustivestruct # Deprecated, replaced by check below.
- exhaustruct
# Forbids some identifiers. I don't have a case for it.
- forbidigo
# Finds forced type assertions, very good for juniors.
- forcetypeassert
# I might have long but a simple function.
- funlen
# Imports order. I do this manually ¯\_(ツ)_/¯
- gci
# I'm not a fan of ginkgo and gomega packages.
- ginkgolinter
# Checks that compiler directive comments (//go:) are valid. Rare.
- gocheckcompilerdirectives
# Globals and init() are ok.
- gochecknoglobals
- gochecknoinits
# Same as `cyclop` linter (see above)
- gocognit
- goconst
- gocyclo
# TODO and friends are ok.
- godox
# Check the error handling expressions. Too noisy.
- goerr113
# I don't use file headers.
- goheader
# 1st Go linter, deprecated :( use `revive`.
- golint
# Reports magic consts. Might be noisy but still good.
- gomnd
# Allowed/blocked packages to import. I prefer to do it manually.
- gomodguard
# Printf-like functions must have -f.
- goprintffuncname
# Groupt declarations, I prefer manually.
- grouper
# Deprecated.
- ifshort
# Checks imports aliases, rare.
- importas
# Forces tiny interfaces, very subjective.
- interfacebloat
# Accept interfaces, return types. Not always.
- ireturn
# I don't set line length. 120 is fine by the way ;)
- lll
# Some log checkers, might be useful.
- loggercheck
# Maintainability index of each function, subjective.
- maintidx
# Slice declarations with non-zero initial length. Not my case.
- makezero
# Deprecated. Use govet `fieldalignment`.
- maligned
# Enforce tags in un/marshaled structs. Cool but not my case.
- musttag
# Deeply nested if statements, subjective.
- nestif
# Forces newlines in some places.
- nlreturn
# Reports all named returns, not that bad.
- nonamedreturns
# Deprecated. Replaced by `revive`.
- nosnakecase
# Finds misuse of Sprintf with host:port in a URL. Cool but rare.
- nosprintfhostport
# I don't use t.Parallel() that much.
- paralleltest
# Often non-`_test` package is ok.
- testpackage
# Compiler can do it too :)
- typecheck
# I'm fine with long variable names with a small scope.
- varnamelen
# gofmt,gofumpt covers that (from what I know).
- whitespace
# Don't find it useful to wrap all errors from external packages.
- wrapcheck
# Forces you to use empty lines. Great if configured correctly.
# I mean there is an agreement in a team.
- wsl
# I'm biased and I'm enabling more than 100 checks
# Might be too much for you. See
- diagnostic
- experimental
- opinionated
- performance
- style
# These 3 will detect many cases, but they do sense
# if it's performance oriented code
- hugeParam
- rangeExprCopy
- rangeValCopy
# Report `a := b.(MyStruct)` when `a, ok := ...` should be.
check-type-assertions: true # Default: false
# Report skipped checks:`num, _ := strconv.Atoi(numStr)`.
check-blank: true # Default: false
# Function to skip.
- io/ioutil.ReadFile
- io.Copy(*bytes.Buffer)
- io.Copy(os.Stdout)
- fieldalignment # I'm ok to waste some bytes
# No naked returns, ever.
max-func-lines: 1 # Default: 30
json: snake # why it's not a `snake` by default?!
yaml: snake # why it's not a `snake` by default?!
xml: camel
bson: camel
avro: snake
mapstructure: kebab
# See also
# I prefer the simplest one: `line-number` and saving to `lint.txt`
# The `tab` also looks good and with the next release I will switch to it
# (ref:
# There are more formats which can be used on CI or by your IDE.
format: line-number:lint.txt
# I do not find this useful, parameter above already enables filepath
# with a line and column. For me, it's easier to follow the path and
# see the line in an IDE where I see more code and understand it better.
print-issued-lines: false
# Must have. Easier to understand the output.
print-linter-name: true
# No, no skips, everything should be reported.
uniq-by-line: false
# To be honest no idea when this can be needed, maybe a multi-module setup?
path-prefix: ""
# Slightly easier to follow the results + getting deterministic output.
sort-results: true
# I found it strange to skip the errors, setting 0 to have all the results.
max-issues-per-linter: 0
# Same here, nothing should be skipped to not miss errors.
max-same-issues: 0
# When set to `true` linter will analyze only new code which are
# not committed or after some specific revision. This is a cool
# feature when you're going to introduce linter into a big project.
# But I prefer going gradually package by package.
# So, it's set to `false` to scan all code.
new: false
# 2 other params regarding git integration
# Even with a recent GPT-4 release I still believe that
# I know better how to do my job and fix the suggestions.
fix: false
Copy link

Why tagliatelle?

Copy link

why not?

Copy link

You are right, unified style are important in one project or a team.

I want to known why json default is caml, you give the snake, did there have any guidelines?

Copy link

In wild world snake_case is more popular (in JS/TS and as a result JSON ecosystem). That's why most of the JSON that I met in my life are snake-cased.

However, that's not a rule or a guideline, more like an observation. Both are fine (JSON spec don't mention this either)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment