Golang regexp MatchString() isn't idempotent

rog*_*rp6 -1 regex go idempotent

I not sure what's happening. The same function with same input return different results when using regexp library of golang.

package main

import (
    "fmt"
    "regexp"
)

type PaymentNetworkData struct {
    Regex string
    Name  string
}

var PAYMENT_NETWORKS = map[string]PaymentNetworkData{
    "Mastercard": {
        Regex: "^5[1-5][0-9]{14}|^(222[1-9]|22[3-9]\\d|2[3-6]\\d{2}|27[0-1]\\d|2720)[0-9]{12}$",
        Name:  "Mastercard",
    },
    "VisaMaster": {
        Regex: "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$",
        Name:  "VisaMaster",
    },
}

func resolvePaymentNetwork(cardIn string) string {
    payNet := "Unknown"
    for _, v := range PAYMENT_NETWORKS {
        regex := regexp.MustCompile(v.Regex)

        if regex.MatchString(cardIn) {
            payNet = v.Name
        }
    }
    return payNet
}

func main() {

    in := "5103901404433835"

    for i := 1; i < 100; i++ {
        payNet := resolvePaymentNetwork(in)
        fmt.Println("Payment Network is: ", payNet)
    }
}
Run Code Online (Sandbox Code Playgroud)

Input: 5103901404433835

Regex:

Mastercard: ^5[1-5][0-9]{14}|^(222[1-9]|22[3-9]\\d|2[3-6]\\d{2}|27[0-1]\\d|2720)[0-9]{12}$
VisaMaster: ^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$
Run Code Online (Sandbox Code Playgroud)

Golang Output:

Payment Network is:  VisaMaster
Payment Network is:  Mastercard
Payment Network is:  Mastercard
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Run Code Online (Sandbox Code Playgroud)

I tested the same code with NodeJS and in this case the result was always the same.

JS Output:

Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Payment Network is:  VisaMaster
Run Code Online (Sandbox Code Playgroud)

mar*_*lex 6

您的代码有几个问题:

\n
    \n
  1. map无明显原因使用,
  2. \n
  3. 两个正则表达式都与提供的卡号匹配。
  4. \n
\n

这些问题以及通过映射进行迭代不能保证产生相同序列的事实导致了非幂等函数。

\n

这是更正后的代码:

\n
package main\n\nimport (\n    "fmt"\n    "regexp"\n)\n\ntype PaymentNetworkData struct {\n    Regex *regexp.Regexp\n    Name  string\n}\n\nvar PAYMENT_NETWORKS = [2]PaymentNetworkData{\n    {\n        Regex: regexp.MustCompile("^(?:5[1-5][0-9]{14}|(?:222[1-9]|22[3-9]\\\\d|2[3-6]\\\\d{2}|27[0-1]\\\\d|2720)[0-9]{12})$"),\n        Name:  "Mastercard",\n    },\n    {\n        Regex: regexp.MustCompile("^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14})$"),\n        Name:  "VisaMaster",\n    },\n}\n\nfunc resolvePaymentNetwork(cardIn string) string {\n    for _, v := range PAYMENT_NETWORKS {\n        if v.Regex.MatchString(cardIn) {\n            return v.Name\n        }\n    }\n    return "Unknown"\n}\n\nfunc main() {\n    in := "5103901404433835"\n\n    for i := 1; i < 100; i++ {\n        payNet := resolvePaymentNetwork(in)\n        fmt.Println("Payment Network is: ", payNet)\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

它使用数组而不是映射来保证顺序。

\n

另外,我已经改变了你的结构,只编译一次正则表达式。

\n

Payment Network is: Mastercard每次都会输出。

\n

演示在这里

\n

注意,它仍然使用相同的正则表达式( @WiktorStribi\xc5\xbcew 在评论中建议更正)。它们看起来不太好,尤其是这部分(?:4[0-9]{12}(?:[0-9]{3})?- 它也会匹配 13 位数字。
\n您最好检查卡号的预期格式,并相应地更正表达式。

\n