<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rgeo on Sam Smith</title><link>https://samsm.ch/tags/rgeo/</link><description>Recent content in Rgeo on Sam Smith</description><generator>Hugo</generator><language>en-gb</language><lastBuildDate>Sat, 08 Mar 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://samsm.ch/tags/rgeo/index.xml" rel="self" type="application/rss+xml"/><item><title>Rgeo — 5 Years On</title><link>https://samsm.ch/rgeo-5-years-on/</link><pubDate>Sat, 08 Mar 2025 00:00:00 +0000</pubDate><guid>https://samsm.ch/rgeo-5-years-on/</guid><description>&lt;p&gt;5 years ago I wrote &lt;a href="https://github.com/sams96/rgeo"&gt;Rgeo&lt;/a&gt;, a small Go package
for reverse geocoding (you input some coordinates, it gives you information
about the location). Today I am putting the projected on an indefinite hiatus.&lt;/p&gt;
&lt;/br&gt;
&lt;p&gt;That&amp;rsquo;s maybe a tad dramatic for my little project that I barely touch anyway,
but I thought I should be clear about the fact that I&amp;rsquo;m not really working on it
at all, and I thought I&amp;rsquo;d just write up my thoughts about it here.&lt;/p&gt;
&lt;/br&gt;
&lt;p&gt;In the time since, Rgeo has been noticed somewhat (much more than I expected),
gaining over 50 stars on GitHub and getting some really nice contributions. I am
very happy with how the project has been received by others, despite my neglect.&lt;/p&gt;
&lt;p&gt;My main motivation for writing Rgeo in the first place was as a portfolio piece,
something that I could show prospective employers to prove that I can write
decent Go code, since at that time I didn&amp;rsquo;t have any professional experience. It
served that purpose well, I got a job writing Go not long after the initial
release. And after that I lost the motivation to work on it, since I had a full
time job writing Go.&lt;/p&gt;
&lt;p&gt;I have been reflecting on this project recently because, despite the fact that I
am still waiting Go professionally, I&amp;rsquo;ve had some more motivation to work on my
own projects, but not this project. I don&amp;rsquo;t have any use for the package myself
so I’m not finding issues nor coming up with new features to add.&lt;/p&gt;
&lt;h2 id="what-to-use-now"&gt;What to use now&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/smilyorg/tinygpkg"&gt;smilyorg/tinygpkg&lt;/a&gt; - Very nice package
inspired by Rgeo. It uses a different approach to vastly reduce startup time at
the cost of slightly slower queries.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/authenticvision/rgeo"&gt;authenticvision/rgeo&lt;/a&gt; - The most
active fork of Rgeo, and most of the contributions I’ve had have come from
these guys.&lt;/li&gt;
&lt;li&gt;Rgeo - There’s no external API calls here so I don’t really see there being
any security concerns, and I will try to keep dependencies up to date and be
better at merging any fixes that come in. There just won’t be any new features
for the time being (not that there has been for a while).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="rgeo-v20"&gt;Rgeo v2.0&lt;/h2&gt;
&lt;p&gt;I have an idea of what I would like to do for a version 2 if I ever come back to
this project, and that is to split the querying logic (which would stay in the
main package) from the parts specific to the natural earth data geojson files
used (which would go into a new sub-package). This would provide a more general
use for the package in handling data from any source while still giving easy
access to the same existing functionality. I also like
&lt;a href="https://github.com/SaTae66"&gt;SaTae66&lt;/a&gt;’s snapping PR, but I wonder if similarly
things could be generalised and more tools could be provided, for example
querying for the closest geojson feature to a given point.&lt;/p&gt;</description><comments>https://toot.io/@mondoman712/114126461240720151</comments></item><item><title>Rgeo — A Go package for basic, fast, local reverse geocoding</title><link>https://samsm.ch/rgeo/</link><pubDate>Sun, 01 Mar 2020 00:00:00 +0000</pubDate><guid>https://samsm.ch/rgeo/</guid><description>&lt;p&gt;&lt;a href="https://github.com/sams96/rgeo"&gt;Rgeo&lt;/a&gt; is a fast, simple solution for local
reverse geocoding, Rather than relying on external software or online APIs, rgeo
packages all of the data it needs in your binary. This means it will only ever
work down to the level of cities , but if that&amp;rsquo;s all you need then this is the
library for you.&lt;/p&gt;
&lt;p&gt;Rgeo uses data from &lt;a href="https://naturalearthdata.com"&gt;naturalearthdata.com&lt;/a&gt;, if
your coordinates are going to be near specific borders I would advise checking
the data beforehand (links to which are in the files). If you want to use your
own dataset, check out
&lt;a href="https://github.com/sams96/rgeo/tree/master/datagen"&gt;datagen&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="key-features"&gt;Key Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast&lt;/strong&gt; - So I haven&amp;rsquo;t &lt;em&gt;actually&lt;/em&gt; benchmarked other reverse geocoding tools
but on my laptop rgeo can run at under 800ns/op.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local&lt;/strong&gt; - Rgeo doesn&amp;rsquo;t require pinging some API, most of which either cost
money to use or have severe rate limits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightweight&lt;/strong&gt; - The rgeo repo is 141MB, which is large for a Go package but
compared to the 800GB needed for a full planet install of
&lt;a href="https://nominatim.org/release-docs/latest/admin/Installation/#hardware"&gt;Nominatim&lt;/a&gt;
it&amp;rsquo;s miniscule.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;
&lt;p&gt;Download with&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;go get github.com/sams96/rgeo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and add&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;import&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;&amp;#34;github.com/sams96/rgeo&amp;#34;&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to the top of your Go file to include it in your project.&lt;/p&gt;
&lt;h2 id="usage"&gt;Usage&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;r,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#900;font-weight:bold"&gt;New&lt;/span&gt;(Provinces10,&lt;span style="color:#bbb"&gt; &lt;/span&gt;Cities10)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Handle error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;loc,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;r.&lt;span style="color:#900;font-weight:bold"&gt;ReverseGeocode&lt;/span&gt;([]&lt;span style="color:#458;font-weight:bold"&gt;float64&lt;/span&gt;{&lt;span style="color:#099"&gt;141.35&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#099"&gt;43.07&lt;/span&gt;})&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Handle error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Println&lt;/span&gt;(loc)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Output: &amp;lt;Location&amp;gt; Sapporo, Hokkaido, Japan (JPN), Asia&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;First initialise rgeo using &lt;code&gt;rgeo.New&lt;/code&gt;,&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#900;font-weight:bold"&gt;New&lt;/span&gt;(datasets&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;...&lt;/span&gt;&lt;span style="font-weight:bold"&gt;func&lt;/span&gt;()&lt;span style="color:#bbb"&gt; &lt;/span&gt;[]&lt;span style="color:#458;font-weight:bold"&gt;byte&lt;/span&gt;)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(&lt;span style="font-weight:bold"&gt;*&lt;/span&gt;Rgeo,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which takes any non-zero number of datasets as arguments. The included datasets
are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Countries110&lt;/code&gt; - Just country information, smallest and lowest detail of the
included datasets.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Countries10&lt;/code&gt; - The same as above but with more detail.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Provinces10&lt;/code&gt; - Includes province information as well as country, so can
still be used alone.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Cities10&lt;/code&gt; - Just city information, if you want provinces and/or countries as
well use one of the above datasets with it.
Once initialised you can use &lt;code&gt;ReverseGeocode&lt;/code&gt; on the value returned by &lt;code&gt;New&lt;/code&gt;,
with your coordinates to get the location information. See the &lt;a href="https://pkg.go.dev/github.com/sams96/rgeo"&gt;Go
Docs&lt;/a&gt; for more information on usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then use &lt;code&gt;ReverseGeocode&lt;/code&gt; to get the location information of the given coordinate.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;func&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;(r&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;*&lt;/span&gt;Rgeo)&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#900;font-weight:bold"&gt;ReverseGeocode&lt;/span&gt;(loc&lt;span style="color:#bbb"&gt; &lt;/span&gt;geom.Coord)&lt;span style="color:#bbb"&gt; &lt;/span&gt;(Location,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;error&lt;/span&gt;)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The input is a &lt;a href="https://github.com/twpayne/go-geom"&gt;&lt;code&gt;geom.Coord&lt;/code&gt;&lt;/a&gt;, which is just
a &lt;code&gt;[]float64&lt;/code&gt; with the longitude in the zeroth position and the latitude in the
first position (i.e. &lt;code&gt;[]float64{lon, lat}&lt;/code&gt;). &lt;code&gt;ReverseGeocode&lt;/code&gt; returns a
&lt;code&gt;Location&lt;/code&gt;, which looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;type&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;Location&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;struct&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Commonly used country name&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;Country&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;country,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Formal name of country&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;CountryLong&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;country_long,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// ISO 3166-1 alpha-1 and alpha-2 codes&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;CountryCode2&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;country_code_2,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;CountryCode3&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;country_code_3,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;Continent&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;continent,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;Region&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;region,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;SubRegion&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;subregion,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;Province&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;province,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// ISO 3166-2 code&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;ProvinceCode&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;province_code,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;City&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#458;font-weight:bold"&gt;string&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#b84"&gt;`json:&amp;#34;city,omitempty&amp;#34;`&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, to put it all together:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;r,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;rgeo.&lt;span style="color:#900;font-weight:bold"&gt;New&lt;/span&gt;(Countries110)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Handle error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;loc,&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;:=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;r.&lt;span style="color:#900;font-weight:bold"&gt;ReverseGeocode&lt;/span&gt;([]&lt;span style="color:#458;font-weight:bold"&gt;float64&lt;/span&gt;{&lt;span style="color:#099"&gt;0&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="color:#099"&gt;52&lt;/span&gt;})&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="font-weight:bold"&gt;if&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;err&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;!=&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;&lt;span style="font-weight:bold"&gt;nil&lt;/span&gt;&lt;span style="color:#bbb"&gt; &lt;/span&gt;{&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;	&lt;/span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Handle error&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.Country)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.CountryLong)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.CountryCode2)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.CountryCode3)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.Continent)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.Region)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;fmt.&lt;span style="color:#900;font-weight:bold"&gt;Printf&lt;/span&gt;(&lt;span style="color:#b84"&gt;&amp;#34;%s\n&amp;#34;&lt;/span&gt;,&lt;span style="color:#bbb"&gt; &lt;/span&gt;loc.SubRegion)&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Output: United Kingdom&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// United Kingdom of Great Britain and Northern Ireland&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// GB&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// GBR&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Europe&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Europe&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#998;font-style:italic"&gt;// Northern Europe&lt;/span&gt;&lt;span style="color:#bbb"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="projects-using-rgeo"&gt;Projects using rgeo&lt;/h2&gt;
&lt;p&gt;Currently the only project that I know of is my own
&lt;a href="https://github.com/sams96/rgeoSrv"&gt;rgeoSrv&lt;/a&gt;, which aims to wrap rgeo into a
microservice. I am also planning on writing a command line appication to apply
IPTC location tags to images that already contain geolocation information.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works&lt;/h2&gt;
&lt;p&gt;The data used by rgeo is made from a collection of GeoJSON files aquired from
&lt;a href="https://github.com/nvkelso/natural-earth-vector/tree/master/geojson"&gt;Natural Earth
Data&lt;/a&gt;,
which are packaged into Go files by
&lt;a href="https://github.com/sams96/rgeo/tree/master/datagen"&gt;datagen&lt;/a&gt;. The go files
contain functions which return byte slices that contain the base 64 encoded,
gzipped GeoJSON files. They&amp;rsquo;re packaged into function because that seems to be
the only way to have the Go compiler ignore them if they aren&amp;rsquo;t used (so your
program isn&amp;rsquo;t inflated by huge data files that you aren&amp;rsquo;t using).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;New&lt;/code&gt; takes the datasets, decodes the data and parses the GeoJSON. It creates an
&lt;code&gt;Rgeo&lt;/code&gt; struct which contains an &lt;a href="https://github.com/golang/geo"&gt;s2&lt;/a&gt; shape index,
a map to store the location information of each area and an s2 contains point
query. The shape index contains s2 polygons for each of the areas in the given
dataset, and the contains point query is what goes from the input coordinates to
a shape. The map is then used to get the location information from the shape.&lt;/p&gt;
&lt;p&gt;One thing I discovered through working on this is initialising s2 loops and
polygons is very slow and there&amp;rsquo;s no way to store them that doesn&amp;rsquo;t have to run
all the validation code upon loading them. I found that going from creating the
s2 types every time to using geom&amp;rsquo;s &lt;code&gt;IsPointInRing&lt;/code&gt; function yields a ~100x
speed increase. I used s2 types because I wrote rgeo to be used many times in a
program rather than a few, and s2&amp;rsquo;s contains point query is &lt;em&gt;very&lt;/em&gt; fast
(although I don&amp;rsquo;t have any benchmarks to hand).&lt;/p&gt;</description></item></channel></rss>