Thank you for your interest in contributing to GoGIS! This document provides guidelines and information for contributors.
We are committed to providing a welcoming and inclusive experience for everyone. Please be respectful in all interactions.
- Search existing issues first to avoid duplicates
- Use the issue template when creating new issues
- Provide clear reproduction steps for bugs
- Include relevant system information (Go version, PostgreSQL version, PostGIS version)
- Check the roadmap to see if the feature is already planned
- Open an issue with the "enhancement" label
- Describe the use case and why the feature would be valuable
- Consider implementation complexity and backward compatibility
- Fork the repository and create a feature branch
- Write tests for your changes
- Follow the coding standards outlined below
- Update documentation if needed
- Submit a pull request with a clear description
- Go 1.19 or later
- PostgreSQL 12+ with PostGIS 3.0+
- Git
-
Clone your fork:
git clone https://github.com/yourusername/gogis.git cd gogis -
Install dependencies:
go mod download
-
Set up test database:
CREATE DATABASE gogis_test; \c gogis_test; CREATE EXTENSION postgis;
-
Set environment variables:
export TEST_DATABASE_URL="host=localhost user=postgres dbname=gogis_test sslmode=disable"
-
Run tests:
go test -v ./...
- Follow Go Code Review Comments
- Use
gofmtto format code - Use meaningful variable names
- Add comments for exported functions and types
- Keep functions focused and small
- GoDoc comments for all exported types and functions
- Usage examples in comments when helpful
- Update README.md for significant changes
- Include code examples in documentation
- Unit tests for all public functions
- Table-driven tests for multiple test cases
- Integration tests for database operations (with build tags)
- Test edge cases and error conditions
- Aim for high test coverage (>90%)
func TestPointString(t *testing.T) {
tests := []struct {
name string
point Point
expected string
}{
{
name: "positive coordinates",
point: Point{Lng: -74.0445, Lat: 40.6892},
expected: "SRID=4326;POINT(-74.0445 40.6892)",
},
// More test cases...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.point.String()
if result != tt.expected {
t.Errorf("Point.String() = %v, want %v", result, tt.expected)
}
})
}
}- Rebase your branch on the latest main
- Run all tests and ensure they pass
- Run linters (golint, govet)
- Update documentation if needed
- Add yourself to CONTRIBUTORS.md
- Use a descriptive title that explains the change
- Reference related issues in the description
- Explain the motivation for the change
- List any breaking changes clearly
- Include screenshots for UI changes (if applicable)
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] All existing tests pass
- [ ] New tests added for new functionality
- [ ] Manual testing completed
## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No new warnings or errorsWhen adding new PostGIS geometry types:
- Create new file named
{type}.go - Implement required interfaces:
Geometry,sql.Scanner,driver.Valuer - Add comprehensive documentation
- Include WKB parsing with both endianness support
- Add to GeometryCollection if applicable
- Write complete test suite
- Add usage examples
gogis/
├── doc.go # Package documentation
├── point.go # Point implementation
├── linestring.go # LineString implementation
├── polygon.go # Polygon implementation
├── geometry_collection.go # GeometryCollection implementation
├── point_test.go # Point tests
├── linestring_test.go # LineString tests
├── polygon_test.go # Polygon tests
├── geometry_collection_test.go # GeometryCollection tests
├── examples/ # Usage examples
│ ├── README.md
│ ├── basic_usage.go
│ ├── linestring_example.go
│ ├── polygon_example.go
│ └── geometry_collection_example.go
├── INDEXING.md # Performance guide
├── CONTRIBUTING.md # This file
└── README.md # Main documentation
All geometry types must implement:
type Geometry interface {
String() string // WKT representation
}
// Plus sql.Scanner and driver.Valuer from database/sql- Return descriptive errors with context
- Use fmt.Errorf for error wrapping
- Validate input parameters before processing
- Handle nil values gracefully
- Test all public methods
- Test error conditions
- Test edge cases (empty geometries, nil values)
- Use table-driven tests for multiple scenarios
- Test with real PostGIS database
- Use build tags:
// +build integration - Test WKB parsing with actual PostGIS output
- Test complex spatial queries
- Benchmark critical operations
- Test with realistic data sizes
- Compare with/without spatial indexes
Every exported type and function must have:
// Point represents a geometric point in 2D space.
//
// Point implements the PostGIS Point geometry type and can be used in GORM models
// to store geographic locations. It uses the WGS 84 coordinate system (SRID 4326).
//
// Example:
// point := Point{Lng: -74.0445, Lat: 40.6892}
// fmt.Println(point.String()) // "SRID=4326;POINT(-74.0445 40.6892)"
type Point struct {
Lng float64 `json:"lng"` // Longitude in decimal degrees
Lat float64 `json:"lat"` // Latitude in decimal degrees
}When adding features, update:
- Feature list
- Usage examples
- API documentation
- Migration notes (for breaking changes)
We follow Semantic Versioning:
- MAJOR: Breaking changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
- Update version in relevant files
- Update CHANGELOG.md
- Tag the release
- Update documentation
- Announce the release
- GitHub Issues: For bugs and feature requests
- GitHub Discussions: For questions and general discussion
- Email: For security issues (private)
Contributors will be:
- Added to CONTRIBUTORS.md
- Mentioned in release notes
- Credited in documentation (for significant contributions)
Thank you for contributing to GoGIS!