Merge remote-tracking branch 'clash/dev' into Alpha

# Conflicts:
#	.github/workflows/docker.yml
#	adapter/outboundgroup/fallback.go
#	adapter/outboundgroup/loadbalance.go
#	adapter/outboundgroup/relay.go
#	adapter/outboundgroup/selector.go
#	adapter/outboundgroup/urltest.go
#	config/config.go
#	go.mod
#	go.sum
#	main.go
#	test/go.mod
#	test/go.sum
This commit is contained in:
MetaCubeX 2022-03-17 01:41:51 +08:00
commit 609d69191a
70 changed files with 241 additions and 255 deletions

View file

@ -2,7 +2,7 @@ linters:
disable-all: true disable-all: true
enable: enable:
- gofumpt - gofumpt
- megacheck - staticcheck
- govet - govet
- gci - gci
@ -12,3 +12,5 @@ linters-settings:
- standard - standard
- prefix(github.com/Dreamacro/clash) - prefix(github.com/Dreamacro/clash)
- default - default
staticcheck:
go: '1.18'

View file

@ -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 linux-mips-hardfloat linux-mips-softfloat linux-mips64 linux-mips64le linux-mipsle-hardfloat linux-mipsle-softfloat# Most used
docker: docker:
$(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
darwin-amd64: darwin-amd64:
GOARCH=amd64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=amd64 GOOS=darwin GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
darwin-arm64: darwin-arm64:
GOARCH=arm64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=arm64 GOOS=darwin $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
@ -53,7 +53,7 @@ linux-386:
GOARCH=386 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=386 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
linux-amd64: linux-amd64:
GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
linux-amd64-AutoIptables: linux-amd64-AutoIptables:
GOARCH=amd64 GOOS=linux $(GOBUILDOP) -o $(BINDIR)/$(NAME)-$@ GOARCH=amd64 GOOS=linux $(GOBUILDOP) -o $(BINDIR)/$(NAME)-$@
@ -98,7 +98,7 @@ freebsd-386:
GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
freebsd-amd64: freebsd-amd64:
GOARCH=amd64 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=amd64 GOOS=freebsd GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
freebsd-arm64: freebsd-arm64:
GOARCH=arm64 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ GOARCH=arm64 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@
@ -107,7 +107,7 @@ windows-386:
GOARCH=386 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe GOARCH=386 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
windows-amd64: windows-amd64:
GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe GOARCH=amd64 GOOS=windows GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe
windows-arm64: windows-arm64:
GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe

View file

@ -93,7 +93,7 @@ func (p *Proxy) MarshalJSON() ([]byte, error) {
return inner, err return inner, err
} }
mapping := map[string]interface{}{} mapping := map[string]any{}
json.Unmarshal(inner, &mapping) json.Unmarshal(inner, &mapping)
mapping["history"] = p.DelayHistory() mapping["history"] = p.DelayHistory()
mapping["name"] = p.Name() mapping["name"] = p.Name()

View file

@ -29,14 +29,14 @@ type ShadowSocks struct {
type ShadowSocksOption struct { type ShadowSocksOption struct {
BasicOption BasicOption
Name string `proxy:"name"` Name string `proxy:"name"`
Server string `proxy:"server"` Server string `proxy:"server"`
Port int `proxy:"port"` Port int `proxy:"port"`
Password string `proxy:"password"` Password string `proxy:"password"`
Cipher string `proxy:"cipher"` Cipher string `proxy:"cipher"`
UDP bool `proxy:"udp,omitempty"` UDP bool `proxy:"udp,omitempty"`
Plugin string `proxy:"plugin,omitempty"` Plugin string `proxy:"plugin,omitempty"`
PluginOpts map[string]interface{} `proxy:"plugin-opts,omitempty"` PluginOpts map[string]any `proxy:"plugin-opts,omitempty"`
} }
type simpleObfsOption struct { type simpleObfsOption struct {

View file

@ -23,13 +23,13 @@ type Snell struct {
type SnellOption struct { type SnellOption struct {
BasicOption BasicOption
Name string `proxy:"name"` Name string `proxy:"name"`
Server string `proxy:"server"` Server string `proxy:"server"`
Port int `proxy:"port"` Port int `proxy:"port"`
Psk string `proxy:"psk"` Psk string `proxy:"psk"`
UDP bool `proxy:"udp,omitempty"` UDP bool `proxy:"udp,omitempty"`
Version int `proxy:"version,omitempty"` Version int `proxy:"version,omitempty"`
ObfsOpts map[string]interface{} `proxy:"obfs-opts,omitempty"` ObfsOpts map[string]any `proxy:"obfs-opts,omitempty"`
} }
type streamOption struct { type streamOption struct {

View file

@ -97,12 +97,11 @@ func (f *Fallback) SupportUDP() bool {
// MarshalJSON implements C.ProxyAdapter // MarshalJSON implements C.ProxyAdapter
func (f *Fallback) MarshalJSON() ([]byte, error) { func (f *Fallback) MarshalJSON() ([]byte, error) {
all := make([]string, 0) var all []string
for _, proxy := range f.proxies(false) { for _, proxy := range f.proxies(false) {
all = append(all, proxy.Name()) all = append(all, proxy.Name())
} }
return json.Marshal(map[string]any{
return json.Marshal(map[string]interface{}{
"type": f.Type().String(), "type": f.Type().String(),
"now": f.Now(), "now": f.Now(),
"all": all, "all": all,
@ -116,8 +115,8 @@ func (f *Fallback) Unwrap(metadata *C.Metadata) C.Proxy {
} }
func (f *Fallback) proxies(touch bool) []C.Proxy { func (f *Fallback) proxies(touch bool) []C.Proxy {
elm, _, _ := f.single.Do(func() (interface{}, error) { elm, _, _ := f.single.Do(func() (any, error) {
return getProvidersProxies(f.providers, touch, f.filter), nil return getProvidersProxies(f.providers, touch), nil
}) })
return elm.([]C.Proxy) return elm.([]C.Proxy)

View file

@ -30,7 +30,7 @@ type LoadBalance struct {
var errStrategy = errors.New("unsupported strategy") 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 elm, ok := config["strategy"]; ok {
if strategy, ok := elm.(string); ok { if strategy, ok := elm.(string); ok {
return strategy return strategy
@ -141,7 +141,7 @@ func (lb *LoadBalance) Unwrap(metadata *C.Metadata) C.Proxy {
} }
func (lb *LoadBalance) proxies(touch bool) []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 return getProvidersProxies(lb.providers, touch, lb.filter), nil
}) })
@ -150,13 +150,11 @@ func (lb *LoadBalance) proxies(touch bool) []C.Proxy {
// MarshalJSON implements C.ProxyAdapter // MarshalJSON implements C.ProxyAdapter
func (lb *LoadBalance) MarshalJSON() ([]byte, error) { func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
all := make([]string, 0) var all []string
for _, proxy := range lb.proxies(false) { for _, proxy := range lb.proxies(false) {
all = append(all, proxy.Name()) all = append(all, proxy.Name())
} }
return json.Marshal(map[string]any{
return json.Marshal(map[string]interface{}{
"type": lb.Type().String(), "type": lb.Type().String(),
"all": all, "all": all,
}) })

View file

@ -32,7 +32,7 @@ type GroupCommonOption struct {
Filter string `group:"filter,omitempty"` 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}) decoder := structure.NewDecoder(structure.Option{TagName: "group", WeaklyTypedInput: true})
groupOption := &GroupCommonOption{ groupOption := &GroupCommonOption{

View file

@ -69,20 +69,18 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
// MarshalJSON implements C.ProxyAdapter // MarshalJSON implements C.ProxyAdapter
func (r *Relay) MarshalJSON() ([]byte, error) { func (r *Relay) MarshalJSON() ([]byte, error) {
all := make([]string, 0) var all []string
for _, proxy := range r.rawProxies(false) { for _, proxy := range r.rawProxies(false) {
all = append(all, proxy.Name()) all = append(all, proxy.Name())
} }
return json.Marshal(map[string]any{
return json.Marshal(map[string]interface{}{
"type": r.Type().String(), "type": r.Type().String(),
"all": all, "all": all,
}) })
} }
func (r *Relay) rawProxies(touch bool) []C.Proxy { 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 return getProvidersProxies(r.providers, touch, r.filter), nil
}) })

View file

@ -50,13 +50,12 @@ func (s *Selector) SupportUDP() bool {
// MarshalJSON implements C.ProxyAdapter // MarshalJSON implements C.ProxyAdapter
func (s *Selector) MarshalJSON() ([]byte, error) { func (s *Selector) MarshalJSON() ([]byte, error) {
all := make([]string, 0) var all []string
for _, proxy := range getProvidersProxies(s.providers, false, s.filter) { for _, proxy := range getProvidersProxies(s.providers, false, s.filter) {
all = append(all, proxy.Name()) all = append(all, proxy.Name())
} }
return json.Marshal(map[string]interface{}{ return json.Marshal(map[string]any{
"type": s.Type().String(), "type": s.Type().String(),
"now": s.Now(), "now": s.Now(),
"all": all, "all": all,
@ -85,7 +84,7 @@ func (s *Selector) Unwrap(metadata *C.Metadata) C.Proxy {
} }
func (s *Selector) selectedProxy(touch bool) 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) proxies := getProvidersProxies(s.providers, touch, s.filter)
for _, proxy := range proxies { for _, proxy := range proxies {
if proxy.Name() == s.selected { if proxy.Name() == s.selected {

View file

@ -49,7 +49,6 @@ func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata, opts ..
} else { } else {
u.onDialFailed() u.onDialFailed()
} }
return c, err return c, err
} }
@ -63,7 +62,6 @@ func (u *URLTest) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
} else { } else {
u.onDialFailed() u.onDialFailed()
} }
return pc, err return pc, err
} }
@ -73,7 +71,7 @@ func (u *URLTest) Unwrap(metadata *C.Metadata) C.Proxy {
} }
func (u *URLTest) proxies(touch bool) []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 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 { 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) proxies := u.proxies(touch)
fast := proxies[0] fast := proxies[0]
min := fast.LastDelay() min := fast.LastDelay()
@ -125,13 +123,11 @@ func (u *URLTest) SupportUDP() bool {
// MarshalJSON implements C.ProxyAdapter // MarshalJSON implements C.ProxyAdapter
func (u *URLTest) MarshalJSON() ([]byte, error) { func (u *URLTest) MarshalJSON() ([]byte, error) {
all := make([]string, 0) var all []string
for _, proxy := range u.proxies(false) { for _, proxy := range u.proxies(false) {
all = append(all, proxy.Name()) all = append(all, proxy.Name())
} }
return json.Marshal(map[string]any{
return json.Marshal(map[string]interface{}{
"type": u.Type().String(), "type": u.Type().String(),
"now": u.Now(), "now": u.Now(),
"all": all, "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{} opts := []urlTestOption{}
// tolerance // tolerance

View file

@ -8,7 +8,7 @@ import (
C "github.com/Dreamacro/clash/constant" 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}) decoder := structure.NewDecoder(structure.Option{TagName: "proxy", WeaklyTypedInput: true})
proxyType, existType := mapping["type"].(string) proxyType, existType := mapping["type"].(string)
if !existType { if !existType {

View file

@ -16,7 +16,7 @@ var (
dirMode os.FileMode = 0o755 dirMode os.FileMode = 0o755
) )
type parser = func([]byte) (interface{}, error) type parser = func([]byte) (any, error)
type fetcher struct { type fetcher struct {
name string name string
@ -26,7 +26,7 @@ type fetcher struct {
done chan struct{} done chan struct{}
hash [16]byte hash [16]byte
parser parser parser parser
onUpdate func(interface{}) onUpdate func(any)
} }
func (f *fetcher) Name() string { func (f *fetcher) Name() string {
@ -37,7 +37,7 @@ func (f *fetcher) VehicleType() types.VehicleType {
return f.vehicle.Type() return f.vehicle.Type()
} }
func (f *fetcher) Initial() (interface{}, error) { func (f *fetcher) Initial() (any, error) {
var ( var (
buf []byte buf []byte
err error err error
@ -92,7 +92,7 @@ func (f *fetcher) Initial() (interface{}, error) {
return proxies, nil return proxies, nil
} }
func (f *fetcher) Update() (interface{}, bool, error) { func (f *fetcher) Update() (any, bool, error) {
buf, err := f.vehicle.Read() buf, err := f.vehicle.Read()
if err != nil { if err != nil {
return nil, false, err return nil, false, err
@ -168,7 +168,7 @@ func safeWrite(path string, buf []byte) error {
return os.WriteFile(path, buf, fileMode) 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 var ticker *time.Ticker
if interval != 0 { if interval != 0 {
ticker = time.NewTicker(interval) ticker = time.NewTicker(interval)

View file

@ -62,7 +62,7 @@ func (hc *HealthCheck) check() {
b, _ := batch.New(context.Background(), batch.WithConcurrencyNum(10)) b, _ := batch.New(context.Background(), batch.WithConcurrencyNum(10))
for _, proxy := range hc.proxies { for _, proxy := range hc.proxies {
p := proxy p := proxy
b.Go(p.Name(), func() (interface{}, error) { b.Go(p.Name(), func() (any, error) {
ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout) ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout)
defer cancel() defer cancel()
p.URLTest(ctx, hc.url) p.URLTest(ctx, hc.url)

View file

@ -28,7 +28,7 @@ type proxyProviderSchema struct {
HealthCheck healthCheckSchema `provider:"health-check,omitempty"` 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}) decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true})
schema := &proxyProviderSchema{ schema := &proxyProviderSchema{

View file

@ -20,7 +20,7 @@ const (
) )
type ProxySchema struct { type ProxySchema struct {
Proxies []map[string]interface{} `yaml:"proxies"` Proxies []map[string]any `yaml:"proxies"`
} }
// for auto gc // for auto gc
@ -35,7 +35,7 @@ type proxySetProvider struct {
} }
func (pp *proxySetProvider) MarshalJSON() ([]byte, error) { func (pp *proxySetProvider) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{ return json.Marshal(map[string]any{
"name": pp.Name(), "name": pp.Name(),
"type": pp.Type().String(), "type": pp.Type().String(),
"vehicleType": pp.VehicleType().String(), "vehicleType": pp.VehicleType().String(),
@ -112,12 +112,12 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, veh
healthCheck: hc, healthCheck: hc,
} }
onUpdate := func(elm interface{}) { onUpdate := func(elm any) {
ret := elm.([]C.Proxy) ret := elm.([]C.Proxy)
pd.setProxies(ret) pd.setProxies(ret)
} }
proxiesParseAndFilter := func(buf []byte) (interface{}, error) { proxiesParseAndFilter := func(buf []byte) (any, error) {
schema := &ProxySchema{} schema := &ProxySchema{}
if err := yaml.Unmarshal(buf, schema); err != nil { if err := yaml.Unmarshal(buf, schema); err != nil {
@ -172,7 +172,7 @@ type compatibleProvider struct {
} }
func (cp *compatibleProvider) MarshalJSON() ([]byte, error) { func (cp *compatibleProvider) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{ return json.Marshal(map[string]any{
"name": cp.Name(), "name": cp.Name(),
"type": cp.Type().String(), "type": cp.Type().String(),
"vehicleType": cp.VehicleType().String(), "vehicleType": cp.VehicleType().String(),

View file

@ -8,7 +8,7 @@ import (
type Option = func(b *Batch) type Option = func(b *Batch)
type Result struct { type Result struct {
Value interface{} Value any
Err error Err error
} }
@ -38,7 +38,7 @@ type Batch struct {
cancel func() 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) b.wg.Add(1)
go func() { go func() {
defer b.wg.Done() defer b.wg.Done()

View file

@ -14,11 +14,11 @@ func TestBatch(t *testing.T) {
b, _ := New(context.Background()) b, _ := New(context.Background())
now := time.Now() now := time.Now()
b.Go("foo", func() (interface{}, error) { b.Go("foo", func() (any, error) {
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
return "foo", nil return "foo", nil
}) })
b.Go("bar", func() (interface{}, error) { b.Go("bar", func() (any, error) {
time.Sleep(time.Millisecond * 150) time.Sleep(time.Millisecond * 150)
return "bar", nil return "bar", nil
}) })
@ -45,7 +45,7 @@ func TestBatchWithConcurrencyNum(t *testing.T) {
now := time.Now() now := time.Now()
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
idx := i idx := i
b.Go(strconv.Itoa(idx), func() (interface{}, error) { b.Go(strconv.Itoa(idx), func() (any, error) {
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
return strconv.Itoa(idx), nil return strconv.Itoa(idx), nil
}) })
@ -64,12 +64,12 @@ func TestBatchWithConcurrencyNum(t *testing.T) {
func TestBatchContext(t *testing.T) { func TestBatchContext(t *testing.T) {
b, ctx := New(context.Background()) b, ctx := New(context.Background())
b.Go("error", func() (interface{}, error) { b.Go("error", func() (any, error) {
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
return nil, errors.New("test error") return nil, errors.New("test error")
}) })
b.Go("ctx", func() (interface{}, error) { b.Go("ctx", func() (any, error) {
<-ctx.Done() <-ctx.Done()
return nil, ctx.Err() return nil, ctx.Err()
}) })

10
common/cache/cache.go vendored
View file

@ -18,11 +18,11 @@ type cache struct {
type element struct { type element struct {
Expired time.Time Expired time.Time
Payload interface{} Payload any
} }
// Put element in Cache with its ttl // 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{ c.mapping.Store(key, &element{
Payload: payload, Payload: payload,
Expired: time.Now().Add(ttl), 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 // 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) item, exist := c.mapping.Load(key)
if !exist { if !exist {
return nil return nil
@ -45,7 +45,7 @@ func (c *cache) Get(key interface{}) interface{} {
} }
// GetWithExpire element in Cache with Expire Time // 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) item, exist := c.mapping.Load(key)
if !exist { if !exist {
return return
@ -60,7 +60,7 @@ func (c *cache) GetWithExpire(key interface{}) (payload interface{}, expired tim
} }
func (c *cache) cleanup() { func (c *cache) cleanup() {
c.mapping.Range(func(k, v interface{}) bool { c.mapping.Range(func(k, v any) bool {
key := k.(string) key := k.(string)
elm := v.(*element) elm := v.(*element)
if time.Since(elm.Expired) > 0 { if time.Since(elm.Expired) > 0 {

View file

@ -12,7 +12,7 @@ import (
type Option func(*LruCache) type Option func(*LruCache)
// EvictCallback is used to get a callback when a cache entry is evicted // 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 // WithEvict set the evict callback
func WithEvict(cb EvictCallback) Option { func WithEvict(cb EvictCallback) Option {
@ -57,7 +57,7 @@ type LruCache struct {
maxAge int64 maxAge int64
maxSize int maxSize int
mu sync.Mutex mu sync.Mutex
cache map[interface{}]*list.Element cache map[any]*list.Element
lru *list.List // Front is least-recent lru *list.List // Front is least-recent
updateAgeOnGet bool updateAgeOnGet bool
staleReturn bool staleReturn bool
@ -68,7 +68,7 @@ type LruCache struct {
func NewLRUCache(options ...Option) *LruCache { func NewLRUCache(options ...Option) *LruCache {
lc := &LruCache{ lc := &LruCache{
lru: list.New(), lru: list.New(),
cache: make(map[interface{}]*list.Element), cache: make(map[any]*list.Element),
} }
for _, option := range options { for _, option := range options {
@ -78,9 +78,9 @@ func NewLRUCache(options ...Option) *LruCache {
return lc 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. // 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) entry := c.get(key)
if entry == nil { if entry == nil {
return nil, false return nil, false
@ -90,11 +90,11 @@ func (c *LruCache) Get(key interface{}) (interface{}, bool) {
return value, true 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, // a time.Time Give expected expires,
// and a bool set to true if the key was found. // 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. // 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) entry := c.get(key)
if entry == nil { if entry == nil {
return nil, time.Time{}, false 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 // 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() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -112,8 +112,8 @@ func (c *LruCache) Exist(key interface{}) bool {
return ok return ok
} }
// Set stores the interface{} representation of a response for a given key. // Set stores the any representation of a response for a given key.
func (c *LruCache) Set(key interface{}, value interface{}) { func (c *LruCache) Set(key any, value any) {
expires := int64(0) expires := int64(0)
if c.maxAge > 0 { if c.maxAge > 0 {
expires = time.Now().Unix() + c.maxAge 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)) 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. // 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() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -155,7 +155,7 @@ func (c *LruCache) CloneTo(n *LruCache) {
defer n.mu.Unlock() defer n.mu.Unlock()
n.lru = list.New() 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() { for e := c.lru.Front(); e != nil; e = e.Next() {
elm := e.Value.(*entry) 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() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
@ -188,7 +188,7 @@ func (c *LruCache) get(key interface{}) *entry {
} }
// Delete removes the value associated with a key. // Delete removes the value associated with a key.
func (c *LruCache) Delete(key interface{}) { func (c *LruCache) Delete(key any) {
c.mu.Lock() c.mu.Lock()
if le, ok := c.cache[key]; ok { if le, ok := c.cache[key]; ok {
@ -217,7 +217,7 @@ func (c *LruCache) deleteElement(le *list.Element) {
} }
type entry struct { type entry struct {
key interface{} key any
value interface{} value any
expires int64 expires int64
} }

View file

@ -126,7 +126,7 @@ func TestExist(t *testing.T) {
func TestEvict(t *testing.T) { func TestEvict(t *testing.T) {
temp := 0 temp := 0
evict := func(key interface{}, value interface{}) { evict := func(key any, value any) {
temp = key.(int) + value.(int) temp = key.(int) + value.(int)
} }

View file

@ -1,3 +1,3 @@
package observable package observable
type Iterable <-chan interface{} type Iterable <-chan any

View file

@ -9,8 +9,8 @@ import (
"go.uber.org/atomic" "go.uber.org/atomic"
) )
func iterator(item []interface{}) chan interface{} { func iterator(item []any) chan any {
ch := make(chan interface{}) ch := make(chan any)
go func() { go func() {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
for _, elm := range item { for _, elm := range item {
@ -22,7 +22,7 @@ func iterator(item []interface{}) chan interface{} {
} }
func TestObservable(t *testing.T) { func TestObservable(t *testing.T) {
iter := iterator([]interface{}{1, 2, 3, 4, 5}) iter := iterator([]any{1, 2, 3, 4, 5})
src := NewObservable(iter) src := NewObservable(iter)
data, err := src.Subscribe() data, err := src.Subscribe()
assert.Nil(t, err) assert.Nil(t, err)
@ -34,7 +34,7 @@ func TestObservable(t *testing.T) {
} }
func TestObservable_MultiSubscribe(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) src := NewObservable(iter)
ch1, _ := src.Subscribe() ch1, _ := src.Subscribe()
ch2, _ := src.Subscribe() ch2, _ := src.Subscribe()
@ -42,7 +42,7 @@ func TestObservable_MultiSubscribe(t *testing.T) {
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(2) wg.Add(2)
waitCh := func(ch <-chan interface{}) { waitCh := func(ch <-chan any) {
for range ch { for range ch {
count.Inc() count.Inc()
} }
@ -55,7 +55,7 @@ func TestObservable_MultiSubscribe(t *testing.T) {
} }
func TestObservable_UnSubscribe(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) src := NewObservable(iter)
data, err := src.Subscribe() data, err := src.Subscribe()
assert.Nil(t, err) assert.Nil(t, err)
@ -65,7 +65,7 @@ func TestObservable_UnSubscribe(t *testing.T) {
} }
func TestObservable_SubscribeClosedSource(t *testing.T) { func TestObservable_SubscribeClosedSource(t *testing.T) {
iter := iterator([]interface{}{1}) iter := iterator([]any{1})
src := NewObservable(iter) src := NewObservable(iter)
data, _ := src.Subscribe() data, _ := src.Subscribe()
<-data <-data
@ -75,14 +75,14 @@ func TestObservable_SubscribeClosedSource(t *testing.T) {
} }
func TestObservable_UnSubscribeWithNotExistSubscription(t *testing.T) { func TestObservable_UnSubscribeWithNotExistSubscription(t *testing.T) {
sub := Subscription(make(chan interface{})) sub := Subscription(make(chan any))
iter := iterator([]interface{}{1}) iter := iterator([]any{1})
src := NewObservable(iter) src := NewObservable(iter)
src.UnSubscribe(sub) src.UnSubscribe(sub)
} }
func TestObservable_SubscribeGoroutineLeak(t *testing.T) { 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) src := NewObservable(iter)
max := 100 max := 100
@ -94,7 +94,7 @@ func TestObservable_SubscribeGoroutineLeak(t *testing.T) {
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(max) wg.Add(max)
waitCh := func(ch <-chan interface{}) { waitCh := func(ch <-chan any) {
for range ch { for range ch {
} }
wg.Done() wg.Done()
@ -115,7 +115,7 @@ func TestObservable_SubscribeGoroutineLeak(t *testing.T) {
} }
func Benchmark_Observable_1000(b *testing.B) { func Benchmark_Observable_1000(b *testing.B) {
ch := make(chan interface{}) ch := make(chan any)
o := NewObservable(ch) o := NewObservable(ch)
num := 1000 num := 1000

View file

@ -4,14 +4,14 @@ import (
"sync" "sync"
) )
type Subscription <-chan interface{} type Subscription <-chan any
type Subscriber struct { type Subscriber struct {
buffer chan interface{} buffer chan any
once sync.Once once sync.Once
} }
func (s *Subscriber) Emit(item interface{}) { func (s *Subscriber) Emit(item any) {
s.buffer <- item s.buffer <- item
} }
@ -27,7 +27,7 @@ func (s *Subscriber) Close() {
func newSubscriber() *Subscriber { func newSubscriber() *Subscriber {
sub := &Subscriber{ sub := &Subscriber{
buffer: make(chan interface{}, 200), buffer: make(chan any, 200),
} }
return sub return sub
} }

View file

@ -17,7 +17,7 @@ type Picker struct {
once sync.Once once sync.Once
errOnce sync.Once errOnce sync.Once
result interface{} result any
err error 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, // Wait blocks until all function calls from the Go method have returned,
// then returns the first nil error result (if any) from them. // then returns the first nil error result (if any) from them.
func (p *Picker) Wait() interface{} { func (p *Picker) Wait() any {
p.wg.Wait() p.wg.Wait()
if p.cancel != nil { if p.cancel != nil {
p.cancel() p.cancel()
@ -58,7 +58,7 @@ func (p *Picker) Error() error {
// Go calls the given function in a new goroutine. // 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. // 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) p.wg.Add(1)
go func() { go func() {

View file

@ -8,8 +8,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func sleepAndSend(ctx context.Context, delay int, input interface{}) func() (interface{}, error) { func sleepAndSend(ctx context.Context, delay int, input any) func() (any, error) {
return func() (interface{}, error) { return func() (any, error) {
timer := time.NewTimer(time.Millisecond * time.Duration(delay)) timer := time.NewTimer(time.Millisecond * time.Duration(delay))
select { select {
case <-timer.C: case <-timer.C:

View file

@ -23,7 +23,7 @@ func NewAllocator() *Allocator {
alloc.buffers = make([]sync.Pool, 17) // 1B -> 64K alloc.buffers = make([]sync.Pool, 17) // 1B -> 64K
for k := range alloc.buffers { for k := range alloc.buffers {
i := k i := k
alloc.buffers[k].New = func() interface{} { alloc.buffers[k].New = func() any {
return make([]byte, 1<<uint32(i)) return make([]byte, 1<<uint32(i))
} }
} }

View file

@ -5,7 +5,7 @@ import (
"sync" "sync"
) )
var bufferPool = sync.Pool{New: func() interface{} { return &bytes.Buffer{} }} var bufferPool = sync.Pool{New: func() any { return &bytes.Buffer{} }}
func GetBuffer() *bytes.Buffer { func GetBuffer() *bytes.Buffer {
return bufferPool.Get().(*bytes.Buffer) return bufferPool.Get().(*bytes.Buffer)

View file

@ -6,12 +6,12 @@ import (
// Queue is a simple concurrent safe queue // Queue is a simple concurrent safe queue
type Queue struct { type Queue struct {
items []interface{} items []any
lock sync.RWMutex lock sync.RWMutex
} }
// Put add the item to the queue. // Put add the item to the queue.
func (q *Queue) Put(items ...interface{}) { func (q *Queue) Put(items ...any) {
if len(items) == 0 { if len(items) == 0 {
return return
} }
@ -22,7 +22,7 @@ func (q *Queue) Put(items ...interface{}) {
} }
// Pop returns the head of items. // Pop returns the head of items.
func (q *Queue) Pop() interface{} { func (q *Queue) Pop() any {
if len(q.items) == 0 { if len(q.items) == 0 {
return nil return nil
} }
@ -35,7 +35,7 @@ func (q *Queue) Pop() interface{} {
} }
// Last returns the last of item. // Last returns the last of item.
func (q *Queue) Last() interface{} { func (q *Queue) Last() any {
if len(q.items) == 0 { if len(q.items) == 0 {
return nil return nil
} }
@ -47,8 +47,8 @@ func (q *Queue) Last() interface{} {
} }
// Copy get the copy of queue. // Copy get the copy of queue.
func (q *Queue) Copy() []interface{} { func (q *Queue) Copy() []any {
items := []interface{}{} items := []any{}
q.lock.RLock() q.lock.RLock()
items = append(items, q.items...) items = append(items, q.items...)
q.lock.RUnlock() q.lock.RUnlock()
@ -66,6 +66,6 @@ func (q *Queue) Len() int64 {
// New is a constructor for a new concurrent safe queue. // New is a constructor for a new concurrent safe queue.
func New(hint int64) *Queue { func New(hint int64) *Queue {
return &Queue{ return &Queue{
items: make([]interface{}, 0, hint), items: make([]any, 0, hint),
} }
} }

View file

@ -7,7 +7,7 @@ import (
type call struct { type call struct {
wg sync.WaitGroup wg sync.WaitGroup
val interface{} val any
err error err error
} }
@ -20,13 +20,13 @@ type Single struct {
} }
type Result struct { type Result struct {
Val interface{} Val any
Err error Err error
} }
// Do single.Do likes sync.singleFlight // Do single.Do likes sync.singleFlight
//lint:ignore ST1008 it likes sync.singleFlight //lint:ignore ST1008 it likes sync.singleFlight
func (s *Single) Do(fn func() (interface{}, error)) (v interface{}, err error, shared bool) { func (s *Single) Do(fn func() (any, error)) (v any, err error, shared bool) {
s.mux.Lock() s.mux.Lock()
now := time.Now() now := time.Now()
if now.Before(s.last.Add(s.wait)) { if now.Before(s.last.Add(s.wait)) {

View file

@ -13,7 +13,7 @@ func TestBasic(t *testing.T) {
single := NewSingle(time.Millisecond * 30) single := NewSingle(time.Millisecond * 30)
foo := 0 foo := 0
shardCount := atomic.NewInt32(0) shardCount := atomic.NewInt32(0)
call := func() (interface{}, error) { call := func() (any, error) {
foo++ foo++
time.Sleep(time.Millisecond * 5) time.Sleep(time.Millisecond * 5)
return nil, nil return nil, nil
@ -40,7 +40,7 @@ func TestBasic(t *testing.T) {
func TestTimer(t *testing.T) { func TestTimer(t *testing.T) {
single := NewSingle(time.Millisecond * 30) single := NewSingle(time.Millisecond * 30)
foo := 0 foo := 0
call := func() (interface{}, error) { call := func() (any, error) {
foo++ foo++
return nil, nil return nil, nil
} }
@ -56,7 +56,7 @@ func TestTimer(t *testing.T) {
func TestReset(t *testing.T) { func TestReset(t *testing.T) {
single := NewSingle(time.Millisecond * 30) single := NewSingle(time.Millisecond * 30)
foo := 0 foo := 0
call := func() (interface{}, error) { call := func() (any, error) {
foo++ foo++
return nil, nil return nil, nil
} }

View file

@ -1,5 +1,4 @@
//go:build !linux //go:build !linux
// +build !linux
package sockopt package sockopt

View file

@ -28,8 +28,8 @@ func NewDecoder(option Option) *Decoder {
return &Decoder{option: &option} return &Decoder{option: &option}
} }
// Decode transform a map[string]interface{} to a struct // Decode transform a map[string]any to a struct
func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error { func (d *Decoder) Decode(src map[string]any, dst any) error {
if reflect.TypeOf(dst).Kind() != reflect.Ptr { if reflect.TypeOf(dst).Kind() != reflect.Ptr {
return fmt.Errorf("Decode must recive a ptr struct") return fmt.Errorf("Decode must recive a ptr struct")
} }
@ -45,12 +45,8 @@ func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error {
} }
tag := field.Tag.Get(d.option.TagName) tag := field.Tag.Get(d.option.TagName)
str := strings.SplitN(tag, ",", 2) key, omitKey, found := strings.Cut(tag, ",")
key := str[0] omitempty := found && omitKey == "omitempty"
omitempty := false
if len(str) > 1 {
omitempty = str[1] == "omitempty"
}
value, ok := src[key] value, ok := src[key]
if !ok || value == nil { if !ok || value == nil {
@ -68,7 +64,7 @@ func (d *Decoder) Decode(src map[string]interface{}, dst interface{}) error {
return nil 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() { switch val.Kind() {
case reflect.Int: case reflect.Int:
return d.decodeInt(name, data, val) 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) dataVal := reflect.ValueOf(data)
kind := dataVal.Kind() kind := dataVal.Kind()
switch { switch {
@ -112,7 +108,7 @@ func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) (e
return err 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) dataVal := reflect.ValueOf(data)
kind := dataVal.Kind() kind := dataVal.Kind()
switch { switch {
@ -129,7 +125,7 @@ func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value)
return err 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) dataVal := reflect.ValueOf(data)
kind := dataVal.Kind() kind := dataVal.Kind()
switch { switch {
@ -146,7 +142,7 @@ func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) (
return err 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)) dataVal := reflect.Indirect(reflect.ValueOf(data))
valType := val.Type() valType := val.Type()
valElemType := valType.Elem() valElemType := valType.Elem()
@ -173,7 +169,7 @@ func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value)
return nil 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() valType := val.Type()
valKeyType := valType.Key() valKeyType := valType.Key()
valElemType := valType.Elem() valElemType := valType.Elem()
@ -245,7 +241,7 @@ func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val refle
return nil 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)) dataVal := reflect.Indirect(reflect.ValueOf(data))
// If the type of the value to write to and the data match directly, // 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{}) dataValKeys := make(map[reflect.Value]struct{})
dataValKeysUnused := make(map[interface{}]struct{}) dataValKeysUnused := make(map[any]struct{})
for _, dataValKey := range dataVal.MapKeys() { for _, dataValKey := range dataVal.MapKeys() {
dataValKeys[dataValKey] = struct{}{} dataValKeys[dataValKey] = struct{}{}
dataValKeysUnused[dataValKey.Interface()] = struct{}{} dataValKeysUnused[dataValKey.Interface()] = struct{}{}
@ -398,7 +394,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e
return nil 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) dataVal := reflect.ValueOf(data)
val.Set(dataVal) val.Set(dataVal)
return nil return nil

View file

@ -27,7 +27,7 @@ type BazOptional struct {
} }
func TestStructure_Basic(t *testing.T) { func TestStructure_Basic(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": 1, "foo": 1,
"bar": "test", "bar": "test",
"extra": false, "extra": false,
@ -45,7 +45,7 @@ func TestStructure_Basic(t *testing.T) {
} }
func TestStructure_Slice(t *testing.T) { func TestStructure_Slice(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": 1, "foo": 1,
"bar": []string{"one", "two"}, "bar": []string{"one", "two"},
} }
@ -62,7 +62,7 @@ func TestStructure_Slice(t *testing.T) {
} }
func TestStructure_Optional(t *testing.T) { func TestStructure_Optional(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": 1, "foo": 1,
} }
@ -77,7 +77,7 @@ func TestStructure_Optional(t *testing.T) {
} }
func TestStructure_MissingKey(t *testing.T) { func TestStructure_MissingKey(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": 1, "foo": 1,
} }
@ -87,14 +87,14 @@ func TestStructure_MissingKey(t *testing.T) {
} }
func TestStructure_ParamError(t *testing.T) { func TestStructure_ParamError(t *testing.T) {
rawMap := map[string]interface{}{} rawMap := map[string]any{}
s := Baz{} s := Baz{}
err := decoder.Decode(rawMap, s) err := decoder.Decode(rawMap, s)
assert.NotNilf(t, err, "should throw error: %#v", s) assert.NotNilf(t, err, "should throw error: %#v", s)
} }
func TestStructure_SliceTypeError(t *testing.T) { func TestStructure_SliceTypeError(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": 1, "foo": 1,
"bar": []int{1, 2}, "bar": []int{1, 2},
} }
@ -105,7 +105,7 @@ func TestStructure_SliceTypeError(t *testing.T) {
} }
func TestStructure_WeakType(t *testing.T) { func TestStructure_WeakType(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": "1", "foo": "1",
"bar": []int{1}, "bar": []int{1},
} }
@ -122,7 +122,7 @@ func TestStructure_WeakType(t *testing.T) {
} }
func TestStructure_Nest(t *testing.T) { func TestStructure_Nest(t *testing.T) {
rawMap := map[string]interface{}{ rawMap := map[string]any{
"foo": 1, "foo": 1,
} }

View file

@ -36,7 +36,7 @@ func NewAuthenticator(users []AuthUser) Authenticator {
au.storage.Store(user.User, user.Pass) au.storage.Store(user.User, user.Pass)
} }
usernames := make([]string, 0, len(users)) 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)) usernames = append(usernames, key.(string))
return true return true
}) })

View file

@ -1,5 +1,4 @@
//go:build !linux && !darwin //go:build !linux && !darwin
// +build !linux,!darwin
package dialer package dialer

View file

@ -1,5 +1,4 @@
//go:build linux //go:build linux
// +build linux
package dialer package dialer

View file

@ -1,5 +1,4 @@
//go:build !linux //go:build !linux
// +build !linux
package dialer package dialer

View file

@ -1,5 +1,4 @@
//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows //go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !windows
// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!windows
package dialer package dialer

View file

@ -1,5 +1,4 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package dialer package dialer

View file

@ -23,7 +23,7 @@ var (
var interfaces = singledo.NewSingle(time.Second * 20) var interfaces = singledo.NewSingle(time.Second * 20)
func ResolveInterface(name string) (*Interface, error) { func ResolveInterface(name string) (*Interface, error) {
value, err, _ := interfaces.Do(func() (interface{}, error) { value, err, _ := interfaces.Do(func() (any, error) {
ifaces, err := net.Interfaces() ifaces, err := net.Interfaces()
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -6,17 +6,17 @@ import (
"time" "time"
) )
type Factory = func(context.Context) (interface{}, error) type Factory = func(context.Context) (any, error)
type entry struct { type entry struct {
elm interface{} elm any
time time.Time time time.Time
} }
type Option func(*pool) type Option func(*pool)
// WithEvict set the evict callback // WithEvict set the evict callback
func WithEvict(cb func(interface{})) Option { func WithEvict(cb func(any)) Option {
return func(p *pool) { return func(p *pool) {
p.evict = cb p.evict = cb
} }
@ -32,7 +32,7 @@ func WithAge(maxAge int64) Option {
// WithSize defined max size of Pool // WithSize defined max size of Pool
func WithSize(maxSize int) Option { func WithSize(maxSize int) Option {
return func(p *pool) { 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 { type pool struct {
ch chan interface{} ch chan any
factory Factory factory Factory
evict func(interface{}) evict func(any)
maxAge int64 maxAge int64
} }
func (p *pool) GetContext(ctx context.Context) (interface{}, error) { func (p *pool) GetContext(ctx context.Context) (any, error) {
now := time.Now() now := time.Now()
for { for {
select { 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()) return p.GetContext(context.Background())
} }
func (p *pool) Put(item interface{}) { func (p *pool) Put(item any) {
e := &entry{ e := &entry{
elm: item, elm: item,
time: time.Now(), time: time.Now(),
@ -100,7 +100,7 @@ func recycle(p *Pool) {
func New(factory Factory, options ...Option) *Pool { func New(factory Factory, options ...Option) *Pool {
p := &pool{ p := &pool{
ch: make(chan interface{}, 10), ch: make(chan any, 10),
factory: factory, factory: factory,
} }

View file

@ -10,7 +10,7 @@ import (
func lg() Factory { func lg() Factory {
initial := -1 initial := -1
return func(context.Context) (interface{}, error) { return func(context.Context) (any, error) {
initial++ initial++
return initial, nil return initial, nil
} }
@ -34,7 +34,7 @@ func TestPool_MaxSize(t *testing.T) {
size := 5 size := 5
pool := New(g, WithSize(size)) pool := New(g, WithSize(size))
items := []interface{}{} items := []any{}
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
item, _ := pool.Get() item, _ := pool.Get()

View file

@ -1,8 +1,4 @@
//go:build !darwin && !linux && !windows && (!freebsd || !amd64) //go:build !darwin && !linux && !windows && (!freebsd || !amd64)
// +build !darwin
// +build !linux
// +build !windows
// +build !freebsd !amd64
package process package process

View file

@ -51,7 +51,7 @@ func ValidAndSplitDomain(domain string) ([]string, bool) {
// 3. subdomain.*.example.com // 3. subdomain.*.example.com
// 4. .example.com // 4. .example.com
// 5. +.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) parts, valid := ValidAndSplitDomain(domain)
if !valid { if !valid {
return ErrInvalidDomain return ErrInvalidDomain
@ -68,7 +68,7 @@ func (t *DomainTrie) Insert(domain string, data interface{}) error {
return nil return nil
} }
func (t *DomainTrie) insert(parts []string, data interface{}) { func (t *DomainTrie) insert(parts []string, data any) {
node := t.root node := t.root
// reverse storage domain part to save space // reverse storage domain part to save space
for i := len(parts) - 1; i >= 0; i-- { for i := len(parts) - 1; i >= 0; i-- {

View file

@ -3,7 +3,7 @@ package trie
// Node is the trie's node // Node is the trie's node
type Node struct { type Node struct {
children map[string]*Node children map[string]*Node
Data interface{} Data any
} }
func (n *Node) getChild(s string) *Node { func (n *Node) getChild(s string) *Node {
@ -18,7 +18,7 @@ func (n *Node) addChild(s string, child *Node) {
n.children[s] = child n.children[s] = child
} }
func newNode(data interface{}) *Node { func newNode(data any) *Node {
return &Node{ return &Node{
Data: data, Data: data,
children: map[string]*Node{}, children: map[string]*Node{},

View file

@ -186,8 +186,8 @@ type RawConfig struct {
Tun Tun `yaml:"tun"` Tun Tun `yaml:"tun"`
Experimental Experimental `yaml:"experimental"` Experimental Experimental `yaml:"experimental"`
Profile Profile `yaml:"profile"` Profile Profile `yaml:"profile"`
Proxy []map[string]interface{} `yaml:"proxies"` Proxy []map[string]any `yaml:"proxies"`
ProxyGroup []map[string]interface{} `yaml:"proxy-groups"` ProxyGroup []map[string]any
Rule []string `yaml:"rules"` Rule []string `yaml:"rules"`
Script Script `yaml:"script"` Script Script `yaml:"script"`
} }
@ -216,8 +216,8 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
LogLevel: log.INFO, LogLevel: log.INFO,
Hosts: map[string]string{}, Hosts: map[string]string{},
Rule: []string{}, Rule: []string{},
Proxy: []map[string]interface{}{}, Proxy: []map[string]any{},
ProxyGroup: []map[string]interface{}{}, ProxyGroup: []map[string]any{},
Tun: Tun{ Tun: Tun{
Enable: false, Enable: false,
Stack: "gvisor", Stack: "gvisor",
@ -432,7 +432,19 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
proxies[groupName] = adapter.NewProxy(group) 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 { for _, v := range proxyList {
ps = append(ps, proxies[v]) ps = append(ps, proxies[v])
} }
@ -597,7 +609,7 @@ func parseHosts(cfg *RawConfig) (*trie.DomainTrie, error) {
if ip == nil { if ip == nil {
return nil, fmt.Errorf("%s is not a valid IP", ipStr) 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) { func parseNameServer(servers []string) ([]dns.NameServer, error) {
var nameservers []dns.NameServer nameservers := []dns.NameServer{}
for idx, server := range servers { for idx, server := range servers {
// parse without scheme .e.g 8.8.8.8:53 // 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) { func parseFallbackIPCIDR(ips []string) ([]*net.IPNet, error) {
var ipNets []*net.IPNet ipNets := []*net.IPNet{}
for idx, ip := range ips { for idx, ip := range ips {
_, ipnet, err := net.ParseCIDR(ip) _, 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 { if len(cfg.FakeIPFilter) != 0 {
host = trie.New() host = trie.New()
for _, domain := range cfg.FakeIPFilter { 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 { func parseAuthentication(rawRecords []string) []auth.AuthUser {
users := make([]auth.AuthUser, 0) users := []auth.AuthUser{}
for _, line := range rawRecords { for _, line := range rawRecords {
userData := strings.SplitN(line, ":", 2) if user, pass, found := strings.Cut(line, ":"); found {
if len(userData) == 2 { users = append(users, auth.AuthUser{User: user, Pass: pass})
users = append(users, auth.AuthUser{User: userData[0], Pass: userData[1]})
} }
} }
return users return users

View file

@ -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. // Check if ProxyGroups form DAG(Directed Acyclic Graph), and sort all ProxyGroups by dependency order.
// Meanwhile, record the original index in the config file. // Meanwhile, record the original index in the config file.
// If loop is detected, return an error with location of loop. // 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 { type graphNode struct {
indegree int indegree int
// topological order // topological order
topo int topo int
// the original data in `groupsConfig` // the original data in `groupsConfig`
data map[string]interface{} data map[string]any
// `outdegree` and `from` are used in loop locating // `outdegree` and `from` are used in loop locating
outdegree int outdegree int
option *outboundgroup.GroupCommonOption option *outboundgroup.GroupCommonOption

View file

@ -21,7 +21,7 @@ const (
type DNSMode int type DNSMode int
// UnmarshalYAML unserialize EnhancedMode with yaml // 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 var tp string
if err := unmarshal(&tp); err != nil { if err := unmarshal(&tp); err != nil {
return err return err
@ -35,7 +35,7 @@ func (e *DNSMode) UnmarshalYAML(unmarshal func(interface{}) error) error {
} }
// MarshalYAML serialize EnhancedMode with yaml // MarshalYAML serialize EnhancedMode with yaml
func (e DNSMode) MarshalYAML() (interface{}, error) { func (e DNSMode) MarshalYAML() (any, error) {
return e.String(), nil return e.String(), nil
} }

View file

@ -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) { func (r *Resolver) exchangeWithoutCache(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) {
q := m.Question[0] 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() { defer func() {
if err != nil { if err != nil {
return return
@ -154,7 +154,7 @@ func (r *Resolver) batchExchange(ctx context.Context, clients []dnsClient, m *D.
fast, ctx := picker.WithTimeout(ctx, resolver.DefaultDNSTimeout) fast, ctx := picker.WithTimeout(ctx, resolver.DefaultDNSTimeout)
for _, client := range clients { for _, client := range clients {
r := client r := client
fast.Go(func() (interface{}, error) { fast.Go(func() (any, error) {
m, err := r.ExchangeContext(ctx, m) m, err := r.ExchangeContext(ctx, m)
if err != nil { if err != nil {
return nil, err return nil, err

1
go.mod
View file

@ -53,5 +53,4 @@ require (
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
) )

View file

@ -117,10 +117,10 @@ func authentication(next http.Handler) http.Handler {
} }
header := r.Header.Get("Authorization") header := r.Header.Get("Authorization")
text := strings.SplitN(header, " ", 2) bearer, token, found := strings.Cut(header, " ")
hasInvalidHeader := text[0] != "Bearer" hasInvalidHeader := bearer != "Bearer"
hasInvalidSecret := len(text) != 2 || text[1] != serverSecret hasInvalidSecret := !found || token != serverSecret
if hasInvalidHeader || hasInvalidSecret { if hasInvalidHeader || hasInvalidSecret {
render.Status(r, http.StatusUnauthorized) render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized) render.JSON(w, r, ErrUnauthorized)

View file

@ -108,7 +108,7 @@ func authenticate(request *http.Request, cache *cache.Cache) *http.Response {
return resp return resp
} }
var authed interface{} var authed any
if authed = cache.Get(credential); authed == nil { if authed = cache.Get(credential); authed == nil {
user, pass, err := decodeBasicProxyAuthorization(credential) user, pass, err := decodeBasicProxyAuthorization(credential)
authed = err == nil && authenticator.Verify(user, pass) authed = err == nil && authenticator.Verify(user, pass)

View file

@ -65,10 +65,10 @@ func decodeBasicProxyAuthorization(credential string) (string, string, error) {
return "", "", err return "", "", err
} }
login := strings.Split(string(plain), ":") user, pass, found := strings.Cut(string(plain), ":")
if len(login) != 2 { if !found {
return "", "", errors.New("invalid login") return "", "", errors.New("invalid login")
} }
return login[0], login[1], nil return user, pass, nil
} }

View file

@ -1,5 +1,4 @@
//go:build linux && !386 //go:build linux && !386
// +build linux,!386
package redir package redir

View file

@ -1,5 +1,4 @@
//go:build !darwin && !linux && !freebsd //go:build !darwin && !linux && !freebsd
// +build !darwin,!linux,!freebsd
package redir package redir

View file

@ -1,5 +1,4 @@
//go:build linux //go:build linux
// +build linux
package tproxy package tproxy

View file

@ -1,5 +1,4 @@
//go:build !linux //go:build !linux
// +build !linux
package tproxy package tproxy

View file

@ -1,5 +1,4 @@
//go:build linux //go:build linux
// +build linux
package tproxy package tproxy

View file

@ -1,5 +1,4 @@
//go:build !linux //go:build !linux
// +build !linux
package tproxy package tproxy

View file

@ -25,7 +25,7 @@ const (
type LogLevel int type LogLevel int
// UnmarshalYAML unserialize LogLevel with yaml // 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 var tp string
unmarshal(&tp) unmarshal(&tp)
level, exist := LogLevelMapping[tp] level, exist := LogLevelMapping[tp]
@ -54,7 +54,7 @@ func (l LogLevel) MarshalJSON() ([]byte, error) {
} }
// MarshalYAML serialize LogLevel with yaml // MarshalYAML serialize LogLevel with yaml
func (l LogLevel) MarshalYAML() (interface{}, error) { func (l LogLevel) MarshalYAML() (any, error) {
return l.String(), nil return l.String(), nil
} }

View file

@ -10,7 +10,7 @@ import (
) )
var ( var (
logCh = make(chan interface{}) logCh = make(chan any)
source = observable.NewObservable(logCh) source = observable.NewObservable(logCh)
level = INFO level = INFO
) )
@ -29,31 +29,31 @@ func (e *Event) Type() string {
return e.LogLevel.String() return e.LogLevel.String()
} }
func Infoln(format string, v ...interface{}) { func Infoln(format string, v ...any) {
event := newLog(INFO, format, v...) event := newLog(INFO, format, v...)
logCh <- event logCh <- event
print(event) print(event)
} }
func Warnln(format string, v ...interface{}) { func Warnln(format string, v ...any) {
event := newLog(WARNING, format, v...) event := newLog(WARNING, format, v...)
logCh <- event logCh <- event
print(event) print(event)
} }
func Errorln(format string, v ...interface{}) { func Errorln(format string, v ...any) {
event := newLog(ERROR, format, v...) event := newLog(ERROR, format, v...)
logCh <- event logCh <- event
print(event) print(event)
} }
func Debugln(format string, v ...interface{}) { func Debugln(format string, v ...any) {
event := newLog(DEBUG, format, v...) event := newLog(DEBUG, format, v...)
logCh <- event logCh <- event
print(event) print(event)
} }
func Fatalln(format string, v ...interface{}) { func Fatalln(format string, v ...any) {
log.Fatalf(format, v...) 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{ return &Event{
LogLevel: logLevel, LogLevel: logLevel,
Payload: fmt.Sprintf(format, v...), Payload: fmt.Sprintf(format, v...),

View file

@ -48,7 +48,7 @@ func init() {
} }
func main() { func main() {
_, _ = maxprocs.Set(maxprocs.Logger(func(string, ...interface{}) {})) maxprocs.Set(maxprocs.Logger(func(string, ...any) {}))
if version { if version {
fmt.Printf("Clash Meta %s %s %s with %s %s\n", C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime) fmt.Printf("Clash Meta %s %s %s with %s %s\n", C.Version, runtime.GOOS, runtime.GOARCH, runtime.Version(), C.BuildTime)
return return

View file

@ -1,30 +1,33 @@
module clash-test module clash-test
go 1.17 go 1.18
require ( require (
github.com/Dreamacro/clash v1.7.2-0.20211108085948-bd2ea2b917aa 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/docker/go-connections v0.4.0
github.com/miekg/dns v1.1.45 github.com/miekg/dns v1.1.47
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.1
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f golang.org/x/net v0.0.0-20220225172249-27dd8689420f
) )
replace github.com/Dreamacro/clash => ../ replace github.com/Dreamacro/clash => ../
require ( require (
github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect github.com/Dreamacro/go-shadowsocks2 v0.1.7 // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/containerd/containerd v1.5.8 // indirect github.com/containerd/containerd v1.6.1 // indirect
github.com/davecgh/go-spew v1.1.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/docker/go-units v0.4.0 // indirect
github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect
github.com/gogo/protobuf v1.3.2 // 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/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect github.com/google/btree v1.0.1 // indirect
github.com/gorilla/mux v1.8.0 // 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/gorilla/websocket v1.4.2 // indirect
github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 // indirect github.com/insomniacslk/dhcp v0.0.0-20211214070828-5297eed8f489 // indirect
github.com/kr328/tun2socket v0.0.0-20210412191540-3d56c47e2d99 // 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/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // 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/oschwald/maxminddb-golang v1.8.0 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // 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 github.com/yaling888/go-lwip v0.0.0-20211103185822-c9d650538091 // indirect
go.etcd.io/bbolt v1.3.6 // indirect go.etcd.io/bbolt v1.3.6 // indirect
go.uber.org/atomic v1.9.0 // 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/mod v0.4.2 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect
golang.org/x/text v0.3.6 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // 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/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.43.0 // indirect google.golang.org/grpc v1.45.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect google.golang.org/protobuf v1.27.1 // indirect
golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 // indirect golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42 // indirect
golang.org/x/text v0.3.8-0.20211004125949-5bd84dd9b33b // 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/grpc v1.42.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // 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 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
gvisor.dev/gvisor v0.0.0-20211104052249-2de3450f76d6 // indirect gvisor.dev/gvisor v0.0.0-20211104052249-2de3450f76d6 // indirect
) )

View file

@ -37,7 +37,7 @@ func TestClash_SnellObfsHTTP(t *testing.T) {
Server: localIP.String(), Server: localIP.String(),
Port: 10002, Port: 10002,
Psk: "password", Psk: "password",
ObfsOpts: map[string]interface{}{ ObfsOpts: map[string]any{
"mode": "http", "mode": "http",
}, },
}) })
@ -74,7 +74,7 @@ func TestClash_SnellObfsTLS(t *testing.T) {
Server: localIP.String(), Server: localIP.String(),
Port: 10002, Port: 10002,
Psk: "password", Psk: "password",
ObfsOpts: map[string]interface{}{ ObfsOpts: map[string]any{
"mode": "tls", "mode": "tls",
}, },
}) })
@ -181,7 +181,7 @@ func Benchmark_Snell(b *testing.B) {
Server: localIP.String(), Server: localIP.String(),
Port: 10002, Port: 10002,
Psk: "password", Psk: "password",
ObfsOpts: map[string]interface{}{ ObfsOpts: map[string]any{
"mode": "http", "mode": "http",
}, },
}) })

View file

@ -76,7 +76,7 @@ func TestClash_ShadowsocksObfsHTTP(t *testing.T) {
Cipher: "chacha20-ietf-poly1305", Cipher: "chacha20-ietf-poly1305",
UDP: true, UDP: true,
Plugin: "obfs", Plugin: "obfs",
PluginOpts: map[string]interface{}{ PluginOpts: map[string]any{
"mode": "http", "mode": "http",
}, },
}) })
@ -118,7 +118,7 @@ func TestClash_ShadowsocksObfsTLS(t *testing.T) {
Cipher: "chacha20-ietf-poly1305", Cipher: "chacha20-ietf-poly1305",
UDP: true, UDP: true,
Plugin: "obfs", Plugin: "obfs",
PluginOpts: map[string]interface{}{ PluginOpts: map[string]any{
"mode": "tls", "mode": "tls",
}, },
}) })
@ -160,7 +160,7 @@ func TestClash_ShadowsocksV2RayPlugin(t *testing.T) {
Cipher: "chacha20-ietf-poly1305", Cipher: "chacha20-ietf-poly1305",
UDP: true, UDP: true,
Plugin: "v2ray-plugin", Plugin: "v2ray-plugin",
PluginOpts: map[string]interface{}{ PluginOpts: map[string]any{
"mode": "websocket", "mode": "websocket",
}, },
}) })

View file

@ -1,5 +1,4 @@
//go:build !darwin //go:build !darwin
// +build !darwin
package main package main

View file

@ -71,12 +71,12 @@ func (pc *PoolConn) Close() error {
func NewPool(factory func(context.Context) (*Snell, error)) *Pool { func NewPool(factory func(context.Context) (*Snell, error)) *Pool {
p := pool.New( p := pool.New(
func(ctx context.Context) (interface{}, error) { func(ctx context.Context) (any, error) {
return factory(ctx) return factory(ctx)
}, },
pool.WithAge(15000), pool.WithAge(15000),
pool.WithSize(10), pool.WithSize(10),
pool.WithEvict(func(item interface{}) { pool.WithEvict(func(item any) {
item.(*Snell).Close() item.(*Snell).Close()
}), }),
) )

View file

@ -36,7 +36,7 @@ func (m *TunnelMode) UnmarshalJSON(data []byte) error {
} }
// UnmarshalYAML unserialize Mode with yaml // 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 var tp string
unmarshal(&tp) unmarshal(&tp)
mode, exist := ModeMapping[strings.ToLower(tp)] mode, exist := ModeMapping[strings.ToLower(tp)]
@ -53,7 +53,7 @@ func (m TunnelMode) MarshalJSON() ([]byte, error) {
} }
// MarshalYAML serialize TunnelMode with yaml // MarshalYAML serialize TunnelMode with yaml
func (m TunnelMode) MarshalYAML() (interface{}, error) { func (m TunnelMode) MarshalYAML() (any, error) {
return m.String(), nil return m.String(), nil
} }

View file

@ -56,7 +56,7 @@ func (m *Manager) Now() (up int64, down int64) {
func (m *Manager) Snapshot() *Snapshot { func (m *Manager) Snapshot() *Snapshot {
connections := []tracker{} connections := []tracker{}
m.connections.Range(func(key, value interface{}) bool { m.connections.Range(func(key, value any) bool {
connections = append(connections, value.(tracker)) connections = append(connections, value.(tracker))
return true return true
}) })