在golang的大型ip/子网列表中搜索ip的最快方式?

在golang的大型ip/子网列表中搜索ip的最快方式?,go,Go,请帮助我以最快的方式解决下一个任务 我有一个很大的ip/子网列表,如 35.132.199.128/27 8.44.144.248/32 87.117.185.193 45.23.45.45 等 我需要在go中尽可能快的找到一些ip 当我尝试使用字符串片段和范围时,在大列表中速度非常慢 我可以使用map,比如map[string]string,它看起来很有用,但只用于ip检查,不用于子网检查 有人能帮我解决这个任务吗?谢谢 我的代码 func (app *application) valida

请帮助我以最快的方式解决下一个任务

我有一个很大的ip/子网列表,如

35.132.199.128/27
8.44.144.248/32
87.117.185.193
45.23.45.45
等 我需要在go中尽可能快的找到一些ip

当我尝试使用字符串片段和范围时,在大列表中速度非常慢

我可以使用map,比如map[string]string,它看起来很有用,但只用于ip检查,不用于子网检查

有人能帮我解决这个任务吗?谢谢

我的代码

func (app *application) validateIP(ip string) bool {

for _, item := range app.IPList {

    itemIsIP := net.ParseIP(item)

    if itemIsIP != nil {
        if ip == itemIsIP.String() {
            return true
        }
        continue
    }

    _, itemNet, err := net.ParseCIDR(item)
    if err != nil {
        log.Printf("[ERROR] %+v", err)
    }

    checkedIP := net.ParseIP(ip)

    if itemNet.Contains(checkedIP) {
        return true
    }
}
return false

}我们在项目中解决了这个问题:

isIPV4inCIDRList("35.132.199.128", []string{"35.132.199.128/27"})

func isIPV4inCIDRList(ip []byte, list []string) bool {
    for i := 0; i < 32; i++ {
        sm := strconv.Itoa(i)
        m, _ := mask(sm, 4)
        inv := andIP(ip, []byte(m))
        if len(inv) == 0 {
            continue
        }

        for _, cidr := range list {
            if cidr == inv.String() + "/" + sm {
                return true
            }
        }
    }

    return false
}

func andIP(ip, mask []byte) net.IP {
    inv := net.IP{}
    for i, v := range ip {
        inv = append(inv, mask[i]&v)
    }
    return inv
}

// Bigger than we need, not too big to worry about overflow
const big = 0xFFFFFF

// Decimal to integer.
// Returns number, characters consumed, success.
func dtoi(s string) (n int, i int, ok bool) {
    n = 0
    for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
        n = n*10 + int(s[i]-'0')
        if n >= big {
            return big, i, false
        }
    }
    if i == 0 {
        return 0, 0, false
    }
    return n, i, true
}

func mask(m string, iplen int) (net.IPMask, error) {
    n, i, ok := dtoi(m)
    if !ok || i != len(m) || n < 0 || n > 8*iplen {
        return nil, &net.ParseError{Type: "CIDR address"}
    }
    return net.CIDRMask(n, 8*iplen), nil
}
isIPV4inCIDRList(“35.132.199.128”,[]字符串{“35.132.199.128/27”)
func isIPV4inCIDRList(ip[]字节,list[]字符串)布尔{
对于i:=0;i<32;i++{
sm:=strconv.Itoa(一)
m、 _u:=遮罩(sm,4)
inv:=andIP(ip,[]字节(m))
如果len(inv)==0{
持续
}
对于_,cidr:=范围列表{
如果cidr==存货字符串()+“/”+sm{
返回真值
}
}
}
返回错误
}
func andIP(ip,掩码[]字节)net.ip{
inv:=net.IP{}
对于i,v:=范围ip{
inv=追加(inv、掩码[i]&v)
}
退货库存
}
//比我们需要的大,不太大,不需要担心溢出
常量大=0xFFFFFF
//从十进制到整数。
//返回数字、使用的字符数和成功数。
func dtoi(s字符串)(n int,i int,ok bool){
n=0
对于i=0;i
将ip+CIDR掩码转换为5个字节,并将其存储在uint中,然后将生成的数字用作映射键。如果您想找到某个特定ip属于哪个范围,那么会稍微复杂一点什么是“非常大的列表”?您使用的是二进制搜索吗?您确定代码运行缓慢是因为对列表进行了迭代,还是因为每次比较都要将每个字符串转换为ip&mask?此时,在列表200k记录中,使用代码更新了第一篇文章您正在为每次比较分析每个字符串。先分析这些数据,看看是否足够好,这样做是否有意义?(这也可能有助于从一些真正的基准测试中看出瓶颈在哪里)我认为a将是一个很好的数据结构,可以在这里使用,因为您实际上是在进行前缀搜索。我没有现成的套餐可以推荐,虽然看起来不错。