Library / SDK
golang/geo avatar
golang/geo

golang/geo tracks S2 type availability

S2 geometry library in Go

1,853 stars198 forksGoApache-2.0

At a glance

What is it?
golang/geo is the Go port of Google's S2 spherical geometry library, and unlike most ports it ships a per type status table showing which C++ types are feature complete, mostly complete or absent. The gaps cluster around the encoded and indexed types, so the honest question is not whether the port is finished but which specific operations you need.
Who is it for?
Take golang/geo if your Go service needs exact predicates and snap rounded constructive operations on the sphere, and if the specific S2 types your design relies on appear as complete or mostly complete in the README status table. Leave it if your pipeline reads GIS formats or needs planar geometry, both of which the README places outside scope, or if you need the encoded index types and shape index region, which are marked unavailable.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • golang/geo1,853 ★ · -1
Star history
Repository2026-10-162026-10-23
golang/geo1.9k1.9k

-1 Stars in the last 7 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Spherical by default, planar on purpose

S2 operates on shapes drawn on a sphere rather than on a planar 2D map, and the README says that is the primary design decision rather than an afterthought. The name comes from the mathematical notation for the unit sphere, S2, which is a fair description of the whole design.

The scope list is concrete. Representations of angles, intervals, latitude-longitude points and unit vectors, with operations on those types. Geometric shapes over the unit sphere: spherical caps described as discs, latitude-longitude rectangles, polylines and polygons, collectively called regions. A hierarchical decomposition of the sphere into cells, starting from the six faces of a projected cube and subdividing them quadtree style. Constructive operations such as union, and boolean predicates such as containment, over arbitrary collections of points, polylines and polygons. Fast in-memory indexing of those collections. Distance measurement and nearby object search. Snapping and simplification with accuracy and topology guarantees. Exact mathematical predicates for testing relationships. And spatial indexing support, including approximating regions as collections of discrete S2 cells, which the README says is what makes large distributed spatial indexes easy to build.

Two things are explicitly out of scope: planar geometry, and conversions to and from common GIS formats. That second exclusion has practical consequences. If your data arrives as shapefiles or GeoJSON, something else has to parse it before it reaches this library.

The package layout mirrors the mathematics rather than the use case: r1 for one dimensional Cartesian coordinates, r2 for two dimensions, r3 for three dimensions, s1 for circular geometry, s2 for spherical geometry, and earth for turning angles and steradians into distances and areas using the earth's radius.

What the accuracy guarantee actually says

The README defines the guarantee rather than asserting it. Core operations are designed to be 100% robust, meaning each operation makes strict mathematical guarantees about its output and is implemented to meet those guarantees for all possible valid inputs.

The polygon intersection example is the clearest statement of what that buys. The output is guaranteed to be topologically correct, up to the creation of degeneracies, and the boundary of the output is guaranteed to stay within a user-specified tolerance of the true mathematically exact result.

Three techniques are named as how the guarantee is achieved: conservative error bounds, exact geometric predicates, and snap rounding. The first bounds how wrong an intermediate answer can be, the second replaces floating point comparison with something decidable, and the third quantises coordinates so that points which should coincide do coincide.

The library also aims to be precise about definitions, not just about numbers. Whether a region includes its boundary, and how degeneracies are handled, are treated as decisions to be specified. Numerical accuracy is a second concern, with cancellation error called out as something to minimise.

One framing sentence matters for expectations. The intent is to represent geometry as a mathematical abstraction: the unit sphere is a useful approximation for the earth's surface, but functions specifically related to geography are not part of the core library. Easting and northing conversions, ellipsoid approximations and the geodetic versus geocentric distinction are all named as things the core does not do. The earth package is the boundary where some of that reappears.

The status table is the most useful page in the repository

golang/geo is described as principally a port of the C++ S2 library, adapting to Go idioms where it makes sense, and the README tracks progress type by type against the C++ original. The legend is three states: feature complete, mostly complete, and not available.

The lower dimensional packages are done. R1Interval, R2Point, R2Rect, R3Vector, R3ExactVector, Matrix3x3, S1Angle, S1ChordAngle and S1Interval are all marked feature complete, so the primitives are not where the risk lies.

In the spherical package the pattern is clearer. S2Cap, S2Cell, S2CellId, S2CellUnion, S2Coords, S2DistanceTarget, S2EdgeVector, S2LatLng, S2LatLngRect, S2Loop, S2PaddedCell, S2Point, S2PointVector, S2Polyline, S2Region, S2RegionCoverer, S2RegionUnion and S2ShapeIndex are complete. S2CellIndex, S2LaxLoop, S2LaxPolygon, S2LaxPolyline and S2Polygon are mostly complete.

The unavailable types include EncodedLaxPolygon, EncodedLaxPolyline, EncodedShapeIndex, EncodedStringVector, EncodedUintVector, IdSetLexicon, ValueSetLexicon and SequenceLexicon. Point indexing is missing too: S2PointIndex, S2PointSpan, S2PointRegion and S2CellIdVector. S2RegionIntersection, S2R2Rect, S2ShapeIndexRegion, S2DensityTree, LaxClosedPolyline and VertexIDLaxLoop are also absent.

So if your design needs one of those types, the README marks it as not available.

Building and consuming a Go module with almost no dependencies

There is nothing to install beyond the module. go.mod declares the module as github.com/golang/geo with a language level of go 1.23.0, and a comment in the file explains that this version may be updated freely up to oldstable and that.github/workflows/go.yml has to be updated when it is bumped.

The dependency list contains two entries, both marked indirect: github.com/google/go-cmp at v0.7.0 and github.com/google/go-units at v0.0.0-20250612230646-eddd77f68220.

Consumption follows the standard module path, and the package documentation lives on pkg.go.dev per package rather than as a single site. The README points to s2geometry.io for details about S2 in general, which is the right place to read about the algorithms since the Go repository is a port rather than the canonical description.

Beyond dependencies, the CI signals in the README badge row are worth noting for a library you would depend on: a Go build and test workflow, CodeQL code scanning, golangci-lint, and an OpenSSF Scorecard badge. There is also a SECURITY.md and a CONTRIBUTING.md at the top level. The repository has no GitHub releases, so dependency management goes through module pseudo versions and the last push was on 2026-10-13.

How the alternatives actually differ

The README names the equivalents: the C++ original at google/s2geometry, a Java port at google/s2-geometry-library-java, and a Python binding inside the C++ repository. The interesting comparison is not feature for feature, because the algorithms are the same, but about what you inherit.

The README measures the Go port's type coverage against the C++ library, so its status table is the place to check corresponding type availability.

The genuinely different alternative is not another S2 port. It is treating coordinates as planar, using a Mercator projection and a 2D geometry library, which is the default approach in a lot of mapping code. The difference in approach is exactly what the README refuses: on a sphere, distances and areas are not linear, a rectangle in latitude-longitude is not a rectangle in shape, and predicates that hold on a plane fail near the poles and across the antimeridian. The cost of S2 is that every operation has to be spherical, and the benefit is that the answers match the geometry of the earth rather than the geometry of a projection.

Editorial conclusion

Take golang/geo if your Go service needs exact predicates and snap rounded constructive operations on the sphere, and if the specific S2 types your design relies on appear as complete or mostly complete in the README status table. Leave it if your pipeline reads GIS formats or needs planar geometry, both of which the README places outside scope, or if you need the encoded index types and shape index region, which are marked unavailable. Verify first that your compiler is Go 1.23.0 or newer as go.mod requires, then check the status row for each type you plan to call rather than assuming the port is complete, and treat the earth package as the only place where real geography happens.

Frequently asked questions

Is the golang/geo port of S2 complete?

Not entirely, and the README tracks it per type. Lower dimensional types in r1, r2, r3 and s1 are marked feature complete, while in the s2 package S2CellIndex, S2LaxLoop, S2LaxPolygon, S2LaxPolyline and S2Polygon are mostly complete, and the encoded and point indexing types are marked not available.

Does golang/geo parse shapefiles or GeoJSON?

No. The README places conversions to and from common GIS formats outside the scope of the library, along with planar geometry. You will need another component to parse your input formats.

What Go version does golang/geo require?

go.mod declares go 1.23.0, and a comment in that file notes the version may be updated freely up to oldstable, with .github/workflows/go.yml updated when it changes. The module has only two indirect dependencies.

What does robustness mean in the S2 library?

Core operations are designed to be 100% robust, meaning each makes strict mathematical guarantees and meets them for all valid inputs. For a polygon intersection the output is topologically correct up to degeneracies and its boundary stays within a user-specified tolerance, using conservative error bounds, exact predicates and snap rounding.

Official sources

  1. golang/geo on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/golang-geo.svg)](https://hysenlabs.com/projects/golang-geo)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/golang-geo.svg)](https://hysenlabs.com/projects/golang-geo)

Was this useful?