dominikh / go-tools

Staticcheck - The advanced Go linter
https://staticcheck.dev
MIT License
6.03k stars 362 forks source link

False SA6000 when regex inside switch inside range #1502

Open delve opened 4 months ago

delve commented 4 months ago

staticcheck 2023.1.6 (v0.4.6) reports

main.go:17:16: calling regexp.MatchString in a loop has poor performance, consider using regexp.Compile (SA6000)

on the code

package main

import "regexp"

func main() {
    test := map[string]string{
        "foo":    "things",
        "bar":    "stuff",
        "grepme": "haystack",
    }

    for key, val := range test {
        switch key {
        case "foo": // do things
        case "bar": // do stuff
        case "grepme":
            match, _ := regexp.MatchString("a", val)
            println(match)
        }
    }
}

I'm new to Go so perhaps I'm doing it wrong, but it seems that the switch key will only allow the regex to run once, making the lint finding invalid. OTOH maybe this is too small/awkward a case to warrant handling? Since it depends on several factors (ranging over map keys and switching on the key)

versions

$ staticcheck -debug.version
staticcheck 2023.1.6 (v0.4.6)

Compiled with Go version: go1.21.5
Main module:
        honnef.co/go/tools@v0.4.6 (sum: h1:oFEHCKeID7to/3autwsWfnuv69j3NsfcXbvJKuIcep8=)
Dependencies:
        github.com/BurntSushi/toml@v1.2.1 (sum: h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=)
        golang.org/x/exp/typeparams@v0.0.0-20221208152030-732eee02a75a (sum: h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE=)
        golang.org/x/mod@v0.12.0 (sum: h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=)
        golang.org/x/sys@v0.11.0 (sum: h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=)
        golang.org/x/tools@v0.12.1-0.20230825192346-2191a27a6dc5 (sum: h1:Vk4mysSz+GqQK2eqgWbo4zEO89wkeAjJiFIr9bpqa8k=)

$ go version
go version go1.21.5 linux/amd64
dominikh commented 4 months ago

You're right that in this particular instance, the suggestion isn't useful. We probably could try to handle it, but it should be noted that at first glance, at least for this minimal example, the use of a loop seems odd.

delve commented 4 months ago

Yes, the example above is contrived for brevity. In my actual code I receive a map[string]struct from a 3rd party module which will have some or all of a set of options. The set of options returned is based on user input, unpredictable, and each key must be processed uniquely. So I use the above procedure to deal with it.

If you happen to know a better way to handle that I'd love some hints. :)