go get github.com/lionsoul2014/ip2region/binding/golangStarting from version 3.11.0, a dual-protocol compatible and concurrency-safe Ip2Region query service is provided. It is recommended to prioritize this method for query calls. The specific usage is as follows:
import "github.com/lionsoul2014/ip2region/binding/golang/service"
// 1. Create v4 configuration: specify the cache policy and the v4 xdb file path
// Parameter 1: Cache policy, options: service.NoCache / service.VIndexCache / service.BufferCache
// Parameter 2: xdb file path
// Parameter 3: Number of initialized searchers
v4Config, err := service.NewV4Config(service.VIndexCache, "ip2region v4 xdb path", 20)
if err != nil {
return fmt.Errorf("failed to create v4 config: %s", err)
}
// 2. Create v6 configuration: specify the cache policy and the v6 xdb file path
v6Config, err := service.NewV6Config(service.VIndexCache, "ip2region v6 xdb path", 20)
if err != nil {
return fmt.Errorf("failed to create v6 config: %s", err)
}
// 3. Create the Ip2Region query service using the above configurations
ip2region, err := service.NewIp2Region(v4Config, v6Config)
if err != nil {
return fmt.Errorf("failed to create ip2region service: %s", err)
}
// 4. Export the ip2region service for concurrent dual-version IP address queries, for example:
v4Region, err := ip2region.Search("113.92.157.29") // Perform IPv4 query
v6Region, err := ip2region.Search("240e:3b7:3272:d8d0:db09:c067:8d59:539e") // Perform IPv6 query
// 5. When the parent service needs to be closed, close the ip2region query service as well
ip2region.Close()- The API of this query service is concurrency-safe and supports both IPv4 and IPv6 addresses; the internal implementation handles identification automatically.
- v4 and v6 configurations need to be created separately. You can set different cache policies for v4 and v6, or specify one as
nil, which will cause queries for that IP version to return"". - Please set an appropriate number of searchers based on your project's concurrency. This value is fixed during runtime; each query borrows a searcher from the pool to complete the operation and returns it afterward. If the pool is empty during borrowing, it will wait until a searcher becomes available.
- If the cache policy is set to
service.BufferCache(Full Memory Cache), a single-instance memory searcher is used by default. This implementation is natively concurrency-safe, and the specified number of searchers will be ignored. - If
Closeis called while theIp2Regionservice is running, it will wait up to 10 seconds by default for searchers to be returned. You can also callCloseTimeoutto define a custom maximum wait time.
The location information query API prototypes are:
Search(string | []byte) (string, error)If a query fails, the error will contain specific error details. If successful, it returns the region string. If the specified IP cannot be found, it returns an empty string "".
This xdb query client implementation supports both IPv4 and IPv6 queries. Usage is as follows:
// For IPv4: Set the xdb path to the v4 xdb file and specify the IP version as xdb.IPv4
dbPath := "../../data/ip2region_v4.xdb" // Or your ipv4 xdb path
version := xdb.IPv4
// For IPv6: Set the xdb path to the v6 xdb file and specify the IP version as xdb.IPv6
dbPath = "../../data/ip2region_v6.xdb" // Or your ipv6 xdb path
version = xdb.IPv6
// The IP version of the xdb specified by dbPath must match the version specified, otherwise the query will throw an error.
// Note: The following demonstrations directly use the dbPath and version variables.It is recommended to actively verify the applicability of the xdb file. New features in later versions may make the current Searcher version incompatible with your xdb file. Verification helps avoid unpredictable errors during runtime. You do not need to verify every time; for example, run it during service startup or manually via command line to confirm version matching. Do not run verification every time a Searcher is created, as this will impact query response speed, especially in high-concurrency scenarios.
err := xdb.VerifyFromFile(dbPath)
if err != nil {
// err contains the verification error
return fmt.Errorf("xdb file verify: %w", err)
}
// The current Searcher can safely be used for query operations on the xdb specified by dbPath.import (
"fmt"
"github.com/lionsoul2014/ip2region/binding/golang/xdb"
"time"
)
func main() {
// Create a pure file-based query object using version and dbPath
searcher, err := xdb.NewWithFileOnly(version, dbPath)
if err != nil {
fmt.Printf("failed to create searcher: %s\n", err.Error())
return
}
defer searcher.Close()
// Location info query: both IPv4 and IPv6 addresses are supported
var ip = "1.2.3.4" // IPv4
// ip = "240e:3b7:3272:d8d0:db09:c067:8d59:539e" // IPv6
var tStart = time.Now()
region, err := searcher.Search(ip)
if err != nil {
fmt.Printf("failed to Search(%s): %s\n", ip, err)
return
}
// IPv4 or IPv6 location information
fmt.Printf("{region: %s, took: %s}\n", region, time.Since(tStart))
// Note: For concurrent use, each goroutine needs to create an independent searcher object.
}You can pre-load the vectorIndex cache and store it as a global variable. Using the global vectorIndex whenever creating a searcher reduces a fixed IO operation, accelerating queries and reducing system IO pressure.
// 1. Load VectorIndex cache from dbPath and store the vIndex variable globally in memory.
vIndex, err := xdb.LoadVectorIndexFromFile(dbPath)
if err != nil {
fmt.Printf("failed to load vector index from `%s`: %s\n", dbPath, err)
return
}
// 2. Create a query object with VectorIndex cache using the global vIndex.
searcher, err := xdb.NewWithVectorIndex(version, dbPath, vIndex)
if err != nil {
fmt.Printf("failed to create searcher with vector index: %s\n", err)
return
}
// Note: For concurrent use, all goroutines share the global read-only vIndex cache, while each goroutine creates an independent searcher object.You can pre-load the entire xdb file into memory for full memory-based queries, similar to the previous memory search.
// 1. Load the entire xdb from dbPath into memory
cBuff, err := xdb.LoadContentFromFile(dbPath)
if err != nil {
fmt.Printf("failed to load content from `%s`: %s\n", dbPath, err)
return
}
// 2. Create a fully memory-based query object using the global cBuff.
searcher, err := xdb.NewWithBuffer(version, cBuff)
if err != nil {
fmt.Printf("failed to create searcher with content: %s\n", err)
return
}
// Note: For concurrent use, searcher objects created with the entire xdb cache can be safely used for concurrency.Compile to get the xdb_searcher executable through the following method:
# cd to the golang binding root directory first
makeTest xdb queries using the ./xdb_searcher search command:
➜ golang git:(master) ✗ ./xdb_searcher search --help
./xdb_searcher search [command options]
options:
--v4-db string ip2region v4 binary xdb file path
--v4-cache-policy string v4 cache policy, default vectorIndex, options: file/vectorIndex/content
--v6-db string ip2region v6 binary xdb file path
--v6-cache-policy string v6 cache policy, default vectorIndex, options: file/vectorIndex/content
--help print this help menuv4-xdb: IPv4 xdb file path, defaults to data/ip2region_v4.xdb in the repositoryv6-xdb: IPv6 xdb file path, defaults to data/ip2region_v6.xdb in the repositoryv4-cache-policy: Cache policy used for v4 queries, defaults tovectorIndex, options: file/vectorIndex/contentv6-cache-policy: Cache policy used for v6 queries, defaults tovectorIndex, options: file/vectorIndex/content
Example: Perform query tests using the default data/ip2region_v4.xdb and data/ip2region_v6.xdb:
➜ golang git:(master) ✗ ./xdb_searcher search
ip2region search service test program
+-v4 db: /data01/code/c/ip2region/data/ip2region_v4.xdb (vectorIndex)
+-v6 db: /data01/code/c/ip2region/data/ip2region_v6.xdb (vectorIndex)
type 'quit' to exit
ip2region>> 1.2.3.4
{region: Australia|Queensland|Brisbane|0|AU, took: 50.216µs}
ip2region>> 240e:3b7:3272:d8d0:db09:c067:8d59:539e
{region: 中国|广东省|深圳市|电信|CN, took: 100.606µs}
ip2region>> 2604:a840:3::a04d
{region: United States|California|San Jose|xTom|US, took: 99.078µs}Enter an IPv4 or IPv6 address to perform query tests. You can also set cache-policy to file/vectorIndex/content respectively to test the performance of the three different cache implementations.
Perform automatic bench testing using the xdb_searcher bench command. This ensures that both the program and the xdb file are free of errors, and provides average query performance through a large number of queries:
➜ golang git:(fr_xdb_ipv6) ./xdb_searcher bench
./xdb_searcher bench [command options]
options:
--db string ip2region binary xdb file path
--src string source ip text file path
--cache-policy string cache policy: file/vectorIndex/contentExample: Perform ipv4 bench testing using data/ip2region_v4.xdb and data/ipv4_source.txt:
./xdb_searcher bench --db=../../data/ip2region_v4.xdb --src=../../data/ipv4_source.txt Example: Perform ipv6 bench testing using data/ip2region_v6.xdb and data/ipv6_source.txt:
./xdb_searcher bench --db=../../data/ip2region_v6.xdb --src=../../data/ipv6_source.txt You can set the cache-policy parameter to test the efficiency of file/vectorIndex/content cache mechanisms respectively.
Please note that the src file used for bench needs to be the same source file used to generate the corresponding xdb file.
The bench program will read the source IP file specified by src line by line, then select the start and end IPs from each IP segment for testing to ensure that the queried region information matches the original region information. There is no debug information output during the test; if an error occurs, the error message will be printed and execution will terminate. Seeing Bench finished indicates the bench was successful. Cost represents the average time for each query operation (ns).