mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
chore: apply modernize analyzer fixes across codebase
Mechanical replacements suggested by golang.org/x/tools/.../modernize: strings.Cut/CutPrefix/SplitSeq, slices.Contains, maps.Copy, min(), range-over-int, new(expr), strings.Builder for hot += loops, reflect.TypeFor[T](), sync.WaitGroup.Go(), drop legacy //+build lines.
This commit is contained in:
parent
317c7cb4f1
commit
1ef494bcda
24 changed files with 69 additions and 94 deletions
|
|
@ -69,11 +69,11 @@ func isIgnorableDuplicateColumnErr(err error, mdl any) bool {
|
|||
if !strings.Contains(errMsg, dupPrefix) {
|
||||
return false
|
||||
}
|
||||
idx := strings.Index(errMsg, dupPrefix)
|
||||
if idx < 0 {
|
||||
_, after, ok := strings.Cut(errMsg, dupPrefix)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
col := strings.TrimSpace(errMsg[idx+len(dupPrefix):])
|
||||
col := strings.TrimSpace(after)
|
||||
col = strings.Trim(col, "`\"[]")
|
||||
if col == "" {
|
||||
return false
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -12,7 +12,7 @@ require (
|
|||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/mymmrac/telego v1.8.0
|
||||
github.com/mymmrac/telego v1.9.0
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.1
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
|
|
@ -25,7 +25,7 @@ require (
|
|||
golang.org/x/crypto v0.51.0
|
||||
golang.org/x/sys v0.44.0
|
||||
golang.org/x/text v0.37.0
|
||||
google.golang.org/grpc v1.81.0
|
||||
google.golang.org/grpc v1.81.1
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gorm.io/driver/sqlite v1.6.0
|
||||
gorm.io/gorm v1.31.1
|
||||
|
|
|
|||
8
go.sum
8
go.sum
|
|
@ -130,8 +130,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mymmrac/telego v1.8.0 h1:EvIprWo9Cn0MHgumvvqNXPAXO1yJj3pu2cdCCeDxbow=
|
||||
github.com/mymmrac/telego v1.8.0/go.mod h1:pdLV346EgVuq7Xrh3kMggeBiazeHhsdEoK0RTEOPXRM=
|
||||
github.com/mymmrac/telego v1.9.0 h1:ZUJxZaPx/1IgRvVb5lXnUB8FgW5rNYfRe6Q2EJ4OJ+Y=
|
||||
github.com/mymmrac/telego v1.9.0/go.mod h1:tVEB7OqiOPx8elRk9+ETkwiDQrUhWSB2XmAKIY9KmWY=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.1 h1:JDEJraFsQE17Dut9HFDHzCoAWGEQJom5s0TRd17NIEQ=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.6.1/go.mod h1:Vee0/9RD3Quc/NmwEjzzD7VTZ+Ir7QbXocrkhOzmUKA=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||
|
|
@ -258,8 +258,8 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
|||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60 h1:seT2EwLWM78plQ7wcDfuWBc/4FAEAXDDiaSol4ku4qo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw=
|
||||
google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
|||
|
|
@ -207,9 +207,9 @@ func (s *Server) initRouter() (*gin.Engine, error) {
|
|||
path := c.Request.URL.Path
|
||||
pathPrefix := strings.TrimRight(LinksPath, "/") + "/"
|
||||
if strings.HasPrefix(path, pathPrefix) && strings.Contains(path, "/assets/") {
|
||||
assetsIndex := strings.Index(path, "/assets/")
|
||||
if assetsIndex != -1 {
|
||||
assetPath := path[assetsIndex+8:] // +8 to skip "/assets/"
|
||||
_, after, ok := strings.Cut(path, "/assets/")
|
||||
if ok {
|
||||
assetPath := after // +8 to skip "/assets/"
|
||||
if assetPath != "" {
|
||||
c.FileFromFS(assetPath, assetsFS)
|
||||
c.Abort()
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package sub
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"strings"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
|
@ -471,8 +472,6 @@ func cloneMap(src map[string]any) map[string]any {
|
|||
return nil
|
||||
}
|
||||
dst := make(map[string]any, len(src))
|
||||
for k, v := range src {
|
||||
dst[k] = v
|
||||
}
|
||||
maps.Copy(dst, src)
|
||||
return dst
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package ldaputil
|
|||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
)
|
||||
|
|
@ -82,13 +83,7 @@ func FetchVlessFlags(cfg Config) (map[string]bool, error) {
|
|||
continue
|
||||
}
|
||||
val := e.GetAttributeValue(cfg.FlagField)
|
||||
enabled := false
|
||||
for _, t := range cfg.TruthyVals {
|
||||
if val == t {
|
||||
enabled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
enabled := slices.Contains(cfg.TruthyVals, val)
|
||||
if cfg.Invert {
|
||||
enabled = !enabled
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func TestSeq_NotConstant(t *testing.T) {
|
|||
|
||||
func TestNum_InRange(t *testing.T) {
|
||||
for _, upper := range []int{1, 2, 10, 1000} {
|
||||
for i := 0; i < 200; i++ {
|
||||
for range 200 {
|
||||
v := Num(upper)
|
||||
if v < 0 || v >= upper {
|
||||
t.Fatalf("Num(%d) returned %d, out of [0, %d)", upper, v, upper)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package sys
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package sys
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package sys
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ func NewAPIController(g *gin.RouterGroup, customGeo *service.CustomGeoService) *
|
|||
|
||||
func (a *APIController) checkAPIAuth(c *gin.Context) {
|
||||
auth := c.GetHeader("Authorization")
|
||||
if strings.HasPrefix(auth, "Bearer ") {
|
||||
tok := strings.TrimPrefix(auth, "Bearer ")
|
||||
if after, ok := strings.CutPrefix(auth, "Bearer "); ok {
|
||||
tok := after
|
||||
if a.apiTokenService.Match(tok) {
|
||||
if u, err := a.userService.GetFirstUser(); err == nil {
|
||||
session.SetAPIAuthUser(c, u)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ func getRemoteIp(c *gin.Context) string {
|
|||
}
|
||||
|
||||
if xff := c.GetHeader("X-Forwarded-For"); xff != "" {
|
||||
for _, part := range strings.Split(xff, ",") {
|
||||
for part := range strings.SplitSeq(xff, ",") {
|
||||
if ip, ok := extractTrustedIP(part); ok {
|
||||
return ip
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ func isTrustedProxy(ip string) bool {
|
|||
}
|
||||
|
||||
trusted := trustedProxyCIDRs()
|
||||
for _, value := range strings.Split(trusted, ",") {
|
||||
for value := range strings.SplitSeq(trusted, ",") {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ func (s *AllSetting) CheckValid() error {
|
|||
s.SubClashPath += "/"
|
||||
}
|
||||
|
||||
for _, cidr := range strings.Split(s.TrustedProxyCIDRs, ",") {
|
||||
for cidr := range strings.SplitSeq(s.TrustedProxyCIDRs, ",") {
|
||||
cidr = strings.TrimSpace(cidr)
|
||||
if cidr == "" {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -42,28 +42,24 @@ func TestAtomicBool_ConcurrentSettersExactlyOneTakeWins(t *testing.T) {
|
|||
const readers = 20
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < setters; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for range setters {
|
||||
wg.Go(func() {
|
||||
a.set()
|
||||
}()
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
trueCount := 0
|
||||
var rwg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
for i := 0; i < readers; i++ {
|
||||
rwg.Add(1)
|
||||
go func() {
|
||||
defer rwg.Done()
|
||||
for range readers {
|
||||
rwg.Go(func() {
|
||||
if a.takeAndReset() {
|
||||
mu.Lock()
|
||||
trueCount++
|
||||
mu.Unlock()
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
rwg.Wait()
|
||||
|
||||
|
|
|
|||
|
|
@ -2526,10 +2526,7 @@ func chunkStrings(s []string, size int) [][]string {
|
|||
}
|
||||
out := make([][]string, 0, (len(s)+size-1)/size)
|
||||
for i := 0; i < len(s); i += size {
|
||||
end := i + size
|
||||
if end > len(s) {
|
||||
end = len(s)
|
||||
}
|
||||
end := min(i+size, len(s))
|
||||
out = append(out, s[i:end])
|
||||
}
|
||||
return out
|
||||
|
|
@ -2543,10 +2540,7 @@ func chunkInts(s []int, size int) [][]int {
|
|||
}
|
||||
out := make([][]int, 0, (len(s)+size-1)/size)
|
||||
for i := 0; i < len(s); i += size {
|
||||
end := i + size
|
||||
if end > len(s) {
|
||||
end = len(s)
|
||||
}
|
||||
end := min(i+size, len(s))
|
||||
out = append(out, s[i:end])
|
||||
}
|
||||
return out
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ func compareVersionStrings(a string, b string) (int, bool) {
|
|||
if !okA || !okB {
|
||||
return 0, false
|
||||
}
|
||||
for i := 0; i < len(aParts); i++ {
|
||||
for i := range len(aParts) {
|
||||
if aParts[i] > bParts[i] {
|
||||
return 1, true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ func inboundTransports(protocol model.Protocol, streamSettings, settings string)
|
|||
// "udp", or "tcp,udp". if it's set, it wins outright.
|
||||
if n, ok := st["network"].(string); ok && n != "" {
|
||||
bits = 0
|
||||
for _, part := range strings.Split(n, ",") {
|
||||
for part := range strings.SplitSeq(n, ",") {
|
||||
switch strings.TrimSpace(part) {
|
||||
case "tcp":
|
||||
bits |= transportTCP
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ func seedInboundConflictNode(t *testing.T, tag, listen string, port int, protoco
|
|||
}
|
||||
}
|
||||
|
||||
func intPtr(v int) *int { return &v }
|
||||
//go:fix inline
|
||||
func intPtr(v int) *int { return new(v) }
|
||||
|
||||
func TestInboundTransports(t *testing.T) {
|
||||
cases := []struct {
|
||||
|
|
@ -360,7 +361,7 @@ func TestGenerateInboundTag_SpecificListenSameDisambiguation(t *testing.T) {
|
|||
func TestCheckPortConflict_NodeScope(t *testing.T) {
|
||||
setupConflictDB(t)
|
||||
seedInboundConflictNode(t, "local-443-tcp", "0.0.0.0", 443, model.VLESS, `{"network":"tcp"}`, `{}`, nil)
|
||||
seedInboundConflictNode(t, "node1-443-tcp", "0.0.0.0", 443, model.VLESS, `{"network":"tcp"}`, `{}`, intPtr(1))
|
||||
seedInboundConflictNode(t, "node1-443-tcp", "0.0.0.0", 443, model.VLESS, `{"network":"tcp"}`, `{}`, new(1))
|
||||
|
||||
svc := &InboundService{}
|
||||
|
||||
|
|
@ -370,8 +371,8 @@ func TestCheckPortConflict_NodeScope(t *testing.T) {
|
|||
want bool
|
||||
}{
|
||||
{"new local same port + tcp clashes with local", nil, true},
|
||||
{"new remote on different node from local is fine", intPtr(2), false},
|
||||
{"new remote on existing node 1 clashes", intPtr(1), true},
|
||||
{"new remote on different node from local is fine", new(2), false},
|
||||
{"new remote on existing node 1 clashes", new(1), true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ func (t *Tgbot) Start(i18nFS embed.FS) error {
|
|||
parsedAdminIds := make([]int64, 0)
|
||||
// Parse admin IDs from comma-separated string
|
||||
if tgBotID != "" {
|
||||
for _, adminID := range strings.Split(tgBotID, ",") {
|
||||
for adminID := range strings.SplitSeq(tgBotID, ",") {
|
||||
id, err := strconv.ParseInt(adminID, 10, 64)
|
||||
if err != nil {
|
||||
logger.Warning("Failed to parse admin ID from Telegram bot chat ID:", err)
|
||||
|
|
@ -2051,12 +2051,7 @@ func (t *Tgbot) SubmitAddClient() (bool, error) {
|
|||
|
||||
// checkAdmin checks if the given Telegram ID is an admin.
|
||||
func checkAdmin(tgId int64) bool {
|
||||
for _, adminId := range adminIds {
|
||||
if adminId == tgId {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(adminIds, tgId)
|
||||
}
|
||||
|
||||
// SendAnswer sends a response message with an inline keyboard to the specified chat.
|
||||
|
|
@ -2373,17 +2368,18 @@ func (t *Tgbot) sendClientIndividualLinks(chatId int64, email string) {
|
|||
// Send in chunks to respect message length; use monospace formatting
|
||||
const maxPerMessage = 50
|
||||
for i := 0; i < len(cleaned); i += maxPerMessage {
|
||||
j := i + maxPerMessage
|
||||
if j > len(cleaned) {
|
||||
j = len(cleaned)
|
||||
}
|
||||
j := min(i+maxPerMessage, len(cleaned))
|
||||
chunk := cleaned[i:j]
|
||||
msg := t.I18nBot("subscription.individualLinks") + ":\r\n"
|
||||
var msg strings.Builder
|
||||
msg.WriteString(t.I18nBot("subscription.individualLinks"))
|
||||
msg.WriteString(":\r\n")
|
||||
for _, link := range chunk {
|
||||
// wrap each link in <code>
|
||||
msg += "<code>" + link + "</code>\r\n"
|
||||
msg.WriteString("<code>")
|
||||
msg.WriteString(link)
|
||||
msg.WriteString("</code>\r\n")
|
||||
}
|
||||
t.SendMsgToTgbot(chatId, msg)
|
||||
t.SendMsgToTgbot(chatId, msg.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3439,7 +3435,8 @@ func (t *Tgbot) notifyExhausted() {
|
|||
var exhaustedClients []xray.ClientTraffic
|
||||
traffics, err := t.inboundService.GetClientTrafficTgBot(client.TgID)
|
||||
if err == nil && len(traffics) > 0 {
|
||||
output := t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients"))
|
||||
var output strings.Builder
|
||||
output.WriteString(t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients")))
|
||||
for _, traffic := range traffics {
|
||||
if traffic.Enable {
|
||||
if (traffic.ExpiryTime > 0 && (traffic.ExpiryTime-now < exDiff)) ||
|
||||
|
|
@ -3451,21 +3448,23 @@ func (t *Tgbot) notifyExhausted() {
|
|||
}
|
||||
}
|
||||
if len(exhaustedClients) > 0 {
|
||||
output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients)))
|
||||
output.WriteString(t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients))))
|
||||
if len(disabledClients) > 0 {
|
||||
output += t.I18nBot("tgbot.clients") + ":\r\n"
|
||||
output.WriteString(t.I18nBot("tgbot.clients"))
|
||||
output.WriteString(":\r\n")
|
||||
for _, traffic := range disabledClients {
|
||||
output += " " + traffic.Email
|
||||
output.WriteString(" ")
|
||||
output.WriteString(traffic.Email)
|
||||
}
|
||||
output += "\r\n"
|
||||
output.WriteString("\r\n")
|
||||
}
|
||||
output += "\r\n"
|
||||
output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedClients)))
|
||||
output.WriteString("\r\n")
|
||||
output.WriteString(t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedClients))))
|
||||
for _, traffic := range exhaustedClients {
|
||||
output += t.clientInfoMsg(&traffic, true, false, false, true, true, false)
|
||||
output += "\r\n"
|
||||
output.WriteString(t.clientInfoMsg(&traffic, true, false, false, true, true, false))
|
||||
output.WriteString("\r\n")
|
||||
}
|
||||
t.SendMsgToTgbot(chatID, output)
|
||||
t.SendMsgToTgbot(chatID, output.String())
|
||||
}
|
||||
chatIDsDone = append(chatIDsDone, chatID)
|
||||
}
|
||||
|
|
@ -3480,12 +3479,7 @@ func (t *Tgbot) notifyExhausted() {
|
|||
|
||||
// int64Contains checks if an int64 slice contains a specific item.
|
||||
func int64Contains(slice []int64, item int64) bool {
|
||||
for _, s := range slice {
|
||||
if s == item {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return slices.Contains(slice, item)
|
||||
}
|
||||
|
||||
// onlineClients retrieves and sends information about online clients.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
)
|
||||
|
||||
func TestLoginAttemptDoesNotCarryPassword(t *testing.T) {
|
||||
typ := reflect.TypeOf(LoginAttempt{})
|
||||
typ := reflect.TypeFor[LoginAttempt]()
|
||||
if _, ok := typ.FieldByName("Password"); ok {
|
||||
t.Fatal("LoginAttempt must not carry attempted passwords")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package service
|
|||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"slices"
|
||||
|
||||
"github.com/mhsanaei/3x-ui/v3/util/common"
|
||||
"github.com/mhsanaei/3x-ui/v3/xray"
|
||||
|
|
@ -55,7 +56,7 @@ func (s *XraySettingService) CheckXrayConfig(XrayTemplateConfig string) error {
|
|||
// If `raw` does not look like a wrapper, it is returned unchanged.
|
||||
func UnwrapXrayTemplateConfig(raw string) string {
|
||||
const maxDepth = 8 // defensive cap against pathological multi-nest values
|
||||
for i := 0; i < maxDepth; i++ {
|
||||
for range maxDepth {
|
||||
var top map[string]json.RawMessage
|
||||
if err := json.Unmarshal([]byte(raw), &top); err != nil {
|
||||
return raw
|
||||
|
|
@ -190,10 +191,8 @@ func findApiRule(rules []map[string]any) int {
|
|||
}
|
||||
}
|
||||
case []string:
|
||||
for _, s := range tags {
|
||||
if s == "api" {
|
||||
return i
|
||||
}
|
||||
if slices.Contains(tags, "api") {
|
||||
return i
|
||||
}
|
||||
case string:
|
||||
if tags == "api" {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ func TestUnwrapXrayTemplateConfig(t *testing.T) {
|
|||
// non-wrapped, and confirm we end up at some valid JSON (we
|
||||
// don't loop forever and we don't blow the stack).
|
||||
s := real
|
||||
for i := 0; i < 16; i++ {
|
||||
for range 16 {
|
||||
s = `{"xraySetting":` + s + `}`
|
||||
}
|
||||
got := UnwrapXrayTemplateConfig(s)
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func (h *Hub) shouldThrottle(msgType MessageType) bool {
|
|||
// panic doesn't permanently kill real-time updates for commercial deployments.
|
||||
// After the cap, the hub stays down and the frontend falls back to REST polling.
|
||||
func (h *Hub) Run() {
|
||||
for attempt := 0; attempt < hubRestartAttempts; attempt++ {
|
||||
for attempt := range hubRestartAttempts {
|
||||
stopped := h.runOnce()
|
||||
if stopped {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ func TestHub_ConcurrentRegisterUnregister(t *testing.T) {
|
|||
|
||||
const n = 50
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < n; i++ {
|
||||
for i := range n {
|
||||
wg.Add(1)
|
||||
go func(idx int) {
|
||||
defer wg.Done()
|
||||
|
|
|
|||
Loading…
Reference in a new issue