diff --git a/.golangci.yaml b/.golangci.yaml index efe91527..a0764585 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -2,7 +2,7 @@ linters: disable-all: true enable: - gofumpt - - megacheck + - staticcheck - govet - gci @@ -12,3 +12,5 @@ linters-settings: - standard - prefix(github.com/Dreamacro/clash) - default + staticcheck: + go: '1.18' diff --git a/Makefile b/Makefile index 30fc023e..9004a660 100644 --- a/Makefile +++ b/Makefile @@ -41,10 +41,10 @@ all:linux-amd64\ linux-mips-hardfloat linux-mips-softfloat linux-mips64 linux-mips64le linux-mipsle-hardfloat linux-mipsle-softfloat# Most used docker: - $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ + GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ darwin-amd64: - GOARCH=amd64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ + GOARCH=amd64 GOOS=darwin GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ darwin-arm64: GOARCH=arm64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ @@ -53,7 +53,7 @@ linux-386: GOARCH=386 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ linux-amd64: - GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ + GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ linux-amd64-AutoIptables: GOARCH=amd64 GOOS=linux $(GOBUILDOP) -o $(BINDIR)/$(NAME)-$@ @@ -98,7 +98,7 @@ freebsd-386: GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ freebsd-amd64: - GOARCH=amd64 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ + GOARCH=amd64 GOOS=freebsd GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ freebsd-arm64: GOARCH=arm64 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ @@ -107,7 +107,7 @@ windows-386: GOARCH=386 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe windows-amd64: - GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe + GOARCH=amd64 GOOS=windows GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe windows-arm64: GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe diff --git a/adapter/adapter.go b/adapter/adapter.go index 0b10fae7..9b1a4fb3 100644 --- a/adapter/adapter.go +++ b/adapter/adapter.go @@ -93,7 +93,7 @@ func (p *Proxy) MarshalJSON() ([]byte, error) { return inner, err } - mapping := map[string]interface{}{} + mapping := map[string]any{} json.Unmarshal(inner, &mapping) mapping["history"] = p.DelayHistory() mapping["name"] = p.Name() diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 5e5ebd7c..71b4ae5e 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -29,14 +29,14 @@ type ShadowSocks struct { type ShadowSocksOption struct { BasicOption - Name string `proxy:"name"` - Server string `proxy:"server"` - Port int `proxy:"port"` - Password string `proxy:"password"` - Cipher string `proxy:"cipher"` - UDP bool `proxy:"udp,omitempty"` - Plugin string `proxy:"plugin,omitempty"` - PluginOpts map[string]interface{} `proxy:"plugin-opts,omitempty"` + Name string `proxy:"name"` + Server string `proxy:"server"` + Port int `proxy:"port"` + Password string `proxy:"password"` + Cipher string `proxy:"cipher"` + UDP bool `proxy:"udp,omitempty"` + Plugin string `proxy:"plugin,omitempty"` + PluginOpts map[string]any `proxy:"plugin-opts,omitempty"` } type simpleObfsOption struct { diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index 16791836..d90922ea 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -23,13 +23,13 @@ type Snell struct { type SnellOption struct { BasicOption - Name string `proxy:"name"` - Server string `proxy:"server"` - Port int `proxy:"port"` - Psk string `proxy:"psk"` - UDP bool `proxy:"udp,omitempty"` - Version int `proxy:"version,omitempty"` - ObfsOpts map[string]interface{} `proxy:"obfs-opts,omitempty"` + Name string `proxy:"name"` + Server string `proxy:"server"` + Port int `proxy:"port"` + Psk string `proxy:"psk"` + UDP bool `proxy:"udp,omitempty"` + Version int `proxy:"version,omitempty"` + ObfsOpts map[string]any `proxy:"obfs-opts,omitempty"` } type streamOption struct { diff --git a/adapter/outboundgroup/fallback.go b/adapter/outboundgroup/fallback.go index b795229b..caf4fb5e 100644 --- a/adapter/outboundgroup/fallback.go +++ b/adapter/outboundgroup/fallback.go @@ -97,12 +97,11 @@ func (f *Fallback) SupportUDP() bool { // MarshalJSON implements C.ProxyAdapter func (f *Fallback) MarshalJSON() ([]byte, error) { - all := make([]string, 0) + var all []string for _, proxy := range f.proxies(false) { all = append(all, proxy.Name()) } - - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "type": f.Type().String(), "now": f.Now(), "all": all, @@ -116,8 +115,8 @@ func (f *Fallback) Unwrap(metadata *C.Metadata) C.Proxy { } func (f *Fallback) proxies(touch bool) []C.Proxy { - elm, _, _ := f.single.Do(func() (interface{}, error) { - return getProvidersProxies(f.providers, touch, f.filter), nil + elm, _, _ := f.single.Do(func() (any, error) { + return getProvidersProxies(f.providers, touch), nil }) return elm.([]C.Proxy) diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index 402062c8..0a4dce9c 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -30,7 +30,7 @@ type LoadBalance struct { var errStrategy = errors.New("unsupported strategy") -func parseStrategy(config map[string]interface{}) string { +func parseStrategy(config map[string]any) string { if elm, ok := config["strategy"]; ok { if strategy, ok := elm.(string); ok { return strategy @@ -141,7 +141,7 @@ func (lb *LoadBalance) Unwrap(metadata *C.Metadata) C.Proxy { } func (lb *LoadBalance) proxies(touch bool) []C.Proxy { - elm, _, _ := lb.single.Do(func() (interface{}, error) { + elm, _, _ := lb.single.Do(func() (any, error) { return getProvidersProxies(lb.providers, touch, lb.filter), nil }) @@ -150,13 +150,11 @@ func (lb *LoadBalance) proxies(touch bool) []C.Proxy { // MarshalJSON implements C.ProxyAdapter func (lb *LoadBalance) MarshalJSON() ([]byte, error) { - all := make([]string, 0) - + var all []string for _, proxy := range lb.proxies(false) { all = append(all, proxy.Name()) } - - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "type": lb.Type().String(), "all": all, }) diff --git a/adapter/outboundgroup/parser.go b/adapter/outboundgroup/parser.go index 575d8b93..6fda4af7 100644 --- a/adapter/outboundgroup/parser.go +++ b/adapter/outboundgroup/parser.go @@ -32,7 +32,7 @@ type GroupCommonOption struct { Filter string `group:"filter,omitempty"` } -func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy, providersMap map[string]types.ProxyProvider) (C.ProxyAdapter, error) { +func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, providersMap map[string]types.ProxyProvider) (C.ProxyAdapter, error) { decoder := structure.NewDecoder(structure.Option{TagName: "group", WeaklyTypedInput: true}) groupOption := &GroupCommonOption{ diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index f794afe3..f75bd336 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -69,20 +69,18 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d // MarshalJSON implements C.ProxyAdapter func (r *Relay) MarshalJSON() ([]byte, error) { - all := make([]string, 0) - + var all []string for _, proxy := range r.rawProxies(false) { all = append(all, proxy.Name()) } - - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "type": r.Type().String(), "all": all, }) } func (r *Relay) rawProxies(touch bool) []C.Proxy { - elm, _, _ := r.single.Do(func() (interface{}, error) { + elm, _, _ := r.single.Do(func() (any, error) { return getProvidersProxies(r.providers, touch, r.filter), nil }) diff --git a/adapter/outboundgroup/selector.go b/adapter/outboundgroup/selector.go index 909050bf..11fc076a 100644 --- a/adapter/outboundgroup/selector.go +++ b/adapter/outboundgroup/selector.go @@ -50,13 +50,12 @@ func (s *Selector) SupportUDP() bool { // MarshalJSON implements C.ProxyAdapter func (s *Selector) MarshalJSON() ([]byte, error) { - all := make([]string, 0) - + var all []string for _, proxy := range getProvidersProxies(s.providers, false, s.filter) { all = append(all, proxy.Name()) } - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "type": s.Type().String(), "now": s.Now(), "all": all, @@ -85,7 +84,7 @@ func (s *Selector) Unwrap(metadata *C.Metadata) C.Proxy { } func (s *Selector) selectedProxy(touch bool) C.Proxy { - elm, _, _ := s.single.Do(func() (interface{}, error) { + elm, _, _ := s.single.Do(func() (any, error) { proxies := getProvidersProxies(s.providers, touch, s.filter) for _, proxy := range proxies { if proxy.Name() == s.selected { diff --git a/adapter/outboundgroup/urltest.go b/adapter/outboundgroup/urltest.go index 28a9fe40..67f7ce1b 100644 --- a/adapter/outboundgroup/urltest.go +++ b/adapter/outboundgroup/urltest.go @@ -49,7 +49,6 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata, opts .. } else { u.onDialFailed() } - return c, err } @@ -63,7 +62,6 @@ func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata, } else { u.onDialFailed() } - return pc, err } @@ -73,7 +71,7 @@ func (u *URLTest) Unwrap(metadata *C.Metadata) C.Proxy { } func (u *URLTest) proxies(touch bool) []C.Proxy { - elm, _, _ := u.single.Do(func() (interface{}, error) { + elm, _, _ := u.single.Do(func() (any, error) { return getProvidersProxies(u.providers, touch, u.filter), nil }) @@ -81,7 +79,7 @@ func (u *URLTest) proxies(touch bool) []C.Proxy { } func (u *URLTest) fast(touch bool) C.Proxy { - elm, _, _ := u.fastSingle.Do(func() (interface{}, error) { + elm, _, _ := u.fastSingle.Do(func() (any, error) { proxies := u.proxies(touch) fast := proxies[0] min := fast.LastDelay() @@ -125,13 +123,11 @@ func (u *URLTest) SupportUDP() bool { // MarshalJSON implements C.ProxyAdapter func (u *URLTest) MarshalJSON() ([]byte, error) { - all := make([]string, 0) - + var all []string for _, proxy := range u.proxies(false) { all = append(all, proxy.Name()) } - - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "type": u.Type().String(), "now": u.Now(), "all": all, @@ -164,7 +160,7 @@ func (u *URLTest) onDialFailed() { } } -func parseURLTestOption(config map[string]interface{}) []urlTestOption { +func parseURLTestOption(config map[string]any) []urlTestOption { opts := []urlTestOption{} // tolerance diff --git a/adapter/parser.go b/adapter/parser.go index 70f589e4..13701bc3 100644 --- a/adapter/parser.go +++ b/adapter/parser.go @@ -8,7 +8,7 @@ import ( C "github.com/Dreamacro/clash/constant" ) -func ParseProxy(mapping map[string]interface{}) (C.Proxy, error) { +func ParseProxy(mapping map[string]any) (C.Proxy, error) { decoder := structure.NewDecoder(structure.Option{TagName: "proxy", WeaklyTypedInput: true}) proxyType, existType := mapping["type"].(string) if !existType { diff --git a/adapter/provider/fetcher.go b/adapter/provider/fetcher.go index 81f9ec96..4a7be8b1 100644 --- a/adapter/provider/fetcher.go +++ b/adapter/provider/fetcher.go @@ -16,7 +16,7 @@ var ( dirMode os.FileMode = 0o755 ) -type parser = func([]byte) (interface{}, error) +type parser = func([]byte) (any, error) type fetcher struct { name string @@ -26,7 +26,7 @@ type fetcher struct { done chan struct{} hash [16]byte parser parser - onUpdate func(interface{}) + onUpdate func(any) } func (f *fetcher) Name() string { @@ -37,7 +37,7 @@ func (f *fetcher) VehicleType() types.VehicleType { return f.vehicle.Type() } -func (f *fetcher) Initial() (interface{}, error) { +func (f *fetcher) Initial() (any, error) { var ( buf []byte err error @@ -92,7 +92,7 @@ func (f *fetcher) Initial() (interface{}, error) { return proxies, nil } -func (f *fetcher) Update() (interface{}, bool, error) { +func (f *fetcher) Update() (any, bool, error) { buf, err := f.vehicle.Read() if err != nil { return nil, false, err @@ -168,7 +168,7 @@ func safeWrite(path string, buf []byte) error { return os.WriteFile(path, buf, fileMode) } -func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(interface{})) *fetcher { +func newFetcher(name string, interval time.Duration, vehicle types.Vehicle, parser parser, onUpdate func(any)) *fetcher { var ticker *time.Ticker if interval != 0 { ticker = time.NewTicker(interval) diff --git a/adapter/provider/healthcheck.go b/adapter/provider/healthcheck.go index f41a4788..7a89ffa3 100644 --- a/adapter/provider/healthcheck.go +++ b/adapter/provider/healthcheck.go @@ -62,7 +62,7 @@ func (hc *HealthCheck) check() { b, _ := batch.New(context.Background(), batch.WithConcurrencyNum(10)) for _, proxy := range hc.proxies { p := proxy - b.Go(p.Name(), func() (interface{}, error) { + b.Go(p.Name(), func() (any, error) { ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) defer cancel() p.URLTest(ctx, hc.url) diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index d91aa4a1..887ac5cd 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -28,7 +28,7 @@ type proxyProviderSchema struct { HealthCheck healthCheckSchema `provider:"health-check,omitempty"` } -func ParseProxyProvider(name string, mapping map[string]interface{}) (types.ProxyProvider, error) { +func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvider, error) { decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true}) schema := &proxyProviderSchema{ diff --git a/adapter/provider/provider.go b/adapter/provider/provider.go index e3da2c3a..30f8d61b 100644 --- a/adapter/provider/provider.go +++ b/adapter/provider/provider.go @@ -20,7 +20,7 @@ const ( ) type ProxySchema struct { - Proxies []map[string]interface{} `yaml:"proxies"` + Proxies []map[string]any `yaml:"proxies"` } // for auto gc @@ -35,7 +35,7 @@ type proxySetProvider struct { } func (pp *proxySetProvider) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "name": pp.Name(), "type": pp.Type().String(), "vehicleType": pp.VehicleType().String(), @@ -112,12 +112,12 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, veh healthCheck: hc, } - onUpdate := func(elm interface{}) { + onUpdate := func(elm any) { ret := elm.([]C.Proxy) pd.setProxies(ret) } - proxiesParseAndFilter := func(buf []byte) (interface{}, error) { + proxiesParseAndFilter := func(buf []byte) (any, error) { schema := &ProxySchema{} if err := yaml.Unmarshal(buf, schema); err != nil { @@ -172,7 +172,7 @@ type compatibleProvider struct { } func (cp *compatibleProvider) MarshalJSON() ([]byte, error) { - return json.Marshal(map[string]interface{}{ + return json.Marshal(map[string]any{ "name": cp.Name(), "type": cp.Type().String(), "vehicleType": cp.VehicleType().String(), diff --git a/common/batch/batch.go b/common/batch/batch.go index ce20ed61..f0085215 100644 --- a/common/batch/batch.go +++ b/common/batch/batch.go @@ -8,7 +8,7 @@ import ( type Option = func(b *Batch) type Result struct { - Value interface{} + Value any Err error } @@ -38,7 +38,7 @@ type Batch struct { cancel func() } -func (b *Batch) Go(key string, fn func() (interface{}, error)) { +func (b *Batch) Go(key string, fn func() (any, error)) { b.wg.Add(1) go func() { defer b.wg.Done() diff --git a/common/batch/batch_test.go b/common/batch/batch_test.go index 9465dbad..4e44158c 100644 --- a/common/batch/batch_test.go +++ b/common/batch/batch_test.go @@ -14,11 +14,11 @@ func TestBatch(t *testing.T) { b, _ := New(context.Background()) now := time.Now() - b.Go("foo", func() (interface{}, error) { + b.Go("foo", func() (any, error) { time.Sleep(time.Millisecond * 100) return "foo", nil }) - b.Go("bar", func() (interface{}, error) { + b.Go("bar", func() (any, error) { time.Sleep(time.Millisecond * 150) return "bar", nil }) @@ -45,7 +45,7 @@ func TestBatchWithConcurrencyNum(t *testing.T) { now := time.Now() for i := 0; i < 7; i++ { idx := i - b.Go(strconv.Itoa(idx), func() (interface{}, error) { + b.Go(strconv.Itoa(idx), func() (any, error) { time.Sleep(time.Millisecond * 100) return strconv.Itoa(idx), nil }) @@ -64,12 +64,12 @@ func TestBatchWithConcurrencyNum(t *testing.T) { func TestBatchContext(t *testing.T) { b, ctx := New(context.Background()) - b.Go("error", func() (interface{}, error) { + b.Go("error", func() (any, error) { time.Sleep(time.Millisecond * 100) return nil, errors.New("test error") }) - b.Go("ctx", func() (interface{}, error) { + b.Go("ctx", func() (any, error) { <-ctx.Done() return nil, ctx.Err() }) diff --git a/common/cache/cache.go b/common/cache/cache.go index 6b252c20..e587d77b 100644 --- a/common/cache/cache.go +++ b/common/cache/cache.go @@ -18,11 +18,11 @@ type cache struct { type element struct { Expired time.Time - Payload interface{} + Payload any } // Put element in Cache with its ttl -func (c *cache) Put(key interface{}, payload interface{}, ttl time.Duration) { +func (c *cache) Put(key any, payload any, ttl time.Duration) { c.mapping.Store(key, &element{ Payload: payload, Expired: time.Now().Add(ttl), @@ -30,7 +30,7 @@ func (c *cache) Put(key interface{}, payload interface{}, ttl time.Duration) { } // Get element in Cache, and drop when it expired -func (c *cache) Get(key interface{}) interface{} { +func (c *cache) Get(key any) any { item, exist := c.mapping.Load(key) if !exist { return nil @@ -45,7 +45,7 @@ func (c *cache) Get(key interface{}) interface{} { } // GetWithExpire element in Cache with Expire Time -func (c *cache) GetWithExpire(key interface{}) (payload interface{}, expired time.Time) { +func (c *cache) GetWithExpire(key any) (payload any, expired time.Time) { item, exist := c.mapping.Load(key) if !exist { return @@ -60,7 +60,7 @@ func (c *cache) GetWithExpire(key interface{}) (payload interface{}, expired tim } func (c *cache) cleanup() { - c.mapping.Range(func(k, v interface{}) bool { + c.mapping.Range(func(k, v any) bool { key := k.(string) elm := v.(*element) if time.Since(elm.Expired) > 0 { diff --git a/common/cache/lrucache.go b/common/cache/lrucache.go index 4269d86b..25a1b48e 100644 --- a/common/cache/lrucache.go +++ b/common/cache/lrucache.go @@ -12,7 +12,7 @@ import ( type Option func(*LruCache) // EvictCallback is used to get a callback when a cache entry is evicted -type EvictCallback = func(key interface{}, value interface{}) +type EvictCallback = func(key any, value any) // WithEvict set the evict callback func WithEvict(cb EvictCallback) Option { @@ -57,7 +57,7 @@ type LruCache struct { maxAge int64 maxSize int mu sync.Mutex - cache map[interface{}]*list.Element + cache map[any]*list.Element lru *list.List // Front is least-recent updateAgeOnGet bool staleReturn bool @@ -68,7 +68,7 @@ type LruCache struct { func NewLRUCache(options ...Option) *LruCache { lc := &LruCache{ lru: list.New(), - cache: make(map[interface{}]*list.Element), + cache: make(map[any]*list.Element), } for _, option := range options { @@ -78,9 +78,9 @@ func NewLRUCache(options ...Option) *LruCache { return lc } -// Get returns the interface{} representation of a cached response and a bool +// Get returns the any representation of a cached response and a bool // set to true if the key was found. -func (c *LruCache) Get(key interface{}) (interface{}, bool) { +func (c *LruCache) Get(key any) (any, bool) { entry := c.get(key) if entry == nil { return nil, false @@ -90,11 +90,11 @@ func (c *LruCache) Get(key interface{}) (interface{}, bool) { return value, true } -// GetWithExpire returns the interface{} representation of a cached response, +// GetWithExpire returns the any representation of a cached response, // a time.Time Give expected expires, // and a bool set to true if the key was found. // This method will NOT check the maxAge of element and will NOT update the expires. -func (c *LruCache) GetWithExpire(key interface{}) (interface{}, time.Time, bool) { +func (c *LruCache) GetWithExpire(key any) (any, time.Time, bool) { entry := c.get(key) if entry == nil { return nil, time.Time{}, false @@ -104,7 +104,7 @@ func (c *LruCache) GetWithExpire(key interface{}) (interface{}, time.Time, bool) } // Exist returns if key exist in cache but not put item to the head of linked list -func (c *LruCache) Exist(key interface{}) bool { +func (c *LruCache) Exist(key any) bool { c.mu.Lock() defer c.mu.Unlock() @@ -112,8 +112,8 @@ func (c *LruCache) Exist(key interface{}) bool { return ok } -// Set stores the interface{} representation of a response for a given key. -func (c *LruCache) Set(key interface{}, value interface{}) { +// Set stores the any representation of a response for a given key. +func (c *LruCache) Set(key any, value any) { expires := int64(0) if c.maxAge > 0 { expires = time.Now().Unix() + c.maxAge @@ -121,9 +121,9 @@ func (c *LruCache) Set(key interface{}, value interface{}) { c.SetWithExpire(key, value, time.Unix(expires, 0)) } -// SetWithExpire stores the interface{} representation of a response for a given key and given expires. +// SetWithExpire stores the any representation of a response for a given key and given expires. // The expires time will round to second. -func (c *LruCache) SetWithExpire(key interface{}, value interface{}, expires time.Time) { +func (c *LruCache) SetWithExpire(key any, value any, expires time.Time) { c.mu.Lock() defer c.mu.Unlock() @@ -155,7 +155,7 @@ func (c *LruCache) CloneTo(n *LruCache) { defer n.mu.Unlock() n.lru = list.New() - n.cache = make(map[interface{}]*list.Element) + n.cache = make(map[any]*list.Element) for e := c.lru.Front(); e != nil; e = e.Next() { elm := e.Value.(*entry) @@ -163,7 +163,7 @@ func (c *LruCache) CloneTo(n *LruCache) { } } -func (c *LruCache) get(key interface{}) *entry { +func (c *LruCache) get(key any) *entry { c.mu.Lock() defer c.mu.Unlock() @@ -188,7 +188,7 @@ func (c *LruCache) get(key interface{}) *entry { } // Delete removes the value associated with a key. -func (c *LruCache) Delete(key interface{}) { +func (c *LruCache) Delete(key any) { c.mu.Lock() if le, ok := c.cache[key]; ok { @@ -217,7 +217,7 @@ func (c *LruCache) deleteElement(le *list.Element) { } type entry struct { - key interface{} - value interface{} + key any + value any expires int64 } diff --git a/common/cache/lrucache_test.go b/common/cache/lrucache_test.go index 8a04f746..1a910b4a 100644 --- a/common/cache/lrucache_test.go +++ b/common/cache/lrucache_test.go @@ -126,7 +126,7 @@ func TestExist(t *testing.T) { func TestEvict(t *testing.T) { temp := 0 - evict := func(key interface{}, value interface{}) { + evict := func(key any, value any) { temp = key.(int) + value.(int) } diff --git a/common/observable/iterable.go b/common/observable/iterable.go index ad0943b5..2ac38b40 100644 --- a/common/observable/iterable.go +++ b/common/observable/iterable.go @@ -1,3 +1,3 @@ package observable -type Iterable <-chan interface{} +type Iterable <-chan any diff --git a/common/observable/observable_test.go b/common/observable/observable_test.go index b70feec8..da3e6d5c 100644 --- a/common/observable/observable_test.go +++ b/common/observable/observable_test.go @@ -9,8 +9,8 @@ import ( "go.uber.org/atomic" ) -func iterator(item []interface{}) chan interface{} { - ch := make(chan interface{}) +func iterator(item []any) chan any { + ch := make(chan any) go func() { time.Sleep(100 * time.Millisecond) for _, elm := range item { @@ -22,7 +22,7 @@ func iterator(item []interface{}) chan interface{} { } func TestObservable(t *testing.T) { - iter := iterator([]interface{}{1, 2, 3, 4, 5}) + iter := iterator([]any{1, 2, 3, 4, 5}) src := NewObservable(iter) data, err := src.Subscribe() assert.Nil(t, err) @@ -34,7 +34,7 @@ func TestObservable(t *testing.T) { } func TestObservable_MultiSubscribe(t *testing.T) { - iter := iterator([]interface{}{1, 2, 3, 4, 5}) + iter := iterator([]any{1, 2, 3, 4, 5}) src := NewObservable(iter) ch1, _ := src.Subscribe() ch2, _ := src.Subscribe() @@ -42,7 +42,7 @@ func TestObservable_MultiSubscribe(t *testing.T) { var wg sync.WaitGroup wg.Add(2) - waitCh := func(ch <-chan interface{}) { + waitCh := func(ch <-chan any) { for range ch { count.Inc() } @@ -55,7 +55,7 @@ func TestObservable_MultiSubscribe(t *testing.T) { } func TestObservable_UnSubscribe(t *testing.T) { - iter := iterator([]interface{}{1, 2, 3, 4, 5}) + iter := iterator([]any{1, 2, 3, 4, 5}) src := NewObservable(iter) data, err := src.Subscribe() assert.Nil(t, err) @@ -65,7 +65,7 @@ func TestObservable_UnSubscribe(t *testing.T) { } func TestObservable_SubscribeClosedSource(t *testing.T) { - iter := iterator([]interface{}{1}) + iter := iterator([]any{1}) src := NewObservable(iter) data, _ := src.Subscribe() <-data @@ -75,14 +75,14 @@ func TestObservable_SubscribeClosedSource(t *testing.T) { } func TestObservable_UnSubscribeWithNotExistSubscription(t *testing.T) { - sub := Subscription(make(chan interface{})) - iter := iterator([]interface{}{1}) + sub := Subscription(make(chan any)) + iter := iterator([]any{1}) src := NewObservable(iter) src.UnSubscribe(sub) } func TestObservable_SubscribeGoroutineLeak(t *testing.T) { - iter := iterator([]interface{}{1, 2, 3, 4, 5}) + iter := iterator([]any{1, 2, 3, 4, 5}) src := NewObservable(iter) max := 100 @@ -94,7 +94,7 @@ func TestObservable_SubscribeGoroutineLeak(t *testing.T) { var wg sync.WaitGroup wg.Add(max) - waitCh := func(ch <-chan interface{}) { + waitCh := func(ch <-chan any) { for range ch { } wg.Done() @@ -115,7 +115,7 @@ func TestObservable_SubscribeGoroutineLeak(t *testing.T) { } func Benchmark_Observable_1000(b *testing.B) { - ch := make(chan interface{}) + ch := make(chan any) o := NewObservable(ch) num := 1000 diff --git a/common/observable/subscriber.go b/common/observable/subscriber.go index cb2a70f4..0d8559bc 100644 --- a/common/observable/subscriber.go +++ b/common/observable/subscriber.go @@ -4,14 +4,14 @@ import ( "sync" ) -type Subscription <-chan interface{} +type Subscription <-chan any type Subscriber struct { - buffer chan interface{} + buffer chan any once sync.Once } -func (s *Subscriber) Emit(item interface{}) { +func (s *Subscriber) Emit(item any) { s.buffer <- item } @@ -27,7 +27,7 @@ func (s *Subscriber) Close() { func newSubscriber() *Subscriber { sub := &Subscriber{ - buffer: make(chan interface{}, 200), + buffer: make(chan any, 200), } return sub } diff --git a/common/picker/picker.go b/common/picker/picker.go index 9f38aede..e701268a 100644 --- a/common/picker/picker.go +++ b/common/picker/picker.go @@ -17,7 +17,7 @@ type Picker struct { once sync.Once errOnce sync.Once - result interface{} + result any err error } @@ -43,7 +43,7 @@ func WithTimeout(ctx context.Context, timeout time.Duration) (*Picker, context.C // Wait blocks until all function calls from the Go method have returned, // then returns the first nil error result (if any) from them. -func (p *Picker) Wait() interface{} { +func (p *Picker) Wait() any { p.wg.Wait() if p.cancel != nil { p.cancel() @@ -58,7 +58,7 @@ func (p *Picker) Error() error { // Go calls the given function in a new goroutine. // The first call to return a nil error cancels the group; its result will be returned by Wait. -func (p *Picker) Go(f func() (interface{}, error)) { +func (p *Picker) Go(f func() (any, error)) { p.wg.Add(1) go func() { diff --git a/common/picker/picker_test.go b/common/picker/picker_test.go index 82122d7f..ca10499d 100644 --- a/common/picker/picker_test.go +++ b/common/picker/picker_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" ) -func sleepAndSend(ctx context.Context, delay int, input interface{}) func() (interface{}, error) { - return func() (interface{}, error) { +func sleepAndSend(ctx context.Context, delay int, input any) func() (any, error) { + return func() (any, error) { timer := time.NewTimer(time.Millisecond * time.Duration(delay)) select { case <-timer.C: diff --git a/common/pool/alloc.go b/common/pool/alloc.go index 710639af..efc19123 100644 --- a/common/pool/alloc.go +++ b/common/pool/alloc.go @@ -23,7 +23,7 @@ func NewAllocator() *Allocator { alloc.buffers = make([]sync.Pool, 17) // 1B -> 64K for k := range alloc.buffers { i := k - alloc.buffers[k].New = func() interface{} { + alloc.buffers[k].New = func() any { return make([]byte, 1< 1 { - omitempty = str[1] == "omitempty" - } + key, omitKey, found := strings.Cut(tag, ",") + omitempty := found && omitKey == "omitempty" value, ok := src[key] if !ok || value == nil { @@ -68,7 +64,7 @@ func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error { return nil } -func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decode(name string, data any, val reflect.Value) error { switch val.Kind() { case reflect.Int: return d.decodeInt(name, data, val) @@ -89,7 +85,7 @@ func (d *Decoder) decode(name string, data interface{}, val reflect.Value) error } } -func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) (err error) { +func (d *Decoder) decodeInt(name string, data any, val reflect.Value) (err error) { dataVal := reflect.ValueOf(data) kind := dataVal.Kind() switch { @@ -112,7 +108,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) (e return err } -func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) (err error) { +func (d *Decoder) decodeString(name string, data any, val reflect.Value) (err error) { dataVal := reflect.ValueOf(data) kind := dataVal.Kind() switch { @@ -129,7 +125,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) return err } -func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) (err error) { +func (d *Decoder) decodeBool(name string, data any, val reflect.Value) (err error) { dataVal := reflect.ValueOf(data) kind := dataVal.Kind() switch { @@ -146,7 +142,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) ( return err } -func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeSlice(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) valType := val.Type() valElemType := valType.Elem() @@ -173,7 +169,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) return nil } -func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeMap(name string, data any, val reflect.Value) error { valType := val.Type() valKeyType := valType.Key() valElemType := valType.Elem() @@ -245,7 +241,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle return nil } -func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { +func (d *Decoder) decodeStruct(name string, data any, val reflect.Value) error { dataVal := reflect.Indirect(reflect.ValueOf(data)) // If the type of the value to write to and the data match directly, @@ -273,7 +269,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e } dataValKeys := make(map[reflect.Value]struct{}) - dataValKeysUnused := make(map[interface{}]struct{}) + dataValKeysUnused := make(map[any]struct{}) for _, dataValKey := range dataVal.MapKeys() { dataValKeys[dataValKey] = struct{}{} dataValKeysUnused[dataValKey.Interface()] = struct{}{} @@ -398,7 +394,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e return nil } -func (d *Decoder) setInterface(name string, data interface{}, val reflect.Value) (err error) { +func (d *Decoder) setInterface(name string, data any, val reflect.Value) (err error) { dataVal := reflect.ValueOf(data) val.Set(dataVal) return nil diff --git a/common/structure/structure_test.go b/common/structure/structure_test.go index 69268fa6..b3bc52a6 100644 --- a/common/structure/structure_test.go +++ b/common/structure/structure_test.go @@ -27,7 +27,7 @@ type BazOptional struct { } func TestStructure_Basic(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": 1, "bar": "test", "extra": false, @@ -45,7 +45,7 @@ func TestStructure_Basic(t *testing.T) { } func TestStructure_Slice(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": 1, "bar": []string{"one", "two"}, } @@ -62,7 +62,7 @@ func TestStructure_Slice(t *testing.T) { } func TestStructure_Optional(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": 1, } @@ -77,7 +77,7 @@ func TestStructure_Optional(t *testing.T) { } func TestStructure_MissingKey(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": 1, } @@ -87,14 +87,14 @@ func TestStructure_MissingKey(t *testing.T) { } func TestStructure_ParamError(t *testing.T) { - rawMap := map[string]interface{}{} + rawMap := map[string]any{} s := Baz{} err := decoder.Decode(rawMap, s) assert.NotNilf(t, err, "should throw error: %#v", s) } func TestStructure_SliceTypeError(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": 1, "bar": []int{1, 2}, } @@ -105,7 +105,7 @@ func TestStructure_SliceTypeError(t *testing.T) { } func TestStructure_WeakType(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": "1", "bar": []int{1}, } @@ -122,7 +122,7 @@ func TestStructure_WeakType(t *testing.T) { } func TestStructure_Nest(t *testing.T) { - rawMap := map[string]interface{}{ + rawMap := map[string]any{ "foo": 1, } diff --git a/component/auth/auth.go b/component/auth/auth.go index 98414d8b..9d30b927 100644 --- a/component/auth/auth.go +++ b/component/auth/auth.go @@ -36,7 +36,7 @@ func NewAuthenticator(users []AuthUser) Authenticator { au.storage.Store(user.User, user.Pass) } usernames := make([]string, 0, len(users)) - au.storage.Range(func(key, value interface{}) bool { + au.storage.Range(func(key, value any) bool { usernames = append(usernames, key.(string)) return true }) diff --git a/component/dialer/bind_others.go b/component/dialer/bind_others.go index 2cabb48a..51b2ef68 100644 --- a/component/dialer/bind_others.go +++ b/component/dialer/bind_others.go @@ -1,5 +1,4 @@ //go:build !linux && !darwin -// +build !linux,!darwin package dialer diff --git a/component/dialer/mark_linux.go b/component/dialer/mark_linux.go index 79a2185e..e54873bc 100644 --- a/component/dialer/mark_linux.go +++ b/component/dialer/mark_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package dialer diff --git a/component/dialer/mark_nonlinux.go b/component/dialer/mark_nonlinux.go index 5d9befb1..98645e48 100644 --- a/component/dialer/mark_nonlinux.go +++ b/component/dialer/mark_nonlinux.go @@ -1,5 +1,4 @@ //go:build !linux -// +build !linux package dialer diff --git a/component/dialer/reuse_others.go b/component/dialer/reuse_others.go index b76213a7..db67a095 100644 --- a/component/dialer/reuse_others.go +++ b/component/dialer/reuse_others.go @@ -1,5 +1,4 @@ //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows -// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows package dialer diff --git a/component/dialer/reuse_unix.go b/component/dialer/reuse_unix.go index d5f43d8f..85fe5e5e 100644 --- a/component/dialer/reuse_unix.go +++ b/component/dialer/reuse_unix.go @@ -1,5 +1,4 @@ //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris -// +build darwin dragonfly freebsd linux netbsd openbsd solaris package dialer diff --git a/component/iface/iface.go b/component/iface/iface.go index 4e916260..df290811 100644 --- a/component/iface/iface.go +++ b/component/iface/iface.go @@ -23,7 +23,7 @@ var ( var interfaces = singledo.NewSingle(time.Second * 20) func ResolveInterface(name string) (*Interface, error) { - value, err, _ := interfaces.Do(func() (interface{}, error) { + value, err, _ := interfaces.Do(func() (any, error) { ifaces, err := net.Interfaces() if err != nil { return nil, err diff --git a/component/pool/pool.go b/component/pool/pool.go index ce40a129..ef117539 100644 --- a/component/pool/pool.go +++ b/component/pool/pool.go @@ -6,17 +6,17 @@ import ( "time" ) -type Factory = func(context.Context) (interface{}, error) +type Factory = func(context.Context) (any, error) type entry struct { - elm interface{} + elm any time time.Time } type Option func(*pool) // WithEvict set the evict callback -func WithEvict(cb func(interface{})) Option { +func WithEvict(cb func(any)) Option { return func(p *pool) { p.evict = cb } @@ -32,7 +32,7 @@ func WithAge(maxAge int64) Option { // WithSize defined max size of Pool func WithSize(maxSize int) Option { return func(p *pool) { - p.ch = make(chan interface{}, maxSize) + p.ch = make(chan any, maxSize) } } @@ -42,13 +42,13 @@ type Pool struct { } type pool struct { - ch chan interface{} + ch chan any factory Factory - evict func(interface{}) + evict func(any) maxAge int64 } -func (p *pool) GetContext(ctx context.Context) (interface{}, error) { +func (p *pool) GetContext(ctx context.Context) (any, error) { now := time.Now() for { select { @@ -68,11 +68,11 @@ func (p *pool) GetContext(ctx context.Context) (interface{}, error) { } } -func (p *pool) Get() (interface{}, error) { +func (p *pool) Get() (any, error) { return p.GetContext(context.Background()) } -func (p *pool) Put(item interface{}) { +func (p *pool) Put(item any) { e := &entry{ elm: item, time: time.Now(), @@ -100,7 +100,7 @@ func recycle(p *Pool) { func New(factory Factory, options ...Option) *Pool { p := &pool{ - ch: make(chan interface{}, 10), + ch: make(chan any, 10), factory: factory, } diff --git a/component/pool/pool_test.go b/component/pool/pool_test.go index f03a1c9b..10f49965 100644 --- a/component/pool/pool_test.go +++ b/component/pool/pool_test.go @@ -10,7 +10,7 @@ import ( func lg() Factory { initial := -1 - return func(context.Context) (interface{}, error) { + return func(context.Context) (any, error) { initial++ return initial, nil } @@ -34,7 +34,7 @@ func TestPool_MaxSize(t *testing.T) { size := 5 pool := New(g, WithSize(size)) - items := []interface{}{} + items := []any{} for i := 0; i < size; i++ { item, _ := pool.Get() diff --git a/component/process/process_other.go b/component/process/process_other.go index f8a6ebbb..c9e486f6 100644 --- a/component/process/process_other.go +++ b/component/process/process_other.go @@ -1,8 +1,4 @@ //go:build !darwin && !linux && !windows && (!freebsd || !amd64) -// +build !darwin -// +build !linux -// +build !windows -// +build !freebsd !amd64 package process diff --git a/component/trie/domain.go b/component/trie/domain.go index fcc9e3ba..8915eda3 100644 --- a/component/trie/domain.go +++ b/component/trie/domain.go @@ -51,7 +51,7 @@ func ValidAndSplitDomain(domain string) ([]string, bool) { // 3. subdomain.*.example.com // 4. .example.com // 5. +.example.com -func (t *DomainTrie) Insert(domain string, data interface{}) error { +func (t *DomainTrie) Insert(domain string, data any) error { parts, valid := ValidAndSplitDomain(domain) if !valid { return ErrInvalidDomain @@ -68,7 +68,7 @@ func (t *DomainTrie) Insert(domain string, data interface{}) error { return nil } -func (t *DomainTrie) insert(parts []string, data interface{}) { +func (t *DomainTrie) insert(parts []string, data any) { node := t.root // reverse storage domain part to save space for i := len(parts) - 1; i >= 0; i-- { diff --git a/component/trie/node.go b/component/trie/node.go index 42672f0b..67ef64a4 100644 --- a/component/trie/node.go +++ b/component/trie/node.go @@ -3,7 +3,7 @@ package trie // Node is the trie's node type Node struct { children map[string]*Node - Data interface{} + Data any } func (n *Node) getChild(s string) *Node { @@ -18,7 +18,7 @@ func (n *Node) addChild(s string, child *Node) { n.children[s] = child } -func newNode(data interface{}) *Node { +func newNode(data any) *Node { return &Node{ Data: data, children: map[string]*Node{}, diff --git a/config/config.go b/config/config.go index 8ca33fd0..3171083c 100644 --- a/config/config.go +++ b/config/config.go @@ -186,8 +186,8 @@ type RawConfig struct { Tun Tun `yaml:"tun"` Experimental Experimental `yaml:"experimental"` Profile Profile `yaml:"profile"` - Proxy []map[string]interface{} `yaml:"proxies"` - ProxyGroup []map[string]interface{} `yaml:"proxy-groups"` + Proxy []map[string]any `yaml:"proxies"` + ProxyGroup []map[string]any Rule []string `yaml:"rules"` Script Script `yaml:"script"` } @@ -216,8 +216,8 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) { LogLevel: log.INFO, Hosts: map[string]string{}, Rule: []string{}, - Proxy: []map[string]interface{}{}, - ProxyGroup: []map[string]interface{}{}, + Proxy: []map[string]any{}, + ProxyGroup: []map[string]any{}, Tun: Tun{ Enable: false, Stack: "gvisor", @@ -432,7 +432,19 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[ proxies[groupName] = adapter.NewProxy(group) } - var ps []C.Proxy + // initial compatible provider + for _, pd := range providersMap { + if pd.VehicleType() != providerTypes.Compatible { + continue + } + + log.Infoln("Start initial compatible provider %s", pd.Name()) + if err := pd.Initial(); err != nil { + return nil, nil, err + } + } + + ps := []C.Proxy{} for _, v := range proxyList { ps = append(ps, proxies[v]) } @@ -597,7 +609,7 @@ func parseHosts(cfg *RawConfig) (*trie.DomainTrie, error) { if ip == nil { return nil, fmt.Errorf("%s is not a valid IP", ipStr) } - _ = tree.Insert(domain, ip) + tree.Insert(domain, ip) } } @@ -622,7 +634,7 @@ func hostWithDefaultPort(host string, defPort string) (string, error) { } func parseNameServer(servers []string) ([]dns.NameServer, error) { - var nameservers []dns.NameServer + nameservers := []dns.NameServer{} for idx, server := range servers { // parse without scheme .e.g 8.8.8.8:53 @@ -693,7 +705,7 @@ func parseNameServerPolicy(nsPolicy map[string]string) (map[string]dns.NameServe } func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) { - var ipNets []*net.IPNet + ipNets := []*net.IPNet{} for idx, ip := range ips { _, ipnet, err := net.ParseCIDR(ip) @@ -795,7 +807,7 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie, rules []C.Rule) (*DNS, if len(cfg.FakeIPFilter) != 0 { host = trie.New() for _, domain := range cfg.FakeIPFilter { - _ = host.Insert(domain, true) + host.Insert(domain, true) } } @@ -846,11 +858,10 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie, rules []C.Rule) (*DNS, } func parseAuthentication(rawRecords []string) []auth.AuthUser { - users := make([]auth.AuthUser, 0) + users := []auth.AuthUser{} for _, line := range rawRecords { - userData := strings.SplitN(line, ":", 2) - if len(userData) == 2 { - users = append(users, auth.AuthUser{User: userData[0], Pass: userData[1]}) + if user, pass, found := strings.Cut(line, ":"); found { + users = append(users, auth.AuthUser{User: user, Pass: pass}) } } return users diff --git a/config/utils.go b/config/utils.go index 387591d0..1d49552f 100644 --- a/config/utils.go +++ b/config/utils.go @@ -18,13 +18,13 @@ func trimArr(arr []string) (r []string) { // Check if ProxyGroups form DAG(Directed Acyclic Graph), and sort all ProxyGroups by dependency order. // Meanwhile, record the original index in the config file. // If loop is detected, return an error with location of loop. -func proxyGroupsDagSort(groupsConfig []map[string]interface{}) error { +func proxyGroupsDagSort(groupsConfig []map[string]any) error { type graphNode struct { indegree int // topological order topo int // the original data in `groupsConfig` - data map[string]interface{} + data map[string]any // `outdegree` and `from` are used in loop locating outdegree int option *outboundgroup.GroupCommonOption diff --git a/constant/dns.go b/constant/dns.go index d1cd7a61..eee98e5d 100644 --- a/constant/dns.go +++ b/constant/dns.go @@ -21,7 +21,7 @@ const ( type DNSMode int // UnmarshalYAML unserialize EnhancedMode with yaml -func (e *DNSMode) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (e *DNSMode) UnmarshalYAML(unmarshal func(any) error) error { var tp string if err := unmarshal(&tp); err != nil { return err @@ -35,7 +35,7 @@ func (e *DNSMode) UnmarshalYAML(unmarshal func(interface{}) error) error { } // MarshalYAML serialize EnhancedMode with yaml -func (e DNSMode) MarshalYAML() (interface{}, error) { +func (e DNSMode) MarshalYAML() (any, error) { return e.String(), nil } diff --git a/dns/resolver.go b/dns/resolver.go index 8a10f317..ce48a040 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -118,7 +118,7 @@ func (r *Resolver) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, e func (r *Resolver) exchangeWithoutCache(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { q := m.Question[0] - ret, err, shared := r.group.Do(q.String(), func() (result interface{}, err error) { + ret, err, shared := r.group.Do(q.String(), func() (result any, err error) { defer func() { if err != nil { return @@ -154,7 +154,7 @@ func (r *Resolver) batchExchange(ctx context.Context, clients []dnsClient, m *D. fast, ctx := picker.WithTimeout(ctx, resolver.DefaultDNSTimeout) for _, client := range clients { r := client - fast.Go(func() (interface{}, error) { + fast.Go(func() (any, error) { m, err := r.ExchangeContext(ctx, m) if err != nil { return nil, err diff --git a/go.mod b/go.mod index 01c19a43..5f251602 100644 --- a/go.mod +++ b/go.mod @@ -53,5 +53,4 @@ require ( golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect - ) diff --git a/hub/route/server.go b/hub/route/server.go index b657128e..e7fea3d6 100644 --- a/hub/route/server.go +++ b/hub/route/server.go @@ -117,10 +117,10 @@ func authentication(next http.Handler) http.Handler { } header := r.Header.Get("Authorization") - text := strings.SplitN(header, " ", 2) + bearer, token, found := strings.Cut(header, " ") - hasInvalidHeader := text[0] != "Bearer" - hasInvalidSecret := len(text) != 2 || text[1] != serverSecret + hasInvalidHeader := bearer != "Bearer" + hasInvalidSecret := !found || token != serverSecret if hasInvalidHeader || hasInvalidSecret { render.Status(r, http.StatusUnauthorized) render.JSON(w, r, ErrUnauthorized) diff --git a/listener/http/proxy.go b/listener/http/proxy.go index becb3673..18f1e5d4 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -108,7 +108,7 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response { return resp } - var authed interface{} + var authed any if authed = cache.Get(credential); authed == nil { user, pass, err := decodeBasicProxyAuthorization(credential) authed = err == nil && authenticator.Verify(user, pass) diff --git a/listener/http/utils.go b/listener/http/utils.go index 17760799..74b12005 100644 --- a/listener/http/utils.go +++ b/listener/http/utils.go @@ -65,10 +65,10 @@ func decodeBasicProxyAuthorization(credential string) (string, string, error) { return "", "", err } - login := strings.Split(string(plain), ":") - if len(login) != 2 { + user, pass, found := strings.Cut(string(plain), ":") + if !found { return "", "", errors.New("invalid login") } - return login[0], login[1], nil + return user, pass, nil } diff --git a/listener/redir/tcp_linux_other.go b/listener/redir/tcp_linux_other.go index 3299843d..b8c7de8a 100644 --- a/listener/redir/tcp_linux_other.go +++ b/listener/redir/tcp_linux_other.go @@ -1,5 +1,4 @@ //go:build linux && !386 -// +build linux,!386 package redir diff --git a/listener/redir/tcp_other.go b/listener/redir/tcp_other.go index 592e9584..a01550c7 100644 --- a/listener/redir/tcp_other.go +++ b/listener/redir/tcp_other.go @@ -1,5 +1,4 @@ //go:build !darwin && !linux && !freebsd -// +build !darwin,!linux,!freebsd package redir diff --git a/listener/tproxy/setsockopt_linux.go b/listener/tproxy/setsockopt_linux.go index 1e92db12..06f3e1c3 100644 --- a/listener/tproxy/setsockopt_linux.go +++ b/listener/tproxy/setsockopt_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package tproxy diff --git a/listener/tproxy/setsockopt_other.go b/listener/tproxy/setsockopt_other.go index 24fb7c7b..9ba06f91 100644 --- a/listener/tproxy/setsockopt_other.go +++ b/listener/tproxy/setsockopt_other.go @@ -1,5 +1,4 @@ //go:build !linux -// +build !linux package tproxy diff --git a/listener/tproxy/udp_linux.go b/listener/tproxy/udp_linux.go index f68ce8f1..8cda96fd 100644 --- a/listener/tproxy/udp_linux.go +++ b/listener/tproxy/udp_linux.go @@ -1,5 +1,4 @@ //go:build linux -// +build linux package tproxy diff --git a/listener/tproxy/udp_other.go b/listener/tproxy/udp_other.go index f899fc3d..db4a1409 100644 --- a/listener/tproxy/udp_other.go +++ b/listener/tproxy/udp_other.go @@ -1,5 +1,4 @@ //go:build !linux -// +build !linux package tproxy diff --git a/log/level.go b/log/level.go index f70116a3..ea06ee4b 100644 --- a/log/level.go +++ b/log/level.go @@ -25,7 +25,7 @@ const ( type LogLevel int // UnmarshalYAML unserialize LogLevel with yaml -func (l *LogLevel) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (l *LogLevel) UnmarshalYAML(unmarshal func(any) error) error { var tp string unmarshal(&tp) level, exist := LogLevelMapping[tp] @@ -54,7 +54,7 @@ func (l LogLevel) MarshalJSON() ([]byte, error) { } // MarshalYAML serialize LogLevel with yaml -func (l LogLevel) MarshalYAML() (interface{}, error) { +func (l LogLevel) MarshalYAML() (any, error) { return l.String(), nil } diff --git a/log/log.go b/log/log.go index f5c57768..4e5c375b 100644 --- a/log/log.go +++ b/log/log.go @@ -10,7 +10,7 @@ import ( ) var ( - logCh = make(chan interface{}) + logCh = make(chan any) source = observable.NewObservable(logCh) level = INFO ) @@ -29,31 +29,31 @@ func (e *Event) Type() string { return e.LogLevel.String() } -func Infoln(format string, v ...interface{}) { +func Infoln(format string, v ...any) { event := newLog(INFO, format, v...) logCh <- event print(event) } -func Warnln(format string, v ...interface{}) { +func Warnln(format string, v ...any) { event := newLog(WARNING, format, v...) logCh <- event print(event) } -func Errorln(format string, v ...interface{}) { +func Errorln(format string, v ...any) { event := newLog(ERROR, format, v...) logCh <- event print(event) } -func Debugln(format string, v ...interface{}) { +func Debugln(format string, v ...any) { event := newLog(DEBUG, format, v...) logCh <- event print(event) } -func Fatalln(format string, v ...interface{}) { +func Fatalln(format string, v ...any) { log.Fatalf(format, v...) } @@ -91,7 +91,7 @@ func print(data *Event) { } } -func newLog(logLevel LogLevel, format string, v ...interface{}) *Event { +func newLog(logLevel LogLevel, format string, v ...any) *Event { return &Event{ LogLevel: logLevel, Payload: fmt.Sprintf(format, v...), diff --git a/main.go b/main.go index 60a20809..cad43d75 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ func init() { } func main() { - _, _ = maxprocs.Set(maxprocs.Logger(func(string, ...interface{}) {})) + maxprocs.Set(maxprocs.Logger(func(string, ...any) {})) if version { fmt.Printf("Clash Meta %s %s %s with %s %s\n", C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime) return diff --git a/test/go.mod b/test/go.mod index 3c05e6a3..2c66f153 100644 --- a/test/go.mod +++ b/test/go.mod @@ -1,30 +1,33 @@ module clash-test -go 1.17 +go 1.18 require ( github.com/Dreamacro/clash v1.7.2-0.20211108085948-bd2ea2b917aa - github.com/docker/docker v20.10.12+incompatible + github.com/docker/docker v20.10.13+incompatible github.com/docker/go-connections v0.4.0 - github.com/miekg/dns v1.1.45 - github.com/stretchr/testify v1.7.0 - golang.org/x/net v0.0.0-20211216030914-fe4d6282115f + github.com/miekg/dns v1.1.47 + github.com/stretchr/testify v1.7.1 + golang.org/x/net v0.0.0-20220225172249-27dd8689420f ) replace github.com/Dreamacro/clash => ../ require ( github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect - github.com/containerd/containerd v1.5.8 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/containerd/containerd v1.6.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/go-units v0.4.0 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/gorilla/mux v1.8.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 // indirect github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99 // indirect @@ -32,7 +35,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect - github.com/oschwald/geoip2-golang v1.5.0 // indirect + github.com/oschwald/geoip2-golang v1.6.1 // indirect github.com/oschwald/maxminddb-golang v1.8.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -42,16 +45,16 @@ require ( github.com/yaling888/go-lwip v0.0.0-20211103185822-c9d650538091 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect + golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect golang.org/x/mod v0.4.2 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect - golang.org/x/text v0.3.6 // indirect - golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect + golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect - google.golang.org/grpc v1.43.0 // indirect + google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect + google.golang.org/grpc v1.45.0 // indirect google.golang.org/protobuf v1.27.1 // indirect golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 // indirect golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // indirect @@ -61,6 +64,8 @@ require ( google.golang.org/grpc v1.42.0 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + gotest.tools/v3 v3.1.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect gvisor.dev/gvisor v0.0.0-20211104052249-2de3450f76d6 // indirect ) diff --git a/test/snell_test.go b/test/snell_test.go index 04ae9cbc..8149fb53 100644 --- a/test/snell_test.go +++ b/test/snell_test.go @@ -37,7 +37,7 @@ func TestClash_SnellObfsHTTP(t *testing.T) { Server: localIP.String(), Port: 10002, Psk: "password", - ObfsOpts: map[string]interface{}{ + ObfsOpts: map[string]any{ "mode": "http", }, }) @@ -74,7 +74,7 @@ func TestClash_SnellObfsTLS(t *testing.T) { Server: localIP.String(), Port: 10002, Psk: "password", - ObfsOpts: map[string]interface{}{ + ObfsOpts: map[string]any{ "mode": "tls", }, }) @@ -181,7 +181,7 @@ func Benchmark_Snell(b *testing.B) { Server: localIP.String(), Port: 10002, Psk: "password", - ObfsOpts: map[string]interface{}{ + ObfsOpts: map[string]any{ "mode": "http", }, }) diff --git a/test/ss_test.go b/test/ss_test.go index a611bea5..467a6e1e 100644 --- a/test/ss_test.go +++ b/test/ss_test.go @@ -76,7 +76,7 @@ func TestClash_ShadowsocksObfsHTTP(t *testing.T) { Cipher: "chacha20-ietf-poly1305", UDP: true, Plugin: "obfs", - PluginOpts: map[string]interface{}{ + PluginOpts: map[string]any{ "mode": "http", }, }) @@ -118,7 +118,7 @@ func TestClash_ShadowsocksObfsTLS(t *testing.T) { Cipher: "chacha20-ietf-poly1305", UDP: true, Plugin: "obfs", - PluginOpts: map[string]interface{}{ + PluginOpts: map[string]any{ "mode": "tls", }, }) @@ -160,7 +160,7 @@ func TestClash_ShadowsocksV2RayPlugin(t *testing.T) { Cipher: "chacha20-ietf-poly1305", UDP: true, Plugin: "v2ray-plugin", - PluginOpts: map[string]interface{}{ + PluginOpts: map[string]any{ "mode": "websocket", }, }) diff --git a/test/util_other_test.go b/test/util_other_test.go index 13ba87f3..708b6099 100644 --- a/test/util_other_test.go +++ b/test/util_other_test.go @@ -1,5 +1,4 @@ //go:build !darwin -// +build !darwin package main diff --git a/transport/snell/pool.go b/transport/snell/pool.go index 6eda2a9d..62d21b4e 100644 --- a/transport/snell/pool.go +++ b/transport/snell/pool.go @@ -71,12 +71,12 @@ func (pc *PoolConn) Close() error { func NewPool(factory func(context.Context) (*Snell, error)) *Pool { p := pool.New( - func(ctx context.Context) (interface{}, error) { + func(ctx context.Context) (any, error) { return factory(ctx) }, pool.WithAge(15000), pool.WithSize(10), - pool.WithEvict(func(item interface{}) { + pool.WithEvict(func(item any) { item.(*Snell).Close() }), ) diff --git a/tunnel/mode.go b/tunnel/mode.go index bdf646f0..6e3561d8 100644 --- a/tunnel/mode.go +++ b/tunnel/mode.go @@ -36,7 +36,7 @@ func (m *TunnelMode) UnmarshalJSON(data []byte) error { } // UnmarshalYAML unserialize Mode with yaml -func (m *TunnelMode) UnmarshalYAML(unmarshal func(interface{}) error) error { +func (m *TunnelMode) UnmarshalYAML(unmarshal func(any) error) error { var tp string unmarshal(&tp) mode, exist := ModeMapping[strings.ToLower(tp)] @@ -53,7 +53,7 @@ func (m TunnelMode) MarshalJSON() ([]byte, error) { } // MarshalYAML serialize TunnelMode with yaml -func (m TunnelMode) MarshalYAML() (interface{}, error) { +func (m TunnelMode) MarshalYAML() (any, error) { return m.String(), nil } diff --git a/tunnel/statistic/manager.go b/tunnel/statistic/manager.go index 462da674..e67d3871 100644 --- a/tunnel/statistic/manager.go +++ b/tunnel/statistic/manager.go @@ -56,7 +56,7 @@ func (m *Manager) Now() (up int64, down int64) { func (m *Manager) Snapshot() *Snapshot { connections := []tracker{} - m.connections.Range(func(key, value interface{}) bool { + m.connections.Range(func(key, value any) bool { connections = append(connections, value.(tracker)) return true })