در اکثر مواقع استفاده از لینترها در هر زبانی میتونه از جنبههای مختلف کمک زیادی برای بهبود کدها انجام بدن اما هنوز هم دولوپرها بخوبی باهاشون آشتی نکردن.
لینترها با هزینه پایین، میتونن کدها رو از جنبههای مختلفی بررسی کنن و خب لینترهای گولنگی هم از این قاعده مستثنی نیستند.
لینترهای گولنگی میتونن بهمون کمک کنن:
- فیلدهای یک struct طوری بچینیم که با ساختار memory سازگارتر باشه و مموری فوتپرینت رو کمتر کنیم
- هر زمان که فراموش کردیم یه خطا رو بهدرستی لاگ یا wrap کنیم بهمون اخطار بدن
- کدهای duplicate رو تشخیص بدن
- اجازه ندن هر dependency در هرجایی ایمپورت بشه
- از هاردکدها و مجیک نامبرها جلوگیری میکنن
- برای ifهای بیش از اندازه توو در توو نمره منفی میذارن
- و حتی میشه اجازه ندیم بعضی مواقع اسلایسی بدون ظرفیت مناسب تعریف بشه
- و…
اما احساس میکنم یکی از مهمترین قابلیتهای لینترها ایجاد یک چارچوب مشخص برای نوشتن کدها در هنگام توسعه تیمی و در فرآیندهای مختلفی مثل CI هست. وقتی تیمی کار میکنید بیش از هر زمان دیگهای نسبت به رعایت یک سری قوانین مشخص احساس نیاز میشه که خب میتونه با استفاده از لینترها دقیقتر پیاده بشه.
خب golangci-lint یکی از ابزارهاییه که به سادگی به ما اجازه میده مجموعهای از لینترهای محبوب مثل revive و… رو ترکیب کنیم و یه فایل چارچوب کدنویسی متناسب با پروژه و تیممون درست کنیم. فقط کافیه golangci-lint رو نصب و یه فایل yml یا json که شامل ruleها میشه براش بنویسیم.
یه نمونه فایل کانفیگ ساده رو اینجا میذارم، شاید دوست داشتین تست کنید:
linters-settings:
asasalint: # will prevent any function for having "...any" variadic parameter except log funcs
exclude:
- \.Debugf
- \.Infof
- \.Warnf
- \.Errorf
- \.Fatalf
ignore-test: true
errcheck:
check-type-assertions: true
gocyclo:
min-complexity: 5
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 3
ignore-tests: true
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
gomnd:
checks:
- argument
- case
- condition
- operation
- return
- assign
ignored-numbers:
- '0666' # will ignore hard coded numbers which are permission codes, but a better approach is using octal number e.g: 0o666 and remove this section
- '0755'
ignored-functions:
- '^math\.' # will ignore hard coded numbers which are used alongside math, e.g: math.rand() * 2
govet:
check-shadowing: true
enable:
- fieldalignment
- nilfunc
- nilness
revive:
severity: error
enable-all-rules: true
confidence: 0.8
rules:
- name: unused-parameter
severity: warning
disabled: false
# arguments:
# - allowRegex: "." # use regex to allow an unused-parameter when you need, e.g: (tx *gorm.DB) in gorm hooks
- name: unused-receiver
severity: warning
disabled: false
# arguments:
# - allowRegex: "." # use regex to allow an unused-receiver when you need
- name: line-length-limit # will check for line length but you have to enable it
severity: warning
disabled: true
arguments: [80] # pass a desired number for each line length restriction
- name: unchecked-type-assertion
severity: warning
disabled: true
- name: add-constant
severity: warning
disabled: false
arguments:
- maxLitCount: "5"
allowStrs: '""'
allowInts: "0,1,2,3,4"
- name: cognitive-complexity # will check for code complexity and every if, else, ||, & and ! charactars will add to complexity score
severity: warning
disabled: true
arguments: [10] # pass a desired number for complexity score, smaller numbers means more restrictions for using if, else, ||, & and ! chars
nolintlint:
require-explanation: true
require-specific: true
depguard: # will check dependencies and imported packages with defined rules
rules:
main:
files:
- "!**/*_a _file.go"
allow:
- $gostd
- github.com/example
deny:
- pkg: "github.com/pkg/example"
desc: should be replaced by blah blah package
linters:
disable-all: true
enable:
- asasalint
- cyclop
# - depguard # if enabled, will check dependencies and imported packages with above rules
- dupl
- errcheck
# - errorlint # if enabled, will check for wrapping errors and error type assertions without ,ok idioms
- exhaustive
- goconst
- gocritic
# - godox # if enabled, will check codes for finding "todos", "bug" and "fixme" pharses
- gocyclo
- gomnd
- gosimple
- gosec
- govet
- misspell
- musttag
- perfsprint
- prealloc
- predeclared
- usestdlibvars
- whitespace
- wsl
- revive
- bodyclose
- exportloopref
- ineffassign
- nolintlint
- stylecheck
- unconvert
run:
issues-exit-code: 1
issues:
exclude-rules:
- path: _test\.go
linters:
- gocyclo
- gosec
- dupl