Inserting and selecting PostGIS Geometry with Gorm

后端 未结 4 1767
星月不相逢
星月不相逢 2021-02-07 15:56

I\'ve been trying to find a way to insert and retrieve geometric types using Golang, and specifically the library gorm. I\'m also attempting to use the library orb that defines

4条回答
  •  迷失自我
    2021-02-07 16:40

    Another solution, which I ended up using was with go-geos, as I discovered I needed to use the GEOS C library. With that, I am able to convert the struct into WKT for inserting (as postgis accepts it as regular text) and convert from WKB when scanning.

    type Geometry4326 *geos.Geometry
    
    // Value converts the given Geometry4326 struct into WKT such that it can be stored in a 
    // database. Implements Valuer interface for use with database operations.
    func (g Geometry4326) Value() (driver.Value, error) {
    
        str, err := g.ToWKT()
        if err != nil {
            return nil, err
        }
    
        return "SRID=4326;" + str, nil
    }
    
    // Scan converts the hexadecimal representation of geometry into the given Geometry4326 
    // struct. Implements Scanner interface for use with database operations.
    func (g *Geometry4326) Scan(value interface{}) error {
    
        bytes, ok := value.([]byte)
        if !ok {
            return errors.New("cannot convert database value to geometry")
        }
    
        str := string(bytes)
    
        geom, err := geos.FromHex(str)
        if err != nil {
            return errors.Wrap(err, "cannot get geometry from hex")
        }
    
        geometry := Geometry4326(geom)
        *g = geometry
    
        return nil
    }
    

    This solution might not be ideal for everyone as not everyone needs to use the GEOS C library, which can be a pain to get working on windows. I'm sure though that the same thing can be accomplished using different libraries.

    I additionally implemented UnmarshalJSON() and MarshalJSON() on the struct so that it can automatically Marshal/Unmarshal GeoJSON, and then save/get from the database seamlessly. I accomplished this using geojson-go to convert GeoJSON to/from a struct, and then geojson-geos-go to convert said struct into the go-geos struct I was using. A little convoluted, yes, but it works.

提交回复
热议问题