GoGIS is a comprehensive Go library that provides PostGIS geometry types for GORM, enabling seamless integration of spatial data with your Go applications.
β¨ Complete PostGIS Integration - Full support for Point, LineString, Polygon, and GeometryCollection types
π GORM Compatible - Implements sql.Scanner
and driver.Valuer
for automatic ORM integration
πΊοΈ WGS 84 Support - Uses SRID 4326 coordinate system for global geographic data
π Well-Known Formats - Supports both WKB (Well-Known Binary) and WKT (Well-Known Text)
β‘ High Performance - Optimized for spatial queries with proper indexing support
π§ͺ Thoroughly Tested - Comprehensive test suite with >95% coverage
π Well Documented - Complete API documentation and usage examples
go get github.com/restayway/gogis
- Go 1.19+
- PostgreSQL 12+ with PostGIS 3.0+
- GORM v2
Enable PostGIS extension in your PostgreSQL database:
CREATE EXTENSION IF NOT EXISTS postgis;
package main
import (
"github.com/restayway/gogis"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Location struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"not null"`
Point gogis.Point `gorm:"type:geometry(Point,4326)"`
}
func main() {
// Connect to database
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic(err)
}
// Auto-migrate
db.AutoMigrate(&Location{})
// Create location
location := Location{
Name: "Statue of Liberty",
Point: gogis.Point{
Lng: -74.0445, // Longitude
Lat: 40.6892, // Latitude
},
}
db.Create(&location)
// Spatial query - find locations within 1km
var nearby []Location
db.Where("ST_DWithin(point, ST_Point(?, ?), ?)",
-74.0445, 40.6892, 0.009).Find(&nearby)
}
Represents a single location with longitude and latitude coordinates.
type Location struct {
ID uint `gorm:"primaryKey"`
Name string
Point gogis.Point `gorm:"type:geometry(Point,4326)"`
}
location := Location{
Name: "Central Park",
Point: gogis.Point{
Lng: -73.9665, // Longitude (X)
Lat: 40.7812, // Latitude (Y)
},
}
Represents paths, routes, or any sequence of connected points.
type Route struct {
ID uint `gorm:"primaryKey"`
Name string
Path gogis.LineString `gorm:"type:geometry(LineString,4326)"`
}
route := Route{
Name: "Broadway Walk",
Path: gogis.LineString{
Points: []gogis.Point{
{Lng: -73.9857, Lat: 40.7580}, // Times Square
{Lng: -73.9857, Lat: 40.7614}, // North on Broadway
{Lng: -73.9855, Lat: 40.7682}, // Further north
},
},
}
Represents areas with outer boundaries and optional holes.
type Region struct {
ID uint `gorm:"primaryKey"`
Name string
Area gogis.Polygon `gorm:"type:geometry(Polygon,4326)"`
}
region := Region{
Name: "Central Park",
Area: gogis.Polygon{
Rings: [][]gogis.Point{
{ // Outer boundary
{Lng: -73.9812, Lat: 40.7644},
{Lng: -73.9734, Lat: 40.7644},
{Lng: -73.9734, Lat: 40.7947},
{Lng: -73.9812, Lat: 40.7947},
{Lng: -73.9812, Lat: 40.7644}, // Close the ring
},
// Optional: holes can be added as additional rings
},
},
}
Represents collections of heterogeneous geometries.
type Place struct {
ID uint `gorm:"primaryKey"`
Name string
Geometries gogis.GeometryCollection `gorm:"type:geometry(GeometryCollection,4326)"`
}
place := Place{
Name: "Campus",
Geometries: gogis.GeometryCollection{
Geometries: []gogis.Geometry{
&gogis.Point{Lng: -73.9550, Lat: 40.8050}, // Building
&gogis.LineString{Points: walkwayPoints}, // Walkway
&gogis.Polygon{Rings: campusAreaRings}, // Campus area
},
},
}
// Find locations within 1km of a point
var locations []Location
db.Where("ST_DWithin(point, ST_Point(?, ?), ?)",
lng, lat, 0.009).Find(&locations)
// Find nearest 10 locations
db.Order("ST_Distance(point, ST_Point(?, ?))").
Limit(10).Find(&locations, lng, lat)
// Find points within a polygon
var pointsInside []Location
db.Where("ST_Contains(?, point)", polygon.String()).Find(&pointsInside)
// Find polygons containing a point
var regions []Region
db.Where("ST_Contains(area, ST_Point(?, ?))", lng, lat).Find(®ions)
// Find routes that intersect with an area
var routes []Route
db.Where("ST_Intersects(path, ?)", polygon.String()).Find(&routes)
// Find overlapping regions
var overlapping []Region
db.Where("ST_Overlaps(area, ?)", otherPolygon.String()).Find(&overlapping)
// Calculate polygon areas in square meters
db.Select("*, ST_Area(ST_Transform(area, 3857)) as area_meters").Find(®ions)
// Calculate route lengths in meters
db.Select("*, ST_Length(ST_Transform(path, 3857)) as length_meters").Find(&routes)
Create spatial indexes for optimal query performance:
-- For points
CREATE INDEX idx_locations_point ON locations USING GIST (point);
-- For linestrings
CREATE INDEX idx_routes_path ON routes USING GIST (path);
-- For polygons
CREATE INDEX idx_regions_area ON regions USING GIST (area);
-- For geometry collections
CREATE INDEX idx_places_geometries ON places USING GIST (geometries);
- Use ST_DWithin instead of ST_Distance with WHERE clauses
- Create compound indexes for frequently filtered queries
- Use ST_Transform for accurate distance/area calculations
- Consider partial indexes for large datasets
See INDEXING.md for detailed performance optimization guide.
Comprehensive examples are available in the examples/
directory:
- basic_usage/ - Point operations and spatial queries
- linestring_example/ - Routes and path analysis
- polygon_example/ - Area operations and containment
- geometry_collection_example/ - Complex geometries
Run examples:
cd examples/basic_usage && go run main.go
cd examples/linestring_example && go run main.go
cd examples/polygon_example && go run main.go
cd examples/geometry_collection_example && go run main.go
go test -v
# Set up test database
createdb gogis_test
psql gogis_test -c "CREATE EXTENSION postgis;"
# Run integration tests
go test -tags=integration -v
go test -bench=. -benchmem
Full API documentation is available at pkg.go.dev.
If migrating from other PostGIS Go libraries:
- Update imports: Change to
github.com/restayway/gogis
- Update struct tags: Use
gorm:"type:geometry(Type,4326)"
- Update coordinate order: GoGIS uses
{Lng, Lat}
(longitude, latitude) - Update method calls: Check method names in documentation
See CHANGELOG.md for detailed migration information between versions.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
- Fork the repository
- Create a feature branch
- Write tests for your changes
- Ensure all tests pass
- Submit a pull request
- 3D Geometry Support - PointZ, LineStringZ, PolygonZ
- Additional Geometry Types - MultiPoint, MultiLineString, MultiPolygon
- Custom SRID Support - Beyond SRID 4326
- Spatial Functions - Built-in Go implementations of common operations
- GeoJSON Integration - Direct GeoJSON marshaling/unmarshaling
- Performance Optimizations - Further query performance improvements
This project is licensed under the MIT License - see the LICENSE file for details.
- PostGIS Team - For the excellent spatial database extension
- GORM Team - For the fantastic ORM library
- Go Community - For the great language and ecosystem
- π Documentation: pkg.go.dev
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π§ Email: For security issues
GoGIS - Bringing PostGIS spatial capabilities to the Go ecosystem with GORM integration. Build location-aware applications with confidence! π