From a
project of mine:I have a latitude and a longitude, e.g. from Google Maps or
OSM, and I need a street name for that.
There is an API named
Nominatim to solve this issue. Go code:
import (
"fmt"
"encoding/xml"
"io/ioutil"
"net/http"
)
// ...
type ReverseGeoCode struct {
// <reversegeocode> mapping
XMLName xml.Name `xml:"reversegeocode"`
AdressParts AdressParts `xml:"addressparts"`
}
type AdressParts struct {
// <adressparts> mapping
XMLName xml.Name `xml:"addressparts"`
HouseNumber string `xml:"house_number"`
Road string `xml:"road"`
Suburb string `xml:"suburb"`
District string `xml:"city_district"`
City string `xml:"city"`
State string `xml:"state"`
Postcode string `xml:"postcode"`
Country string `xml:"country"`
CountryCode string `xml:"country_code"`
}
func CheckError(err error) {
if err != nil {
panic(err)
}
}
func GetXML(url string) ([]byte, error) {
resp, err := http.Get(url)
CheckError(err)
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return []byte{}, fmt.Errorf("Statusfehler: %v", resp.StatusCode)
}
data, err := ioutil.ReadAll(resp.Body)
CheckError(err)
return data, nil
}
func FindAddress(lat float32, lon float32) {
url := fmt.Sprintf("https://nominatim.openstreetmap.org/reverse?lat=%s&lon=%s", lat, lon)
xmlBytes, err := GetXML(url)
CheckError(err)
var xmlFile ReverseGeoCode
xml.Unmarshal(xmlBytes, &xmlFile)
adressData := xmlFile.AdressParts
p1 := ""
p2 := ""
p3 := ""
if adressData.Road != "" {
p1 = fmt.Sprintf("%s %s, ", adressData.Road, adressData.HouseNumber)
}
if adressData.District != "" {
p2 = fmt.Sprintf("%s, ", adressData.District)
}
if adressData.Postcode != "" {
p3 = fmt.Sprintf("%s %s", adressData.Postcode, adressData.City)
}
location := fmt.Sprintf("%s%s%s", p1, p2, p3)
// location has something like "John Doe Street 123, Random District, 12345 Imaginary City" now.
// Save it or whatever.
}