Bläddra i källkod

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.
MHSanaei 1 dag sedan
förälder
incheckning
1c0b76c27a

+ 29 - 29
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)

+ 1 - 1
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)

+ 20 - 20
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

+ 1 - 4
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 {

+ 1 - 1
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= <hex>" (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

+ 1 - 1
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
 			}

+ 4 - 4
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()
 			}
 		}()

+ 5 - 9
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)