IP Geolocation in Go

Using freegeoip.net we can get location information about hostnames or IP addresses. The service returns information like country name, latitude, and longitude. This example will use Go and its Unmarshal() function to decode the response in to a usable struct.

We make an HTTP GET request to freegeoip.net and it will return a JSON response. We read the HTTP JSON response in to a byte slice before we Unmarshal it to our GeoIP structure. The service supports JSON, XML, and CSV responses. It also supports input as hostnames, IPv4, and IPv6 addresses. In this example we call the /json/ URL to get the JSON response. We could just as easily modify our struct and the GET URL to use the XML format.

package main

import (

type GeoIP struct {
        // The right side is the name of the JSON variable
Ip          string  `json:"ip"`
CountryCode string  `json:"country_code"`
CountryName string  `json:"country_name""`
RegionCode  string  `json:"region_code"`
RegionName  string  `json:"region_name"`
City        string  `json:"city"`
Zipcode     string  `json:"zipcode"`
Lat         float32 `json:"latitude"`
Lon         float32 `json:"longitude"`
MetroCode   int     `json:"metro_code"`
AreaCode    int     `json:"area_code"`

var (
address  string
err      error
geo      GeoIP
response *http.Response
body     []byte

func main() {
// Provide a domain name or IP address
address = "www.devdungeon.com"
// address = "2600:3c00::f03c:91ff:fe98:c0f5"
// address = ""

// Use freegeoip.net to get a JSON response
// There is also /xml/ and /csv/ formats available
response, err = http.Get("https://freegeoip.net/json/" + address)
if err != nil {
defer response.Body.Close()

// response.Body() is a reader type. We have
// to use ioutil.ReadAll() to read the data
// in to a byte slice(string)
body, err = ioutil.ReadAll(response.Body)
if err != nil {

// Unmarshal the JSON byte slice to a GeoIP struct
err = json.Unmarshal(body, &geo)
if err != nil {

// Everything accessible in struct now
fmt.Println("\n==== IP Geolocation Info ====\n")
fmt.Println("IP address:\t", geo.Ip)
fmt.Println("Country Code:\t", geo.CountryCode)
fmt.Println("Country Name:\t", geo.CountryName)
fmt.Println("Zip Code:\t", geo.Zipcode)
fmt.Println("Latitude:\t", geo.Lat)
fmt.Println("Longitude:\t", geo.Lon)
fmt.Println("Metro Code:\t", geo.MetroCode)
fmt.Println("Area Code:\t", geo.AreaCode)