diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 1058dd4f..af6f9a91 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -30,9 +30,8 @@ jobs: - name: Get dependencies, run test and static check run: | go test ./... - go vet ./... - go install honnef.co/go/tools/cmd/staticcheck@latest - staticcheck -- $(go list ./...) + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./... - name: Build if: startsWith(github.ref, 'refs/tags/') diff --git a/Makefile b/Makefile index 97328bc2..b6a5b22a 100644 --- a/Makefile +++ b/Makefile @@ -112,5 +112,9 @@ $(zip_releases): %.zip : % all-arch: $(PLATFORM_LIST) $(WINDOWS_ARCH_LIST) releases: $(gz_releases) $(zip_releases) + +lint: + golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./... + clean: rm $(BINDIR)/* diff --git a/adapter/provider/fetcher.go b/adapter/provider/fetcher.go index d3c85ab5..6c1e96b4 100644 --- a/adapter/provider/fetcher.go +++ b/adapter/provider/fetcher.go @@ -12,8 +12,8 @@ import ( ) var ( - fileMode os.FileMode = 0666 - dirMode os.FileMode = 0755 + fileMode os.FileMode = 0o666 + dirMode os.FileMode = 0o755 ) type parser = func([]byte) (interface{}, error) diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index f326d4cc..8a173966 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -10,9 +10,7 @@ import ( types "github.com/Dreamacro/clash/constant/provider" ) -var ( - errVehicleType = errors.New("unsupport vehicle type") -) +var errVehicleType = errors.New("unsupport vehicle type") type healthCheckSchema struct { Enable bool `provider:"enable"` diff --git a/common/cache/lrucache_test.go b/common/cache/lrucache_test.go index 13675bff..8a04f746 100644 --- a/common/cache/lrucache_test.go +++ b/common/cache/lrucache_test.go @@ -149,7 +149,6 @@ func TestSetWithExpire(t *testing.T) { assert.Equal(t, nil, res) assert.Equal(t, time.Time{}, expires) assert.Equal(t, false, exist) - } func TestStale(t *testing.T) { diff --git a/common/murmur3/murmur32.go b/common/murmur3/murmur32.go index 9861eecd..e52b7937 100644 --- a/common/murmur3/murmur32.go +++ b/common/murmur3/murmur32.go @@ -67,7 +67,6 @@ func (d *digest32) bmix(p []byte) (tail []byte) { } func (d *digest32) Sum32() (h1 uint32) { - h1 = d.h1 var k1 uint32 diff --git a/common/observable/observable_test.go b/common/observable/observable_test.go index cb16ad39..b70feec8 100644 --- a/common/observable/observable_test.go +++ b/common/observable/observable_test.go @@ -38,7 +38,7 @@ func TestObservable_MultiSubscribe(t *testing.T) { src := NewObservable(iter) ch1, _ := src.Subscribe() ch2, _ := src.Subscribe() - var count = atomic.NewInt32(0) + count := atomic.NewInt32(0) var wg sync.WaitGroup wg.Add(2) diff --git a/common/pool/alloc.go b/common/pool/alloc.go index 6ae53c1d..710639af 100644 --- a/common/pool/alloc.go +++ b/common/pool/alloc.go @@ -53,6 +53,7 @@ func (alloc *Allocator) Put(buf []byte) error { } //lint:ignore SA6002 ignore temporarily + //nolint alloc.buffers[bits].Put(buf) return nil } diff --git a/common/singledo/singledo_test.go b/common/singledo/singledo_test.go index 2b0d5988..c85795c2 100644 --- a/common/singledo/singledo_test.go +++ b/common/singledo/singledo_test.go @@ -12,7 +12,7 @@ import ( func TestBasic(t *testing.T) { single := NewSingle(time.Millisecond * 30) foo := 0 - var shardCount = atomic.NewInt32(0) + shardCount := atomic.NewInt32(0) call := func() (interface{}, error) { foo++ time.Sleep(time.Millisecond * 5) diff --git a/common/structure/structure_test.go b/common/structure/structure_test.go index 6e3e6290..0feef28e 100644 --- a/common/structure/structure_test.go +++ b/common/structure/structure_test.go @@ -5,8 +5,10 @@ import ( "testing" ) -var decoder = NewDecoder(Option{TagName: "test"}) -var weakTypeDecoder = NewDecoder(Option{TagName: "test", WeaklyTypedInput: true}) +var ( + decoder = NewDecoder(Option{TagName: "test"}) + weakTypeDecoder = NewDecoder(Option{TagName: "test", WeaklyTypedInput: true}) +) type Baz struct { Foo int `test:"foo"` diff --git a/component/dialer/options.go b/component/dialer/options.go index 4b5d64c0..33083864 100644 --- a/component/dialer/options.go +++ b/component/dialer/options.go @@ -1,8 +1,6 @@ package dialer -var ( - DefaultOptions []Option -) +var DefaultOptions []Option type config struct { skipDefault bool diff --git a/component/iface/iface.go b/component/iface/iface.go index 30c6a6bc..4e916260 100644 --- a/component/iface/iface.go +++ b/component/iface/iface.go @@ -15,8 +15,10 @@ type Interface struct { HardwareAddr net.HardwareAddr } -var ErrIfaceNotFound = errors.New("interface not found") -var ErrAddrNotFound = errors.New("addr not found") +var ( + ErrIfaceNotFound = errors.New("interface not found") + ErrAddrNotFound = errors.New("addr not found") +) var interfaces = singledo.NewSingle(time.Second * 20) diff --git a/component/mmdb/mmdb.go b/component/mmdb/mmdb.go index 08743985..e120055d 100644 --- a/component/mmdb/mmdb.go +++ b/component/mmdb/mmdb.go @@ -9,8 +9,10 @@ import ( "github.com/oschwald/geoip2-golang" ) -var mmdb *geoip2.Reader -var once sync.Once +var ( + mmdb *geoip2.Reader + once sync.Once +) func LoadFromBytes(buffer []byte) { once.Do(func() { diff --git a/component/process/process_linux.go b/component/process/process_linux.go index f77c1059..be758a69 100644 --- a/component/process/process_linux.go +++ b/component/process/process_linux.go @@ -25,8 +25,10 @@ var nativeEndian = func() binary.ByteOrder { return binary.LittleEndian }() -type SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error) -type ProcessNameResolver func(inode, uid int) (name string, err error) +type ( + SocketResolver func(network string, ip net.IP, srcPort int) (inode, uid int, err error) + ProcessNameResolver func(inode, uid int) (name string, err error) +) // export for android var ( diff --git a/component/profile/cachefile/cache.go b/component/profile/cachefile/cache.go index a9d1bc5b..03f389a3 100644 --- a/component/profile/cachefile/cache.go +++ b/component/profile/cachefile/cache.go @@ -16,7 +16,7 @@ import ( var ( initOnce sync.Once - fileMode os.FileMode = 0666 + fileMode os.FileMode = 0o666 defaultCache *CacheFile bucketSelected = []byte("selected") @@ -41,7 +41,6 @@ func (c *CacheFile) SetSelected(group, selected string) { } return bucket.Put([]byte(group), []byte(selected)) }) - if err != nil { log.Warnln("[CacheFile] write cache to %s failed: %s", c.db.Path(), err.Error()) return diff --git a/component/profile/profile.go b/component/profile/profile.go index ca9b1b88..e3d9e78c 100644 --- a/component/profile/profile.go +++ b/component/profile/profile.go @@ -4,7 +4,5 @@ import ( "go.uber.org/atomic" ) -var ( - // StoreSelected is a global switch for storing selected proxy to cache - StoreSelected = atomic.NewBool(true) -) +// StoreSelected is a global switch for storing selected proxy to cache +var StoreSelected = atomic.NewBool(true) diff --git a/component/trie/domain.go b/component/trie/domain.go index b4de4a70..ffd0b754 100644 --- a/component/trie/domain.go +++ b/component/trie/domain.go @@ -12,10 +12,8 @@ const ( domainStep = "." ) -var ( - // ErrInvalidDomain means insert domain is invalid - ErrInvalidDomain = errors.New("invalid domain") -) +// ErrInvalidDomain means insert domain is invalid +var ErrInvalidDomain = errors.New("invalid domain") // DomainTrie contains the main logic for adding and searching nodes for domain segments. // support wildcard domain (e.g *.google.com) diff --git a/config/initial.go b/config/initial.go index df8452b9..9d1a2db1 100644 --- a/config/initial.go +++ b/config/initial.go @@ -18,7 +18,7 @@ func downloadMMDB(path string) (err error) { } defer resp.Body.Close() - f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0644) + f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { return err } @@ -54,7 +54,7 @@ func initMMDB() error { func Init(dir string) error { // initial homedir if _, err := os.Stat(dir); os.IsNotExist(err) { - if err := os.MkdirAll(dir, 0777); err != nil { + if err := os.MkdirAll(dir, 0o777); err != nil { return fmt.Errorf("can't create config directory %s: %s", dir, err.Error()) } } @@ -62,7 +62,7 @@ func Init(dir string) error { // initial config.yaml if _, err := os.Stat(C.Path.Config()); os.IsNotExist(err) { log.Infoln("Can't find config, create a initial config file") - f, err := os.OpenFile(C.Path.Config(), os.O_CREATE|os.O_WRONLY, 0644) + f, err := os.OpenFile(C.Path.Config(), os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { return fmt.Errorf("can't create file %s: %s", C.Path.Config(), err.Error()) } diff --git a/dns/filters.go b/dns/filters.go index bacd7727..30825a44 100644 --- a/dns/filters.go +++ b/dns/filters.go @@ -32,6 +32,7 @@ func (inf *ipnetFilter) Match(ip net.IP) bool { type fallbackDomainFilter interface { Match(domain string) bool } + type domainFilter struct { tree *trie.DomainTrie } diff --git a/dns/middleware.go b/dns/middleware.go index 782c0ef0..da84788d 100644 --- a/dns/middleware.go +++ b/dns/middleware.go @@ -14,8 +14,10 @@ import ( D "github.com/miekg/dns" ) -type handler func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error) -type middleware func(next handler) handler +type ( + handler func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error) + middleware func(next handler) handler +) func withHosts(hosts *trie.DomainTrie) middleware { return func(next handler) handler { diff --git a/dns/resolver.go b/dns/resolver.go index 8bbd0e8b..bf544cb9 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -215,7 +215,6 @@ func (r *Resolver) shouldOnlyQueryFallback(m *D.Msg) bool { } func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { - if matched := r.matchPolicy(m); len(matched) != 0 { res := <-r.asyncExchange(ctx, matched, m) return res.Msg, res.Error diff --git a/dns/util.go b/dns/util.go index b167809a..0e1badab 100644 --- a/dns/util.go +++ b/dns/util.go @@ -13,14 +13,12 @@ import ( D "github.com/miekg/dns" ) -var ( - // EnhancedModeMapping is a mapping for EnhancedMode enum - EnhancedModeMapping = map[string]EnhancedMode{ - NORMAL.String(): NORMAL, - FAKEIP.String(): FAKEIP, - MAPPING.String(): MAPPING, - } -) +// EnhancedModeMapping is a mapping for EnhancedMode enum +var EnhancedModeMapping = map[string]EnhancedMode{ + NORMAL.String(): NORMAL, + FAKEIP.String(): FAKEIP, + MAPPING.String(): MAPPING, +} const ( NORMAL EnhancedMode = iota diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 2147906f..ca8ee95d 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -24,9 +24,7 @@ import ( "github.com/Dreamacro/clash/tunnel" ) -var ( - mux sync.Mutex -) +var mux sync.Mutex func readConfig(path string) ([]byte, error) { if _, err := os.Stat(path); os.IsNotExist(err) { diff --git a/listener/auth/auth.go b/listener/auth/auth.go index 2c29e186..70473114 100644 --- a/listener/auth/auth.go +++ b/listener/auth/auth.go @@ -4,9 +4,7 @@ import ( "github.com/Dreamacro/clash/component/auth" ) -var ( - authenticator auth.Authenticator -) +var authenticator auth.Authenticator func Authenticator() auth.Authenticator { return authenticator diff --git a/log/level.go b/log/level.go index ea223c12..f70116a3 100644 --- a/log/level.go +++ b/log/level.go @@ -5,16 +5,14 @@ import ( "errors" ) -var ( - // LogLevelMapping is a mapping for LogLevel enum - LogLevelMapping = map[string]LogLevel{ - ERROR.String(): ERROR, - WARNING.String(): WARNING, - INFO.String(): INFO, - DEBUG.String(): DEBUG, - SILENT.String(): SILENT, - } -) +// LogLevelMapping is a mapping for LogLevel enum +var LogLevelMapping = map[string]LogLevel{ + ERROR.String(): ERROR, + WARNING.String(): WARNING, + INFO.String(): INFO, + DEBUG.String(): DEBUG, + SILENT.String(): SILENT, +} const ( DEBUG LogLevel = iota diff --git a/transport/gun/gun.go b/transport/gun/gun.go index e60d13d7..f6f76116 100644 --- a/transport/gun/gun.go +++ b/transport/gun/gun.go @@ -27,12 +27,10 @@ var ( ErrSmallBuffer = errors.New("buffer too small") ) -var ( - defaultHeader = http.Header{ - "content-type": []string{"application/grpc"}, - "user-agent": []string{"grpc-go/1.36.0"}, - } -) +var defaultHeader = http.Header{ + "content-type": []string{"application/grpc"}, + "user-agent": []string{"grpc-go/1.36.0"}, +} type DialFn = func(network, addr string) (net.Conn, error) diff --git a/transport/simple-obfs/tls.go b/transport/simple-obfs/tls.go index 914cfe4a..1c609c15 100644 --- a/transport/simple-obfs/tls.go +++ b/transport/simple-obfs/tls.go @@ -78,6 +78,7 @@ func (to *TLSObfs) Read(b []byte) (int, error) { // type + ver = 3 return to.read(b, 3) } + func (to *TLSObfs) Write(b []byte) (int, error) { length := len(b) for i := 0; i < length; i += chunkSize { diff --git a/transport/snell/cipher.go b/transport/snell/cipher.go index f778e647..0f31aea5 100644 --- a/transport/snell/cipher.go +++ b/transport/snell/cipher.go @@ -20,6 +20,7 @@ func (sc *snellCipher) SaltSize() int { return 16 } func (sc *snellCipher) Encrypter(salt []byte) (cipher.AEAD, error) { return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize())) } + func (sc *snellCipher) Decrypter(salt []byte) (cipher.AEAD, error) { return sc.makeAEAD(snellKDF(sc.psk, salt, sc.KeySize())) } diff --git a/transport/snell/snell.go b/transport/snell/snell.go index 8966b4bb..64807b81 100644 --- a/transport/snell/snell.go +++ b/transport/snell/snell.go @@ -30,9 +30,7 @@ const ( Version byte = 1 ) -var ( - endSignal = []byte{} -) +var endSignal = []byte{} type Snell struct { net.Conn diff --git a/transport/socks4/socks4.go b/transport/socks4/socks4.go index c06bea20..a2941624 100644 --- a/transport/socks4/socks4.go +++ b/transport/socks4/socks4.go @@ -184,7 +184,7 @@ func isReservedIP(ip net.IP) bool { } func readUntilNull(r io.Reader) ([]byte, error) { - var buf = &bytes.Buffer{} + buf := &bytes.Buffer{} var data [1]byte for { diff --git a/transport/ssr/protocol/auth_aes128_sha1.go b/transport/ssr/protocol/auth_aes128_sha1.go index fab9d008..8ce57d28 100644 --- a/transport/ssr/protocol/auth_aes128_sha1.go +++ b/transport/ssr/protocol/auth_aes128_sha1.go @@ -14,8 +14,10 @@ import ( "github.com/Dreamacro/clash/transport/ssr/tools" ) -type hmacMethod func(key, data []byte) []byte -type hashDigestMethod func([]byte) []byte +type ( + hmacMethod func(key, data []byte) []byte + hashDigestMethod func([]byte) []byte +) func init() { register("auth_aes128_sha1", newAuthAES128SHA1, 9) diff --git a/transport/vmess/header.go b/transport/vmess/header.go index 27a734be..67d407e6 100644 --- a/transport/vmess/header.go +++ b/transport/vmess/header.go @@ -92,7 +92,7 @@ func sealVMessAEADHeader(key [16]byte, data []byte, t time.Time) []byte { payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:]) } - var outputBuffer = &bytes.Buffer{} + outputBuffer := &bytes.Buffer{} outputBuffer.Write(generatedAuthID[:]) outputBuffer.Write(payloadHeaderLengthAEADEncrypted) diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index f00e4c4b..951fb5d0 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -28,6 +28,7 @@ type websocketConn struct { rMux sync.Mutex wMux sync.Mutex } + type websocketWithEarlyDataConn struct { net.Conn underlay net.Conn diff --git a/tunnel/mode.go b/tunnel/mode.go index 6e07a060..69660721 100644 --- a/tunnel/mode.go +++ b/tunnel/mode.go @@ -8,14 +8,12 @@ import ( type TunnelMode int -var ( - // ModeMapping is a mapping for Mode enum - ModeMapping = map[string]TunnelMode{ - Global.String(): Global, - Rule.String(): Rule, - Direct.String(): Direct, - } -) +// ModeMapping is a mapping for Mode enum +var ModeMapping = map[string]TunnelMode{ + Global.String(): Global, + Rule.String(): Rule, + Direct.String(): Direct, +} const ( Global TunnelMode = iota