github.com/thinwrap/location-go
thinwrap/location-go for Go — unified facade across 6 providers for routing, matrix, geocoding, and isochrone, with built-in polyline utilities. Truly zero deps (net/http only), stateless, BYO *http.Client.
Go constraints
- Runtime dependencies
- Zero runtime dependencies
- BYO HTTP client
- injectable *http.Client via the WithHTTPClient option
- Provenance
- Go module checksum database (sum.golang.org)
- Minimum runtime
- Go 1.18+
- Truly zero dependencies — the standard library net/http is the only HTTP surface, and AWS SigV4 (Bedrock) / JWT signing (FCM, APNs) are hand-rolled on crypto/*.
- Distributed as a Go module with no build step or codegen: the git tag IS the release. The public module proxy serves it directly and integrity is verified through the Go checksum database (sum.golang.org) and your go.sum — there is no separately signed release artifact, and none is needed for `go get`.
- The default *http.Client never follows redirects — a 3xx surfaces as an error rather than silently re-sending auth headers to another host.
30-second install
go get github.com/thinwrap/location-go2-minute end-to-end example
Compute a route between two waypoints through any supported provider. The example below uses Mapbox; switching providers means changing the config struct — input and output shape stay identical.
import location "github.com/thinwrap/location-go"
r := location.NewRouting(location.MapboxConfig{AccessToken: os.Getenv("MAPBOX_TOKEN")})
res, err := r.Route(ctx, location.RoutingOptions{
Waypoints: []location.LatLng{
{Lat: 37.7749, Lng: -122.4194},
{Lat: 37.3382, Lng: -121.8863},
},
})
if err != nil {
var ce *location.ConnectorError
if errors.As(err, &ce) { log.Printf("%s: %s", ce.ProviderCode, ce.ProviderMessage) }
return
}
fmt.Printf("%.1f km, %.0f min\n", res.TotalDistanceMeters/1000, res.TotalDurationSeconds/60)
fmt.Println(res.Polyline) // Google precision-5 encodedSame code works for all supported routing providers — swap to GoogleConfig, HereConfig,EsriConfig, TomTomConfig, orOsrmConfig{BaseURL: …}. Output normalizes to a single RoutingResult shape across every provider.
Supported providers
| Provider | Operations | Auth | README |
|---|---|---|---|
google Google Maps Platform | routing, matrix, geocoding | query | docs |
mapbox Mapbox | routing, matrix, geocoding, isochrone | query | docs |
here HERE | routing, matrix, geocoding, isochrone | header | docs |
esri ESRI ArcGIS | routing, matrix, geocoding, isochrone | bearer | docs |
tomtom TomTom | routing, matrix, geocoding, isochrone | query | docs |
osrm OSRM (self-hosted) | routing, matrix | header | docs |
Migration paths
Built-in polyline utilities
Every routing connector emits a Google precision-5 encoded polyline onres.Polyline. Decode, re-encode, or convert HERE's flex-polyline / ESRI's path geometry without a third-party library:
points := location.DecodePolyline(res.Polyline) // []LatLng
reEncoded := location.EncodePolyline(points) // back to precision-5
here := location.DecodeFlexPolyline("BFoz5...") // HERE flex-polyline
esri := location.EncodeEsriPaths(paths) // ESRI-JSON {paths, spatialReference}The four polyline primitives are the only encode/decode exports — locked at v1.0, no additional module required.
Operation coverage
Provider × operation gaps below are architectural, not bugs:
- OSRM ships only
routing+matrix— geocoding and isochrone are out of scope by design for OSRM. - Google does not expose a public isochrone API at v1.0.
Bring your own *http.Client
Inject any client satisfyinginterface{ Do(*http.Request) (*http.Response, error) }via WithHTTPClient. The default client never follows redirects (a 3xx surfaces as an error rather than re-sending auth headers). The wrapper holds no state — the HERE/TomTom async-matrix submit-poll-retrieve cycle stays hidden inside a singleMatrix call.
Cross-language siblings
The TypeScript (/packages/location-ts) and PHP (/packages/location-php) variants ship the same facade shape and provider set — cross-language parity is a design goal, not a hard release gate.