How do I get a geolocation (e.g. the nearest city) from coordinates (e.g. 49.014,8.4043) with Go?
I tried to use golang-geo:
package main
import (
"log"
"github.com/kellydunn/golang-geo"
)
func main() {
p := geo.NewPoint(49.014, 8.4043)
geocoder := new(geo.GoogleGeocoder)
geo.HandleWithSQL()
res, err := geocoder.ReverseGeocode(p)
if err != nil {
log.Println(err)
}
log.Println(string(res))
}
but it gives Schloßplatz 23, 76131 Karlsruhe, Germany
. I would like Karlsruhe
(so: only the city).
How do I get only the city?
The data you are looking to extract is not returned directly from the library. You can, however, perform a request and parse the JSON response yourself to extract the city, rather than the full address:
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/kellydunn/golang-geo"
)
type googleGeocodeResponse struct {
Results []struct {
AddressComponents []struct {
LongName string `json:"long_name"`
Types []string `json:"types"`
} `json:"address_components"`
}
}
func main() {
p := geo.NewPoint(49.014, 8.4043)
geocoder := new(geo.GoogleGeocoder)
geo.HandleWithSQL()
data, err := geocoder.Request(fmt.Sprintf("latlng=%f,%f", p.Lat(), p.Lng()))
if err != nil {
log.Println(err)
}
var res googleGeocodeResponse
if err := json.Unmarshal(data, &res); err != nil {
log.Println(err)
}
var city string
if len(res.Results) > 0 {
r := res.Results[0]
outer:
for _, comp := range r.AddressComponents {
// See https://developers.google.com/maps/documentation/geocoding/#Types
// for address types
for _, compType := range comp.Types {
if compType == "locality" {
city = comp.LongName
break outer
}
}
}
}
fmt.Printf("City: %s
", city)
}
The documentation for the Geocoder
interface from that library says (emphasis mine):
... Reverse geocoding should accept a pointer to a Point, and return the street address that most closely represents it.
So you'll have to either parse the city name from the street address (which is its own challenge) or find a different geocoder library that provides a city explicitly.
Author of golang-geo
here.
For those following along with this stack overflow question, I've answered @moose 's primary question in issue #31 here.
The tl;dr answer to this question is that while the Google Geocoding APIs do support some fuzzy notion of getting different levels of precision, it has yet to be implemented in golang-geo to date.