You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
goip/ip2region/qqery.go

74 lines
1.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package ip2region
import (
"errors"
"net"
"strconv"
)
type QueryResult struct {
Ip string `json:"ip,omitempty"` // ip
CityId int64 `json:"city_id,omitempty"` // 城市代码
Country string `json:"country,omitempty"` // 国家
Region string `json:"region,omitempty"` // 区域
Province string `json:"province,omitempty"` // 省份
City string `json:"city,omitempty"` // 城市
Isp string `json:"isp,omitempty"` // 运营商
}
func (ip QueryResult) String() string {
return ip.Ip + "|" + strconv.FormatInt(ip.CityId, 10) + "|" + ip.Country + "|" + ip.Region + "|" + ip.Province + "|" + ip.City + "|" + ip.Isp
}
// Query memory算法整个数据库全部载入内存单次查询都在0.1x毫秒内
func (c *Client) Query(ipAddress net.IP) (result QueryResult, err error) {
result.Ip = ipAddress.String()
if c.totalBlocks == 0 {
if err != nil {
return QueryResult{}, err
}
c.firstIndexPtr = getLong(dbBuff, 0)
c.lastIndexPtr = getLong(dbBuff, 4)
c.totalBlocks = (c.lastIndexPtr-c.firstIndexPtr)/IndexBlockLength + 1
}
ip, err := ip2long(result.Ip)
if err != nil {
return QueryResult{}, err
}
h := c.totalBlocks
var dataPtr, l int64
for l <= h {
m := (l + h) >> 1
p := c.firstIndexPtr + m*IndexBlockLength
sip := getLong(dbBuff, p)
if ip < sip {
h = m - 1
} else {
eip := getLong(dbBuff, p+4)
if ip > eip {
l = m + 1
} else {
dataPtr = getLong(dbBuff, p+8)
break
}
}
}
if dataPtr == 0 {
return QueryResult{}, errors.New("not found")
}
dataLen := (dataPtr >> 24) & 0xFF
dataPtr = dataPtr & 0x00FFFFFF
result = getIpInfo(result.Ip, getLong(dbBuff, dataPtr), dbBuff[(dataPtr)+4:dataPtr+dataLen])
return result, nil
}