From 1c0b76c27a3f77ec62a9528c91f7a4ae8c75952a Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Tue, 23 Jun 2026 14:12:28 +0200 Subject: [PATCH] Use efficient APIs and simplify loops Minor refactors across the codebase to improve readability and use more efficient APIs: replace fmt.Sprintf+base64 encoding with fmt.Appendf when building Shadowsocks userInfo; compute elapsed using max(now-prev.at, window) to simplify logic; use strings.SplitSeq for splitting in two places; simplify test and goroutine loops to range-based iterations and use errgroup's Go helper; and align/clean up struct field formatting and test map literals. Mostly stylistic/efficiency changes with no intended behavior changes. --- internal/sub/clash_service_test.go | 58 +++++++++++------------ internal/sub/service.go | 2 +- internal/web/entity/entity.go | 40 ++++++++-------- internal/web/job/node_traffic_sync_job.go | 5 +- internal/web/service/server.go | 2 +- internal/web/web.go | 2 +- internal/xray/log_writer_race_test.go | 8 ++-- internal/xray/process_race_test.go | 14 ++---- 8 files changed, 62 insertions(+), 69 deletions(-) diff --git a/internal/sub/clash_service_test.go b/internal/sub/clash_service_test.go index 8bbb15844..cdcb55f1e 100644 --- a/internal/sub/clash_service_test.go +++ b/internal/sub/clash_service_test.go @@ -320,33 +320,33 @@ func TestBuildProxy_VLESSNoneEncryptionOmittedForClash(t *testing.T) { func TestBuildXhttpClashOpts_FullFieldMapping(t *testing.T) { xhttp := map[string]any{ - "path": "/api/v1", - "mode": "stream-up", - "host": "example.com", - "xPaddingBytes": "100-1000", - "xPaddingObfsMode": true, - "xPaddingKey": "mykey", - "xPaddingHeader": "X-Trace-ID", - "xPaddingPlacement": "queryInHeader", - "xPaddingMethod": "tokenish", - "uplinkHTTPMethod": "POST", - "sessionPlacement": "query", - "sessionKey": "sess", - "seqPlacement": "header", - "seqKey": "seq", - "uplinkDataPlacement": "body", - "uplinkDataKey": "udata", - "uplinkChunkSize": "64-256", - "noGRPCHeader": true, - "scMaxEachPostBytes": "500000", + "path": "/api/v1", + "mode": "stream-up", + "host": "example.com", + "xPaddingBytes": "100-1000", + "xPaddingObfsMode": true, + "xPaddingKey": "mykey", + "xPaddingHeader": "X-Trace-ID", + "xPaddingPlacement": "queryInHeader", + "xPaddingMethod": "tokenish", + "uplinkHTTPMethod": "POST", + "sessionPlacement": "query", + "sessionKey": "sess", + "seqPlacement": "header", + "seqKey": "seq", + "uplinkDataPlacement": "body", + "uplinkDataKey": "udata", + "uplinkChunkSize": "64-256", + "noGRPCHeader": true, + "scMaxEachPostBytes": "500000", "scMinPostsIntervalMs": "50", "xmux": map[string]any{ "maxConcurrency": "16-32", "maxConnections": "4", "cMaxReuseTimes": "8", - "hMaxRequestTimes": "600-900", - "hMaxReusableSecs": "1800-3000", - "hKeepAlivePeriod": float64(60), + "hMaxRequestTimes": "600-900", + "hMaxReusableSecs": "1800-3000", + "hKeepAlivePeriod": float64(60), }, "headers": map[string]any{ "User-Agent": "chrome", @@ -473,8 +473,8 @@ func TestBuildXhttpClashOpts_FullFieldMapping(t *testing.T) { func TestBuildXhttpClashOpts_DPIDefaultsFiltered(t *testing.T) { xhttp := map[string]any{ - "path": "/", - "mode": "stream-up", + "path": "/", + "mode": "stream-up", "scMaxEachPostBytes": "1000000", "scMinPostsIntervalMs": "30", } @@ -494,9 +494,9 @@ func TestBuildXhttpClashOpts_PaddingObfsGate(t *testing.T) { // Sub-test 1: obfs mode false — gated fields should not appear t.Run("ObfsModeFalse", func(t *testing.T) { xhttp := map[string]any{ - "path": "/", + "path": "/", "xPaddingObfsMode": false, - "xPaddingKey": "should-not-appear", + "xPaddingKey": "should-not-appear", } opts := buildXhttpClashOpts(xhttp) if opts == nil { @@ -553,9 +553,9 @@ func TestBuildXhttpClashOpts_XmuxMapsToReuseSettings(t *testing.T) { "maxConcurrency": "16-32", "maxConnections": "4", "cMaxReuseTimes": "8", - "hMaxRequestTimes": "600-900", - "hMaxReusableSecs": "1800-3000", - "hKeepAlivePeriod": float64(60), + "hMaxRequestTimes": "600-900", + "hMaxReusableSecs": "1800-3000", + "hKeepAlivePeriod": float64(60), }, } opts := buildXhttpClashOpts(xhttp) diff --git a/internal/sub/service.go b/internal/sub/service.go index 1e16356b1..99d298671 100644 --- a/internal/sub/service.go +++ b/internal/sub/service.go @@ -747,7 +747,7 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st url.QueryEscape(inboundPassword), url.QueryEscape(clients[clientIndex].Password)) } else { - userInfo = base64.RawURLEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", method, clients[clientIndex].Password))) + userInfo = base64.RawURLEncoding.EncodeToString(fmt.Appendf(nil, "%s:%s", method, clients[clientIndex].Password)) } externalProxies, _ := stream["externalProxy"].([]any) diff --git a/internal/web/entity/entity.go b/internal/web/entity/entity.go index 33b2b52e3..692bb7406 100644 --- a/internal/web/entity/entity.go +++ b/internal/web/entity/entity.go @@ -39,29 +39,29 @@ type AllSetting struct { Datepicker string `json:"datepicker" form:"datepicker"` // Date picker format // Telegram bot settings - TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"` // Enable Telegram bot notifications - TgBotToken string `json:"tgBotToken" form:"tgBotToken"` // Telegram bot token - TgBotProxy string `json:"tgBotProxy" form:"tgBotProxy"` // Proxy URL for Telegram bot - TgBotAPIServer string `json:"tgBotAPIServer" form:"tgBotAPIServer"` // Custom API server for Telegram bot - TgBotChatId string `json:"tgBotChatId" form:"tgBotChatId"` // Telegram chat ID for notifications - TgRunTime string `json:"tgRunTime" form:"tgRunTime"` // Cron schedule for Telegram notifications - TgBotBackup bool `json:"tgBotBackup" form:"tgBotBackup"` // Enable database backup via Telegram - TgCpu int `json:"tgCpu" form:"tgCpu" validate:"gte=0,lte=100"` // CPU usage threshold for alerts (percent) + TgBotEnable bool `json:"tgBotEnable" form:"tgBotEnable"` // Enable Telegram bot notifications + TgBotToken string `json:"tgBotToken" form:"tgBotToken"` // Telegram bot token + TgBotProxy string `json:"tgBotProxy" form:"tgBotProxy"` // Proxy URL for Telegram bot + TgBotAPIServer string `json:"tgBotAPIServer" form:"tgBotAPIServer"` // Custom API server for Telegram bot + TgBotChatId string `json:"tgBotChatId" form:"tgBotChatId"` // Telegram chat ID for notifications + TgRunTime string `json:"tgRunTime" form:"tgRunTime"` // Cron schedule for Telegram notifications + TgBotBackup bool `json:"tgBotBackup" form:"tgBotBackup"` // Enable database backup via Telegram + TgCpu int `json:"tgCpu" form:"tgCpu" validate:"gte=0,lte=100"` // CPU usage threshold for alerts (percent) TgMemory int `json:"tgMemory" form:"tgMemory" validate:"gte=0,lte=100"` // Memory usage threshold for alerts (percent) - TgLang string `json:"tgLang" form:"tgLang"` // Telegram bot language - TgEnabledEvents string `json:"tgEnabledEvents" form:"tgEnabledEvents"` // Comma-separated event types to send via Telegram + TgLang string `json:"tgLang" form:"tgLang"` // Telegram bot language + TgEnabledEvents string `json:"tgEnabledEvents" form:"tgEnabledEvents"` // Comma-separated event types to send via Telegram // Email (SMTP) notification settings - SmtpEnable bool `json:"smtpEnable" form:"smtpEnable"` // Enable email notifications - SmtpHost string `json:"smtpHost" form:"smtpHost"` // SMTP server host - SmtpPort int `json:"smtpPort" form:"smtpPort" validate:"gte=1,lte=65535"` // SMTP server port - SmtpUsername string `json:"smtpUsername" form:"smtpUsername"` // SMTP username - SmtpPassword string `json:"smtpPassword" form:"smtpPassword"` // SMTP password - SmtpTo string `json:"smtpTo" form:"smtpTo"` // Comma-separated recipient emails - SmtpEncryptionType string `json:"smtpEncryptionType" form:"smtpEncryptionType"` // SMTP encryption: none, starttls, tls - SmtpEnabledEvents string `json:"smtpEnabledEvents" form:"smtpEnabledEvents"` // Comma-separated event types to send via email - SmtpCpu int `json:"smtpCpu" form:"smtpCpu" validate:"gte=0,lte=100"` // CPU threshold for email notifications - SmtpMemory int `json:"smtpMemory" form:"smtpMemory" validate:"gte=0,lte=100"` // Memory threshold for email notifications + SmtpEnable bool `json:"smtpEnable" form:"smtpEnable"` // Enable email notifications + SmtpHost string `json:"smtpHost" form:"smtpHost"` // SMTP server host + SmtpPort int `json:"smtpPort" form:"smtpPort" validate:"gte=1,lte=65535"` // SMTP server port + SmtpUsername string `json:"smtpUsername" form:"smtpUsername"` // SMTP username + SmtpPassword string `json:"smtpPassword" form:"smtpPassword"` // SMTP password + SmtpTo string `json:"smtpTo" form:"smtpTo"` // Comma-separated recipient emails + SmtpEncryptionType string `json:"smtpEncryptionType" form:"smtpEncryptionType"` // SMTP encryption: none, starttls, tls + SmtpEnabledEvents string `json:"smtpEnabledEvents" form:"smtpEnabledEvents"` // Comma-separated event types to send via email + SmtpCpu int `json:"smtpCpu" form:"smtpCpu" validate:"gte=0,lte=100"` // CPU threshold for email notifications + SmtpMemory int `json:"smtpMemory" form:"smtpMemory" validate:"gte=0,lte=100"` // Memory threshold for email notifications // Security settings TimeLocation string `json:"timeLocation" form:"timeLocation"` // Time zone location diff --git a/internal/web/job/node_traffic_sync_job.go b/internal/web/job/node_traffic_sync_job.go index 2618cd7b9..40432c0db 100644 --- a/internal/web/job/node_traffic_sync_job.go +++ b/internal/web/job/node_traffic_sync_job.go @@ -246,10 +246,7 @@ func (j *NodeTrafficSyncJob) nodeInboundSpeed() []*xray.Traffic { if dDown < 0 { dDown = 0 } - elapsed := now - prev.at - if elapsed < nodeInboundSpeedWindowMs { - elapsed = nodeInboundSpeedWindowMs - } + elapsed := max(now-prev.at, nodeInboundSpeedWindowMs) up := dUp * nodeInboundSpeedWindowMs / elapsed down := dDown * nodeInboundSpeedWindowMs / elapsed if up > 0 || down > 0 { diff --git a/internal/web/service/server.go b/internal/web/service/server.go index 5fa6e5210..8775d5a5a 100644 --- a/internal/web/service/server.go +++ b/internal/web/service/server.go @@ -936,7 +936,7 @@ func (s *ServerService) fetchXrayDigestSHA256(client *http.Client, dgstURL strin // parseXrayDigestSHA256 extracts the lowercase SHA2-256 hex from an XTLS .dgst // file, whose lines are "ALGO= " (the relevant one being "SHA2-256= ..."). func parseXrayDigestSHA256(dgst []byte) (string, error) { - for _, line := range strings.Split(string(dgst), "\n") { + for line := range strings.SplitSeq(string(dgst), "\n") { rest, ok := strings.CutPrefix(strings.TrimSpace(line), "SHA2-256=") if !ok { continue diff --git a/internal/web/web.go b/internal/web/web.go index e4f754431..6d50faafa 100644 --- a/internal/web/web.go +++ b/internal/web/web.go @@ -429,7 +429,7 @@ func (s *Server) memoryAlarmWanted() bool { if threshold <= 0 { return false } - for _, e := range strings.Split(events, ",") { + for e := range strings.SplitSeq(events, ",") { if strings.TrimSpace(e) == string(eventbus.EventMemoryHigh) { return true } diff --git a/internal/xray/log_writer_race_test.go b/internal/xray/log_writer_race_test.go index 417814946..444d7c6b1 100644 --- a/internal/xray/log_writer_race_test.go +++ b/internal/xray/log_writer_race_test.go @@ -16,18 +16,18 @@ func TestLogWriterLastLineConcurrent(t *testing.T) { var wg sync.WaitGroup wg.Add(writers + readers) - for i := 0; i < writers; i++ { + for range writers { go func() { defer wg.Done() - for j := 0; j < iterations; j++ { + for range iterations { _, _ = lw.Write([]byte("2024/01/01 00:00:00.000000 [Info] connection accepted")) } }() } - for i := 0; i < readers; i++ { + for range readers { go func() { defer wg.Done() - for j := 0; j < iterations; j++ { + for range iterations { _ = lw.LastLine() } }() diff --git a/internal/xray/process_race_test.go b/internal/xray/process_race_test.go index 8bf80c9c3..77db0d39d 100644 --- a/internal/xray/process_race_test.go +++ b/internal/xray/process_race_test.go @@ -19,9 +19,7 @@ func TestProcessLifecycleFieldsRaceSafe(t *testing.T) { stop := make(chan struct{}) // Writer: churn cmd/done/exitErr like Start + waitForCommand. - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { select { case <-stop: @@ -34,13 +32,11 @@ func TestProcessLifecycleFieldsRaceSafe(t *testing.T) { p.mu.Unlock() p.setExitErr(errors.New("boom")) } - }() + }) // Readers: the concurrent status getters. - for i := 0; i < 4; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range 4 { + wg.Go(func() { for { select { case <-stop: @@ -51,7 +47,7 @@ func TestProcessLifecycleFieldsRaceSafe(t *testing.T) { _ = p.GetErr() _ = p.GetResult() } - }() + }) } time.Sleep(50 * time.Millisecond)