Go SDK
github.com/netloc8/netloc8-go — Zero-dependency, context-native IP geolocation client for Go.
Installation
go get github.com/netloc8/netloc8-goRequires Go 1.22+. Zero external dependencies — only the Go standard library.
Quick Start
package main
import (
"context"
"fmt"
"log"
"github.com/netloc8/netloc8-go"
)
func main() {
client := netloc8.NewClient( "sk_your_secret_key" )
geo, err := client.LookupIP( context.Background(), "8.8.8.8" )
if err != nil {
log.Fatal( err )
}
fmt.Println( geo.CountryCode() ) // "US"
fmt.Println( geo.CityName() ) // "Mountain View"
fmt.Println( geo.TZ() ) // "America/Los_Angeles"
fmt.Println( geo.ASN() ) // "AS15169"
fmt.Println( geo.Org() ) // "Google LLC"
}Client Methods
| Method | Description |
|---|---|
LookupIP( ctx, ip ) | Look up geolocation for a specific IP address |
LookupMe( ctx ) | Look up geolocation for the caller's own IP |
Both methods accept context.Context for cancellation, timeouts, and tracing. They return (*Geo, error).
LookupMe — Discover Exit IP
LookupMe calls GET /v1/ip/me to geolocate the IP the API sees. With a proxy transport, this discovers the exit IP of the proxy:
import (
"net/http"
"net/url"
"github.com/netloc8/netloc8-go"
)
proxyURL, _ := url.Parse( "socks5://proxy.example.com:1080" )
transport := &http.Transport{ Proxy: http.ProxyURL( proxyURL ) }
client := netloc8.NewClient( "sk_your_key",
netloc8.WithHTTPClient( &http.Client{ Transport: transport } ),
)
geo, err := client.LookupMe( ctx )
if err != nil {
log.Fatal( err )
}
fmt.Println( geo.IP() ) // the proxy's exit IP
fmt.Println( geo.CountryCode() ) // country of the exit nodeNil-Safe Accessors
All accessor methods on *Geo are nil-safe — they never panic, even on partial or empty responses. Returns the zero value when the underlying field is absent.
| Accessor | Returns | Example |
|---|---|---|
geo.IP() | string | "8.8.8.8" |
geo.CountryCode() | string | "US" |
geo.CountryName() | string | "United States" |
geo.RegionCode() | string | "CA" |
geo.RegionName() | string | "California" |
geo.CityName() | string | "Mountain View" |
geo.TZ() | string | "America/Los_Angeles" |
geo.ASN() | string | "AS15169" |
geo.Org() | string | "Google LLC" |
geo.Lat() | float64 | 37.386 |
geo.Lng() | float64 | -122.084 |
You can also access the full struct directly: geo.Location.Country.Unions, geo.Location.District, geo.Meta.Precision, etc.
Helper Functions
| Function | Description |
|---|---|
netloc8.IsEU( geo ) | Check if geolocation is in the EU (checks unions for "EU") |
netloc8.IsPublicIP( ip ) | Check whether an IP is publicly routable |
netloc8.GetClientIP( r ) | Extract the real client IP from HTTP request headers |
netloc8.NormalizeIP( ip ) | Normalize an IP address string (trim, strip zone ID) |
netloc8.Subnet( ip ) | Derive the /24 (v4) or /48 (v6) subnet from an IP |
// EU compliance check
if netloc8.IsEU( geo ) {
// show cookie consent banner, apply GDPR rules, etc.
}
// Extract client IP behind proxies
ip := netloc8.GetClientIP( r ) // checks X-Forwarded-For, CF-Connecting-IP, etc.
// Derive subnet for IP rotation
subnet := netloc8.Subnet( geo.IP() ) // "203.0.113.0/24"GetClientIP header priority
GetClientIP checks headers in order: X-Forwarded-For (first public IP), CF-Connecting-IP, True-Client-IP, X-Real-IP, X-Client-IP, Fastly-Client-IP, Fly-Client-IP.
Error Handling
API errors are returned as *netloc8.APIError with machine-readable codes. Use errors.As for typed error handling:
import "errors"
geo, err := client.LookupIP( ctx, "not-an-ip" )
if err != nil {
var apiErr *netloc8.APIError
if errors.As( err, &apiErr ) {
fmt.Println( apiErr.Code ) // "INVALID_IP"
fmt.Println( apiErr.Message ) // "Invalid IP address format"
fmt.Println( apiErr.Status ) // 400
fmt.Println( apiErr.RequestID ) // "550e8400-..."
}
}Configuration Options
| Option | Default | Description |
|---|---|---|
WithBaseURL( url ) | https://api.netloc8.com | Override the API base URL (for proxies or self-hosted) |
WithHTTPClient( hc ) | http.DefaultClient | Custom http.Client for proxy transports, custom TLS, etc. |
WithTimeout( d ) | 10s | Request timeout for API calls |
WithOrigin( origin ) | — | Origin header for publishable key (pk_) authentication |
WithUserAgent( ua ) | — | Custom User-Agent string (SDK version is appended) |
client := netloc8.NewClient( "sk_your_key",
netloc8.WithTimeout( 5 * time.Second ),
netloc8.WithBaseURL( "https://geo-proxy.internal" ),
netloc8.WithHTTPClient( &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL( proxyURL ),
},
}),
)Concurrency safe
Client is safe for concurrent use across goroutines. Create one client and reuse it for the lifetime of your application.