Golang 實現 IP 全球定位
在 Golang 開發中,如何快速獲取 IP 地址的地理位置?無論是安全審計、日誌分析,訪問控制,還是資產測繪,網絡空間搜索等等都可能需要 IP 定位。本篇文章將介紹常見幾種 Golang IP 定位方案,幫助你選擇最合適的方法。
IP 全球定位系統
IP 定位系統是利用多種數據庫,如全球城市數據庫、多語言支持庫、IP 地址數據庫以及地圖服務等資源來精準確定用戶位置。藉助於 IP 地理定位 API,我們能夠依據所提供的 IP 地址獲取詳細的地理位置數據,包括但不限於國家、地區、郵政編碼、經緯度座標、域名及互聯網服務提供商(ISP)信息等。另一方面,W3C 地理定位 API 由萬維網聯盟(W3C)開發,旨在提供一種標準化的方式來探測客戶端的地理位置。例如最常見的來源不外是 IP 地址,WiFi,藍牙 MAC 地址,無線射頻識別(RFID)WiFi 連接的位置等。地理編碼與地理位置是息息相關的,通過查詢相關的地理數據庫來獲取相關位置的地理座標 (經緯度)。總的來說,我們可以通過這些方法來獲取地理位置信息。
使用在線 API 服務(最簡單有錢就行)
在線 API 是最簡單的方式,適合低查詢量、對數據實時性要求高的場景。
常見的 IP 定位 API:
-
IPinfo
-
IP2Location
-
MaxMind
-
Ipstack
-
GeoIP by Abstract
示例代碼(IPinfo API):
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type IPInfo struct {
City string `json:"city"`
Region string `json:"region"`
Country string `json:"country"`
IP string `json:"ip"`
HostName string `json:"hostname"`
Loc string `json:"loc"`
Org string `json:"org"`
Postal string `json:"postal"`
Timezone string `json:"timezone"`
Readme string `json:"readme"`
Anycast bool `json:"anycast"`
}
func main() {
ip := "8.8.8.8"
resp, err := http.Get("https://ipinfo.io/" + ip + "/json")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
var info IPInfo
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
fmt.Println("Decode error:", err)
return
}
fmt.Printf("IP: %s, City: %s, Region: %s, Country: %s\n", info.IP, info.City, info.Region, info.Country)
}
✅ 優點:
-
易用,無需維護數據庫
-
數據實時更新
-
支持全球 IP
❌ 缺點:
-
依賴網絡請求,查詢速度較慢
-
可能有 API 訪問限制
-
需要付費
使用本地 IP 數據庫
如果你的應用不想依賴外部 API,可以使用本地 IP 數據庫,例如:
-
MaxMind GeoLite2
-
IP2Location LITE
-
DB-IP
使用 MaxMind GeoLite2
package main
import (
"fmt"
"log"
"net"
"github.com/oschwald/geoip2-golang"
)
func main() {
db, err := geoip2.Open("GeoIP2-City.mmdb")
if err != nil {
log.Fatal(err)
}
defer db.Close()
ip := net.ParseIP("81.2.69.142")
record, err := db.City(ip)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Portuguese (BR) city name: %v\n", record.City.Names["pt-BR"])
if len(record.Subdivisions) > 0 {
fmt.Printf("English subdivision name: %v\n", record.Subdivisions[0].Names["en"])
}
fmt.Printf("Russian country name: %v\n", record.Country.Names["ru"])
fmt.Printf("ISO country code: %v\n", record.Country.IsoCode)
fmt.Printf("Time zone: %v\n", record.Location.TimeZone)
fmt.Printf("Coordinates: %v, %v\n", record.Location.Latitude, record.Location.Longitude)
}
✅ 優點:
-
查詢速度快,適合高併發應用
-
離線查詢,不依賴外部網絡
-
免費數據庫可滿足大部分需求
❌ 缺點:
-
需要定期更新數據庫
-
數據庫文件較大(幾十 MB, 幾 GB 的都有)
結合 BGP 和 ASN 數據(適合運營商分析)
如果你想查詢 IP 歸屬的網絡運營商(ASN 數據),可以使用:
-
IPIP.net ASN 數據庫
-
Team Cymru IP-ASN 服務
package main
import (
"fmt"
"log"
"net"
"github.com/ipinfo/go/v2/ipinfo"
)
func main() {
const token = "YOUR_TOKEN"
client := ipinfo.NewClient(nil, nil, token)
const ip_address = "8.8.8.8"
info, err := client.GetIPInfo(net.ParseIP(ip_address))
if err != nil {
log.Fatal(err)
}
fmt.Println(info)
}
✅ 適用於:
-
分析 IP 歸屬的網絡運營商
-
檢測雲服務商 IP
-
BGP 歸屬分析
輕量級 IP 庫(適合小型項目)
如果不想使用 API,也不想下載幾十 MB 或者幾 GB 的大數據庫,可以使用輕量級 IP 庫:
- github.com/ip2location/ip2location-go
package main
import (
"github.com/ip2location/ip2location-go"
"fmt"
)
func main() {
r, err := ip2location.OpenRegionInfo("./IP2LOCATION-ISO3166-2.CSV")
if err != nil {
fmt.Print(err)
return
}
res, err := r.GetRegionCode("US", "California")
if err != nil {
fmt.Print(err)
return
}
fmt.Printf("region code: %s\n", res)
}
✅ 優點:
-
體積小,查詢快
-
不需要額外 API 請求
❌ 缺點:
-
精度較低
-
數據庫需要定期更新
總結:哪種方案適合?
-
如果你的應用是高併發查詢,推薦 MaxMind GeoLite2 本地數據庫。
-
如果你需要最新的 IP 數據,推薦 API 服務(如 IPinfo、IP2Location)。
-
如果你想分析 IP 運營商信息,可以結合 ASN 數據。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/2yfP9MucnPaDaaS2yHyvtg