Golang在非常大的结构中找到ip范围

时间:2016-03-18 10:26:37

标签: go

我有一个类似于下面的结构,大约有10万个人。

我想循环它,检查一下ip地址是否在范围内。

我目前的代码:

type Users struct {
    Id        string
    Descr     string
    IpStart   string
    IpEnd     string
}
var users []*Users



func LookUpIP(IpAddress string) (string, string) {
    iptocheck := net.ParseIP(IpAddress)
    for _, elem := range users {
        if bytes.Compare(iptocheck, elem.IpStart) >= 0 && bytes.Compare(iptocheck, elem.IpEnd) <= 0 {
            fmt.Printf("%v is between %v and %v\n", IpAddress, elem.IpStart, elem.IpEnd)
            return elem.Id, elem.Descr 
        }
    }
    return "0", "null"
}

上述工作正常,大约40k entires,但结果很慢。有没有更快的方法来确定我的结构中的ip地址是否在范围内?

更新:现在只解析ip一次并将其存储为struct

中的数字

2 个答案:

答案 0 :(得分:2)

我看到了两个简单的步骤。

  1. 进行一次解析并将IP地址存储为单个数字。
  2. 按范围的开头订购范围,然后使用binary search

答案 1 :(得分:0)

完成@Grzegorz Żur建议使用二进制搜索来缩短搜索时间时,这里是一个二元搜索实现。

但首先是什么是二分搜索?二进制搜索将一系列值分成两半,并继续缩小搜索范围,直到找到未知值。这是“分而治之”算法的典型例子。

算法返回某个元素的索引,该元素等于给定值(如果有多个这样的元素,则返回一些任意元素)。当找不到元素时,也可以返回它的“插入点”(如果它插入到数组中,则该值将具有的索引)。

递归方法

func binarySearch(a []float64, value float64, low int, high int) int {
    if high < low {
        return -1
    }
    mid := (low + high) / 2 // calculate the mean of two values
    if a[mid] > value {
        return binarySearch(a, value, low, mid-1)
    } else if a[mid] < value {
        return binarySearch(a, value, mid+1, high)
    }
    return mid
}

迭代方法

func binarySearch(a []float64, value float64) int {
    low := 0
    high := len(a) - 1
    for low <= high {
        mid := (low + high) / 2
        if a[mid] > value {
            high = mid - 1
        } else if a[mid] < value {
            low = mid + 1
        } else {
            return mid
        }
    }
    return -1
}

但是如果你看一下sort package,你可以发现已经实现了基于二分搜索的排序算法。所以这可能是最好的选择。