diff --git a/cmd/outputs.go b/cmd/outputs.go index 0683ff53d41..fa50cd1530f 100644 --- a/cmd/outputs.go +++ b/cmd/outputs.go @@ -127,7 +127,7 @@ func createOutputs( result := make([]output.Output, 0, len(outputs)) for _, outputFullArg := range outputs { - outputType, outputArg := parseOutputArgument(outputFullArg) + outputType, outputArg, _ := strings.Cut(outputFullArg, "=") outputConstructor, ok := outputConstructors[outputType] if !ok { return nil, fmt.Errorf( @@ -173,15 +173,3 @@ func createOutputs( return result, nil } - -func parseOutputArgument(s string) (t, arg string) { - parts := strings.SplitN(s, "=", 2) - switch len(parts) { - case 0: - return "", "" - case 1: - return parts[0], "" - default: - return parts[0], parts[1] - } -} diff --git a/cmd/tests/cmd_run_test.go b/cmd/tests/cmd_run_test.go index dc49e65217e..233825c008f 100644 --- a/cmd/tests/cmd_run_test.go +++ b/cmd/tests/cmd_run_test.go @@ -476,11 +476,11 @@ func TestSubMetricThresholdNoData(t *testing.T) { func getTestServer(tb testing.TB, routes map[string]http.Handler) *httptest.Server { mux := http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { for methodAndRoute, handler := range routes { - methodRouteTuple := strings.SplitN(methodAndRoute, " ", 2) - regex, err := regexp.Compile(methodRouteTuple[1]) + method, route, _ := strings.Cut(methodAndRoute, " ") + routeRegexp, err := regexp.Compile(route) require.NoError(tb, err) - if req.Method == methodRouteTuple[0] && regex.Match([]byte(req.URL.String())) { + if req.Method == method && routeRegexp.Match([]byte(req.URL.String())) { handler.ServeHTTP(resp, req) return } diff --git a/lib/execution_segment.go b/lib/execution_segment.go index 7c469c81a4a..52256dfe653 100644 --- a/lib/execution_segment.go +++ b/lib/execution_segment.go @@ -108,9 +108,9 @@ func NewExecutionSegmentFromString(toStr string) (result *ExecutionSegment, err toStr = "1" // an empty string means a full 0:1 execution segment } if strings.ContainsRune(toStr, ':') { - fromToStr := strings.SplitN(toStr, ":", 2) - toStr = fromToStr[1] - if from, err = stringToRat(fromToStr[0]); err != nil { + var fromStr string + fromStr, toStr, _ = strings.Cut(toStr, ":") + if from, err = stringToRat(fromStr); err != nil { return nil, err } } diff --git a/lib/models.go b/lib/models.go index 30cb6b13b72..64f4e0f0335 100644 --- a/lib/models.go +++ b/lib/models.go @@ -59,16 +59,16 @@ func (s Stage) MarshalJSON() ([]byte, error) { // UnmarshalText implements the encoding.TextUnmarshaler interface func (s *Stage) UnmarshalText(b []byte) error { var stage Stage - parts := strings.SplitN(string(b), ":", 2) - if len(parts) > 0 && parts[0] != "" { - d, err := time.ParseDuration(parts[0]) + durStr, targetStr, _ := strings.Cut(string(b), ":") + if durStr != "" { + d, err := time.ParseDuration(durStr) if err != nil { return err } stage.Duration = types.NullDurationFrom(d) } - if len(parts) > 1 && parts[1] != "" { - t, err := strconv.ParseInt(parts[1], 10, 64) + if targetStr != "" { + t, err := strconv.ParseInt(targetStr, 10, 64) if err != nil { return err } diff --git a/lib/trace/otel.go b/lib/trace/otel.go index 30e5d76685e..447592236c0 100644 --- a/lib/trace/otel.go +++ b/lib/trace/otel.go @@ -175,9 +175,9 @@ func tracerProviderParamsFromConfigLine(line string) (tracerProviderParams, erro return params, nil } - parts := strings.SplitN(line, "=", 2) - if parts[0] != "otel" { - return params, fmt.Errorf("%w %q", ErrInvalidTracesOutput, parts[0]) + traceOutput, _, _ := strings.Cut(line, "=") + if traceOutput != "otel" { + return params, fmt.Errorf("%w %q", ErrInvalidTracesOutput, traceOutput) } tokens, err := strvals.Parse(line) diff --git a/lib/types/dns.go b/lib/types/dns.go index baad4956527..d4be84fb6a8 100644 --- a/lib/types/dns.go +++ b/lib/types/dns.go @@ -198,11 +198,11 @@ func (c *DNSConfig) UnmarshalText(text []byte) error { values := strings.Split(string(text), ",") params := make(map[string]string, len(values)) for _, value := range values { - args := strings.SplitN(value, "=", 2) - if len(args) != 2 { + k, v, _ := strings.Cut(value, "=") + if v == "" { return fmt.Errorf("no value for key %s", value) } - params[args[0]] = args[1] + params[k] = v } return c.unmarshal(params) } diff --git a/lib/types/ipblock.go b/lib/types/ipblock.go index 68487698576..f7c85939a8d 100644 --- a/lib/types/ipblock.go +++ b/lib/types/ipblock.go @@ -41,8 +41,8 @@ func getIPBlock(s string) (*ipBlock, error) { } func ipBlockFromRange(s string) (*ipBlock, error) { - ss := strings.SplitN(s, "-", 2) - ip0, ip1 := net.ParseIP(ss[0]), net.ParseIP(ss[1]) + ip0Str, ip1Str, _ := strings.Cut(s, "-") + ip0, ip1 := net.ParseIP(ip0Str), net.ParseIP(ip1Str) if ip0 == nil || ip1 == nil { return nil, errors.New("wrong IP range format: " + s) } diff --git a/loader/loader.go b/loader/loader.go index 368f79b2924..df33435e6fc 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -83,15 +83,15 @@ func Resolve(pwd *url.URL, moduleSpecifier string) (*url.URL, error) { func resolveFilePath(pwd *url.URL, moduleSpecifier string) (*url.URL, error) { if pwd.Opaque != "" { // this is a loader reference - parts := strings.SplitN(pwd.Opaque, "/", 2) + base, dir, _ := strings.Cut(pwd.Opaque, "/") if moduleSpecifier[0] == '/' { - return &url.URL{Opaque: path.Join(parts[0], moduleSpecifier)}, nil + return &url.URL{Opaque: path.Join(base, moduleSpecifier)}, nil } - return &url.URL{Opaque: path.Join(parts[0], path.Join(path.Dir(parts[1]+"/"), moduleSpecifier))}, nil + return &url.URL{Opaque: path.Join(base, path.Join(path.Dir(dir+"/"), moduleSpecifier))}, nil } // The file is in format like C:/something/path.js. But this will be decoded as scheme `C` - // ... which is not what we want we want it to be decode as file:///C:/something/path.js + // ... which is not what we want, we want it to be decoded as file:///C:/something/path.js if filepath.VolumeName(moduleSpecifier) != "" { moduleSpecifier = "/" + moduleSpecifier } diff --git a/log/file.go b/log/file.go index 06ebcf1ce5f..626423df683 100644 --- a/log/file.go +++ b/log/file.go @@ -42,8 +42,8 @@ func FileHookFromConfigLine( loglines: make(chan []byte, fileHookBufferSize), } - parts := strings.SplitN(line, "=", 2) - if parts[0] != "file" { + logOutput, _, _ := strings.Cut(line, "=") + if logOutput != "file" { return nil, fmt.Errorf("logfile configuration should be in the form `file=path-to-local-file` but is `%s`", line) } if err := hook.parseArgs(line); err != nil { diff --git a/log/loki.go b/log/loki.go index 2a4d353307e..2a3c9bc1fed 100644 --- a/log/loki.go +++ b/log/loki.go @@ -55,8 +55,8 @@ func LokiFromConfigLine(fallbackLogger logrus.FieldLogger, line string) (AsyncHo h.fallbackLogger = fallbackLogger if line != "loki" { - parts := strings.SplitN(line, "=", 2) - if parts[0] != "loki" { + logOutput, _, _ := strings.Cut(line, "=") + if logOutput != "loki" { return nil, fmt.Errorf("loki configuration should be in the form `loki=url-to-push` but is `%s`", line) } diff --git a/metrics/engine/engine.go b/metrics/engine/engine.go index 55f0b87fdb7..18567c2712e 100644 --- a/metrics/engine/engine.go +++ b/metrics/engine/engine.go @@ -62,19 +62,17 @@ func (me *MetricsEngine) CreateIngester() *OutputIngester { } func (me *MetricsEngine) getThresholdMetricOrSubmetric(name string) (*metrics.Metric, error) { - // TODO: replace with strings.Cut after Go 1.18 - nameParts := strings.SplitN(name, "{", 2) + metricDefinition, submetricDefinition, _ := strings.Cut(name, "{") - metric := me.registry.Get(nameParts[0]) + metric := me.registry.Get(metricDefinition) if metric == nil { - return nil, fmt.Errorf("metric '%s' does not exist in the script", nameParts[0]) + return nil, fmt.Errorf("metric '%s' does not exist in the script", metricDefinition) } - if len(nameParts) == 1 { // no sub-metric + if len(submetricDefinition) == 0 { // no sub-metric return metric, nil } - submetricDefinition := nameParts[1] if submetricDefinition[len(submetricDefinition)-1] != '}' { return nil, fmt.Errorf("missing ending bracket, sub-metric format needs to be 'metric{key:value}'") } diff --git a/metrics/metric.go b/metrics/metric.go index d12a5b5a16a..902d6aff31e 100644 --- a/metrics/metric.go +++ b/metrics/metric.go @@ -48,15 +48,15 @@ func (m *Metric) AddSubmetric(keyValues string) (*Submetric, error) { if kv == "" { continue } - parts := strings.SplitN(kv, ":", 2) + k, v, _ := strings.Cut(kv, ":") - key := strings.Trim(strings.TrimSpace(parts[0]), `"'`) - if len(parts) != 2 { + key := strings.Trim(strings.TrimSpace(k), `"'`) + if v == "" { tags = tags.With(key, "") continue } - value := strings.Trim(strings.TrimSpace(parts[1]), `"'`) + value := strings.Trim(strings.TrimSpace(v), `"'`) tags = tags.With(key, value) } @@ -133,9 +133,9 @@ func ParseMetricName(name string) (string, []string, error) { // For each tag definition, ensure it is correctly formed for i, t := range tags { - keyValue := strings.SplitN(t, ":", 2) + _, value, _ := strings.Cut(t, ":") - if len(keyValue) != 2 || keyValue[1] == "" { + if value == "" { return "", nil, fmt.Errorf("%w, metric %q tag expression is malformed", ErrMetricNameParsing, t) } diff --git a/metrics/thresholds_parser.go b/metrics/thresholds_parser.go index 47067c51dbf..de0c4b0f0c6 100644 --- a/metrics/thresholds_parser.go +++ b/metrics/thresholds_parser.go @@ -142,9 +142,9 @@ var operatorTokens = [7]string{ //nolint:gochecknoglobals // their spaces. func scanThresholdExpression(input string) (string, string, string, error) { for _, op := range operatorTokens { - substrings := strings.SplitN(input, op, 2) - if len(substrings) == 2 { - return strings.TrimSpace(substrings[0]), op, strings.TrimSpace(substrings[1]), nil + left, right, _ := strings.Cut(input, op) + if right != "" { + return strings.TrimSpace(left), op, strings.TrimSpace(right), nil } } diff --git a/output/csv/config.go b/output/csv/config.go index 648f9d46277..5f5afa91b0a 100644 --- a/output/csv/config.go +++ b/output/csv/config.go @@ -69,22 +69,22 @@ func ParseArg(arg string) (Config, error) { pairs := strings.Split(arg, ",") for _, pair := range pairs { - r := strings.SplitN(pair, "=", 2) - if len(r) != 2 { + k, v, _ := strings.Cut(pair, "=") + if v == "" { return c, fmt.Errorf("couldn't parse %q as argument for csv output", arg) } - switch r[0] { + switch k { case "saveInterval": - err := c.SaveInterval.UnmarshalText([]byte(r[1])) + err := c.SaveInterval.UnmarshalText([]byte(v)) if err != nil { return c, err } case "fileName": - c.FileName = null.StringFrom(r[1]) + c.FileName = null.StringFrom(v) case "timeFormat": - c.TimeFormat = null.StringFrom(r[1]) + c.TimeFormat = null.StringFrom(v) default: - return c, fmt.Errorf("unknown key %q as argument for csv output", r[0]) + return c, fmt.Errorf("unknown key %q as argument for csv output", k) } } diff --git a/output/influxdb/util.go b/output/influxdb/util.go index 37478182905..07d1aba235b 100644 --- a/output/influxdb/util.go +++ b/output/influxdb/util.go @@ -63,12 +63,9 @@ func checkDuplicatedTypeDefinitions(fieldKinds map[string]FieldKind, tag string) func MakeFieldKinds(conf Config) (map[string]FieldKind, error) { fieldKinds := make(map[string]FieldKind) for _, tag := range conf.TagsAsFields { - var fieldName, fieldType string - s := strings.SplitN(tag, ":", 2) - if len(s) == 1 { - fieldName, fieldType = s[0], "string" - } else { - fieldName, fieldType = s[0], s[1] + fieldName, fieldType, _ := strings.Cut(tag, ":") + if fieldType == "" { + fieldType = "string" } err := checkDuplicatedTypeDefinitions(fieldKinds, fieldName)