Skip to content

Commit 55340be

Browse files
mapleafgoclaude
andcommitted
refactor: Go 1.26 语法现代化与代码质量提升
- 使用 range-over-integer 替换传统 for 循环 (Go 1.22+) - 修复 service.go:145 缩进错误(缺一层 tab) - 简化 GetBool 为单行 type assertion(11行→3行) - 提取 IFF 标志位、group 上限、hop interval 为命名常量 - max_early_data 使用 math.MaxUint32 替代魔法数字(匹配 sing-box uint32 类型) - 移除 translateWS 和 applyMultiplex 的未使用参数 - gofmt 统一全项目格式化 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 3d1e3d4 commit 55340be

20 files changed

Lines changed: 222 additions & 199 deletions

core/core_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ func TestServiceDoubleInit(t *testing.T) {
208208
tmpDir := t.TempDir()
209209
svc := NewService()
210210

211-
if err := svc.Init(initJSON(filepath.Join(tmpDir, "home1"))); err != nil { t.Fatalf("first Init: %v", err)
211+
if err := svc.Init(initJSON(filepath.Join(tmpDir, "home1"))); err != nil {
212+
t.Fatalf("first Init: %v", err)
212213
}
213214
if err := svc.Init(initJSON(filepath.Join(tmpDir, "home2"))); err == nil {
214215
t.Fatal("second Init on same instance should return error")

core/handler.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ import (
99

1010
// Event type constants passed to the onEvent callback.
1111
const (
12-
EventTraffic = 0
13-
EventLogs = 1
14-
EventConnections = 2
15-
EventProxyUpdate = 3
16-
EventModeUpdate = 4
17-
EventCoreLog = 6
12+
EventTraffic = 0
13+
EventLogs = 1
14+
EventConnections = 2
15+
EventProxyUpdate = 3
16+
EventModeUpdate = 4
17+
EventCoreLog = 6
1818
EventConnected = 7
1919
EventDisconnected = 8
2020
)

core/handler_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ type mockLogIterator struct {
1414
index int
1515
}
1616

17-
func (m *mockLogIterator) Len() int32 { return int32(len(m.items)) }
18-
func (m *mockLogIterator) HasNext() bool { return m.index < len(m.items) }
17+
func (m *mockLogIterator) Len() int32 { return int32(len(m.items)) }
18+
func (m *mockLogIterator) HasNext() bool { return m.index < len(m.items) }
1919
func (m *mockLogIterator) Next() *libbox.LogEntry {
2020
if m.index >= len(m.items) {
2121
return nil
@@ -128,11 +128,11 @@ func TestHandler_WriteLogsLevelFilter(t *testing.T) {
128128

129129
h.WriteLogs(&mockLogIterator{
130130
items: []*libbox.LogEntry{
131-
{Level: 2, Message: "error"}, // Error → pass
132-
{Level: 3, Message: "warn"}, // Warn → pass
133-
{Level: 4, Message: "info"}, // Info → pass
134-
{Level: 5, Message: "debug"}, // Debug → filtered
135-
{Level: 6, Message: "trace"}, // Trace → filtered
131+
{Level: 2, Message: "error"}, // Error → pass
132+
{Level: 3, Message: "warn"}, // Warn → pass
133+
{Level: 4, Message: "info"}, // Info → pass
134+
{Level: 5, Message: "debug"}, // Debug → filtered
135+
{Level: 6, Message: "trace"}, // Trace → filtered
136136
},
137137
})
138138

core/logging.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ func (h *coreLogHandler) Handle(_ context.Context, r slog.Record) error {
7373
fmt.Fprintln(os.Stderr, b.String())
7474

7575
entry := LogEntry{
76-
Level: slogToCoreLevel(r.Level),
77-
Message: b.String(),
76+
Level: slogToCoreLevel(r.Level),
77+
Message: b.String(),
7878
Timestamp: r.Time.UnixMilli(),
7979
}
8080

@@ -183,7 +183,7 @@ func queryCoreLogEntries() []LogEntry {
183183
}
184184
entries := make([]LogEntry, 0, coreLogLen)
185185
start := (coreLogPos - coreLogLen + maxCoreLogEntries) % maxCoreLogEntries
186-
for i := 0; i < coreLogLen; i++ {
186+
for i := range coreLogLen {
187187
entries = append(entries, coreLogRing[(start+i)%maxCoreLogEntries])
188188
}
189189
return entries

core/platform.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ type PlatformIO struct {
2727
// Socket protector from mobile platform (Android VpnService.protect).
2828
protectFn func(fd int32) bool
2929

30+
// noProtectorLogged suppresses repeated "no socket protector" warnings.
31+
noProtectorLogged bool
32+
3033
// Interface data from mobile platform (JSON string).
3134
interfacesJSON string
3235

@@ -85,6 +88,7 @@ func (p *PlatformIO) SetSocketProtector(fn func(fd int32) bool) {
8588
defer p.mu.Unlock()
8689
slog.Debug("[SetSocketProtector]", "registered", fn != nil)
8790
p.protectFn = fn
91+
p.noProtectorLogged = false
8892
}
8993

9094
// SetIncludeAllNetworks sets whether the VPN configuration uses includeAllNetworks (iOS).
@@ -150,8 +154,9 @@ func (p *PlatformIO) AutoDetectInterfaceControl(fd int32) error {
150154
if !ok {
151155
return fmt.Errorf("protect fd %d failed", fd)
152156
}
153-
} else {
154-
slog.Warn("AutoDetectInterfaceControl: no socket protector", "fd", fd)
157+
} else if !p.noProtectorLogged {
158+
p.noProtectorLogged = true
159+
slog.Warn("AutoDetectInterfaceControl: no socket protector registered, subsequent warnings suppressed")
155160
}
156161
return nil
157162
}
@@ -362,7 +367,7 @@ func detectDefaultInterface(ctx context.Context, listener libbox.InterfaceUpdate
362367
return
363368
}
364369
targets := []string{"8.8.8.8:53", "1.1.1.1:53"}
365-
for attempt := 0; attempt < 5; attempt++ {
370+
for attempt := range 5 {
366371
select {
367372
case <-ctx.Done():
368373
slog.Debug("detect interface: cancelled")
@@ -451,6 +456,16 @@ func parseInterfacesJSON(jsonStr string) (libbox.NetworkInterfaceIterator, error
451456
return &networkInterfaceIterator{items: result}, nil
452457
}
453458

459+
// POSIX network interface flag bits (decimal values for cross-platform portability).
460+
const (
461+
iffUP int32 = 0x1
462+
iffBroadcast int32 = 0x2
463+
iffLoopback int32 = 0x8
464+
iffPointToPoint int32 = 0x10
465+
iffRunning int32 = 0x40
466+
iffMulticast int32 = 0x1000
467+
)
468+
454469
func buildDesktopInterfaces(ifaces []net.Interface) (libbox.NetworkInterfaceIterator, error) {
455470
var result []*libbox.NetworkInterface
456471
for _, iface := range ifaces {
@@ -469,22 +484,22 @@ func buildDesktopInterfaces(ifaces []net.Interface) (libbox.NetworkInterfaceIter
469484

470485
var flags int32
471486
if iface.Flags&net.FlagUp != 0 {
472-
flags |= 0x1 // IFF_UP
487+
flags |= iffUP
473488
}
474489
if iface.Flags&net.FlagRunning != 0 {
475-
flags |= 0x40 // IFF_RUNNING
490+
flags |= iffRunning
476491
}
477492
if iface.Flags&net.FlagBroadcast != 0 {
478-
flags |= 0x2 // IFF_BROADCAST
493+
flags |= iffBroadcast
479494
}
480495
if iface.Flags&net.FlagLoopback != 0 {
481-
flags |= 0x8 // IFF_LOOPBACK
496+
flags |= iffLoopback
482497
}
483498
if iface.Flags&net.FlagPointToPoint != 0 {
484-
flags |= 0x10 // IFF_POINTOPOINT
499+
flags |= iffPointToPoint
485500
}
486501
if iface.Flags&net.FlagMulticast != 0 {
487-
flags |= 0x1000 // IFF_MULTICAST
502+
flags |= iffMulticast
488503
}
489504

490505
result = append(result, &libbox.NetworkInterface{

core/platform_test.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -543,25 +543,25 @@ func TestResetTunFd_ClearsCachedOptions(t *testing.T) {
543543

544544
type noOpTunOptions struct{}
545545

546-
func (noOpTunOptions) GetInet4Address() libbox.RoutePrefixIterator { return nil }
547-
func (noOpTunOptions) GetInet6Address() libbox.RoutePrefixIterator { return nil }
548-
func (noOpTunOptions) GetDNSServerAddress() (*libbox.StringBox, error) { return nil, nil }
549-
func (noOpTunOptions) GetMTU() int32 { return 0 }
550-
func (noOpTunOptions) GetAutoRoute() bool { return false }
551-
func (noOpTunOptions) GetStrictRoute() bool { return false }
552-
func (noOpTunOptions) GetInet4RouteAddress() libbox.RoutePrefixIterator { return nil }
553-
func (noOpTunOptions) GetInet6RouteAddress() libbox.RoutePrefixIterator { return nil }
554-
func (noOpTunOptions) GetInet4RouteExcludeAddress() libbox.RoutePrefixIterator { return nil }
555-
func (noOpTunOptions) GetInet6RouteExcludeAddress() libbox.RoutePrefixIterator { return nil }
556-
func (noOpTunOptions) GetInet4RouteRange() libbox.RoutePrefixIterator { return nil }
557-
func (noOpTunOptions) GetInet6RouteRange() libbox.RoutePrefixIterator { return nil }
558-
func (noOpTunOptions) GetIncludePackage() libbox.StringIterator { return nil }
559-
func (noOpTunOptions) GetExcludePackage() libbox.StringIterator { return nil }
560-
func (noOpTunOptions) IsHTTPProxyEnabled() bool { return false }
561-
func (noOpTunOptions) GetHTTPProxyServer() string { return "" }
562-
func (noOpTunOptions) GetHTTPProxyServerPort() int32 { return 0 }
563-
func (noOpTunOptions) GetHTTPProxyBypassDomain() libbox.StringIterator { return nil }
564-
func (noOpTunOptions) GetHTTPProxyMatchDomain() libbox.StringIterator { return nil }
546+
func (noOpTunOptions) GetInet4Address() libbox.RoutePrefixIterator { return nil }
547+
func (noOpTunOptions) GetInet6Address() libbox.RoutePrefixIterator { return nil }
548+
func (noOpTunOptions) GetDNSServerAddress() (*libbox.StringBox, error) { return nil, nil }
549+
func (noOpTunOptions) GetMTU() int32 { return 0 }
550+
func (noOpTunOptions) GetAutoRoute() bool { return false }
551+
func (noOpTunOptions) GetStrictRoute() bool { return false }
552+
func (noOpTunOptions) GetInet4RouteAddress() libbox.RoutePrefixIterator { return nil }
553+
func (noOpTunOptions) GetInet6RouteAddress() libbox.RoutePrefixIterator { return nil }
554+
func (noOpTunOptions) GetInet4RouteExcludeAddress() libbox.RoutePrefixIterator { return nil }
555+
func (noOpTunOptions) GetInet6RouteExcludeAddress() libbox.RoutePrefixIterator { return nil }
556+
func (noOpTunOptions) GetInet4RouteRange() libbox.RoutePrefixIterator { return nil }
557+
func (noOpTunOptions) GetInet6RouteRange() libbox.RoutePrefixIterator { return nil }
558+
func (noOpTunOptions) GetIncludePackage() libbox.StringIterator { return nil }
559+
func (noOpTunOptions) GetExcludePackage() libbox.StringIterator { return nil }
560+
func (noOpTunOptions) IsHTTPProxyEnabled() bool { return false }
561+
func (noOpTunOptions) GetHTTPProxyServer() string { return "" }
562+
func (noOpTunOptions) GetHTTPProxyServerPort() int32 { return 0 }
563+
func (noOpTunOptions) GetHTTPProxyBypassDomain() libbox.StringIterator { return nil }
564+
func (noOpTunOptions) GetHTTPProxyMatchDomain() libbox.StringIterator { return nil }
565565

566566
// --- WiFi state ---
567567

core/service.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ func resetLibboxForTesting() {
8484
// └── Stop ←─────────────────────────────────────────────────────┘
8585
// Destroy is terminal; the instance cannot be reused.
8686
type Service struct {
87-
mu sync.Mutex
88-
state State
89-
commandServer *libbox.CommandServer
90-
commandClient *libbox.CommandClient
91-
handler *ClientHandler
92-
platformIO *PlatformIO
87+
mu sync.Mutex
88+
state State
89+
commandServer *libbox.CommandServer
90+
commandClient *libbox.CommandClient
91+
handler *ClientHandler
92+
platformIO *PlatformIO
9393
currentConfig string // translated sing-box JSON (kept for ReloadTUN)
9494
overrideAutoRoute bool
9595
overrideInclude []string
@@ -142,7 +142,7 @@ func (s *Service) Init(optionsJSON string) error {
142142
return fmt.Errorf("create temp dir: %w", err)
143143
}
144144

145-
if !libboxReady {
145+
if !libboxReady {
146146
slog.Debug("[init] calling libbox.Setup")
147147
if err := libbox.Setup(&libbox.SetupOptions{
148148
BasePath: opts.HomeDir,

core/types.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -71,25 +71,25 @@ type ConnectionEventSnapshot struct {
7171

7272
// TunOptionsSnapshot is a JSON-serializable snapshot of TUN configuration.
7373
type TunOptionsSnapshot struct {
74-
Inet4Address []string `json:"inet4_address,omitempty"`
75-
Inet6Address []string `json:"inet6_address,omitempty"`
76-
DNSServerAddress string `json:"dns_server_address,omitempty"`
77-
MTU int32 `json:"mtu"`
78-
AutoRoute bool `json:"auto_route"`
79-
StrictRoute bool `json:"strict_route"`
80-
Inet4RouteAddress []string `json:"inet4_route_address,omitempty"`
81-
Inet6RouteAddress []string `json:"inet6_route_address,omitempty"`
82-
Inet4RouteExcludeAddress []string `json:"inet4_route_exclude_address,omitempty"`
83-
Inet6RouteExcludeAddress []string `json:"inet6_route_exclude_address,omitempty"`
84-
Inet4RouteRange []string `json:"inet4_route_range,omitempty"`
85-
Inet6RouteRange []string `json:"inet6_route_range,omitempty"`
86-
IncludePackage []string `json:"include_package,omitempty"`
87-
ExcludePackage []string `json:"exclude_package,omitempty"`
88-
HTTPProxyEnabled bool `json:"http_proxy_enabled"`
89-
HTTPProxyServer string `json:"http_proxy_server,omitempty"`
90-
HTTPProxyServerPort int32 `json:"http_proxy_server_port,omitempty"`
91-
HTTPProxyBypassDomain []string `json:"http_proxy_bypass_domain,omitempty"`
92-
HTTPProxyMatchDomain []string `json:"http_proxy_match_domain,omitempty"`
74+
Inet4Address []string `json:"inet4_address,omitempty"`
75+
Inet6Address []string `json:"inet6_address,omitempty"`
76+
DNSServerAddress string `json:"dns_server_address,omitempty"`
77+
MTU int32 `json:"mtu"`
78+
AutoRoute bool `json:"auto_route"`
79+
StrictRoute bool `json:"strict_route"`
80+
Inet4RouteAddress []string `json:"inet4_route_address,omitempty"`
81+
Inet6RouteAddress []string `json:"inet6_route_address,omitempty"`
82+
Inet4RouteExcludeAddress []string `json:"inet4_route_exclude_address,omitempty"`
83+
Inet6RouteExcludeAddress []string `json:"inet6_route_exclude_address,omitempty"`
84+
Inet4RouteRange []string `json:"inet4_route_range,omitempty"`
85+
Inet6RouteRange []string `json:"inet6_route_range,omitempty"`
86+
IncludePackage []string `json:"include_package,omitempty"`
87+
ExcludePackage []string `json:"exclude_package,omitempty"`
88+
HTTPProxyEnabled bool `json:"http_proxy_enabled"`
89+
HTTPProxyServer string `json:"http_proxy_server,omitempty"`
90+
HTTPProxyServerPort int32 `json:"http_proxy_server_port,omitempty"`
91+
HTTPProxyBypassDomain []string `json:"http_proxy_bypass_domain,omitempty"`
92+
HTTPProxyMatchDomain []string `json:"http_proxy_match_domain,omitempty"`
9393
}
9494

9595
// OverrideConfig holds override options for VPN split tunneling.

translator/general_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ func TestTranslateGeneralMultiplePorts(t *testing.T) {
100100
}
101101

102102
wantTypes := []struct {
103-
typ string
104-
tag string
103+
typ string
104+
tag string
105105
port int
106106
}{
107107
{"mixed", "mixed-in", 7890},
@@ -125,9 +125,9 @@ func TestTranslateGeneralMultiplePorts(t *testing.T) {
125125

126126
func TestTranslateGeneralFindProcess(t *testing.T) {
127127
tests := []struct {
128-
name string
129-
mode string
130-
want bool
128+
name string
129+
mode string
130+
want bool
131131
}{
132132
{"always enables find_process", "always", true},
133133
{"strict enables find_process", "strict", true},
@@ -154,7 +154,7 @@ func TestTranslateGeneralFindProcess(t *testing.T) {
154154

155155
func TestTranslateGeneralInterface(t *testing.T) {
156156
cfg := &RawConfig{
157-
Interface: "eth0",
157+
Interface: "eth0",
158158
RoutingMark: 1234,
159159
}
160160
result := &singboxConfig{}

translator/group.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package translator
22

33
import (
4+
"math"
5+
46
"github.com/mapleafgo/singcast/translator/proxy"
57
)
68

9+
const (
10+
maxGroupInterval = 86400 // 24 hours
11+
maxGroupIdleTimeout = 1800 // 30 minutes
12+
maxTolerance = math.MaxUint16
13+
)
14+
715
// translateGroups translates mihomo proxy-groups to sing-box outbounds.
816
// proxyOutbounds are the already-translated proxy outbounds (not used directly,
917
// but the proxy tags are available via t.proxyTags for filtering).
@@ -101,12 +109,12 @@ func translateURLTestGroup(name string, proxies []string, g map[string]any) map[
101109
"outbounds": proxies,
102110
"url": url,
103111
"interval": proxy.SecondsToDuration(interval),
104-
"idle_timeout": proxy.SecondsToDuration(max(interval, 1800)),
112+
"idle_timeout": proxy.SecondsToDuration(max(interval, maxGroupIdleTimeout)),
105113
"interrupt_exist_connections": true,
106114
}
107115

108116
if tol, ok := toInt(g["tolerance"]); ok && tol > 0 {
109-
result["tolerance"] = min(tol, 65535)
117+
result["tolerance"] = min(tol, maxTolerance)
110118
}
111119

112120
return result
@@ -121,8 +129,8 @@ func translateFallbackGroup(name string, proxies []string, g map[string]any) map
121129
"outbounds": proxies,
122130
"url": url,
123131
"interval": proxy.SecondsToDuration(interval),
124-
"idle_timeout": proxy.SecondsToDuration(max(interval, 1800)),
125-
"tolerance": 65535, // uint16 max, approx 65s
132+
"idle_timeout": proxy.SecondsToDuration(max(interval, maxGroupIdleTimeout)),
133+
"tolerance": maxTolerance,
126134
"interrupt_exist_connections": true,
127135
}
128136
}
@@ -134,7 +142,7 @@ func groupURLDefaults(g map[string]any) (string, int) {
134142
}
135143
interval := 180
136144
if iv, ok := toInt(g["interval"]); ok && iv > 0 {
137-
interval = min(iv, 86400)
145+
interval = min(iv, maxGroupInterval)
138146
}
139147
return url, interval
140148
}

0 commit comments

Comments
 (0)