I am trying to save to my database, latitude and longitude values as the geography point datatype and i want to be able to retrieve the values accordingly. I have implemented the following
my model device.go looks like this
device.go
package models
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"fmt"
"time"
"gorm.io/gorm"
)
type GeoPoint struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
func (p *GeoPoint) String() string {
return fmt.Sprintf("SRID=4326;POINT(%v %v)", p.Lng, p.Lat)
}
// Scan implements the sql.Scanner interface.
func (p *GeoPoint) Scan(val interface{}) error {
b, err := hex.DecodeString(string(val.(string)))
if err != nil {
return err
}
r := bytes.NewReader(b)
var wkbByteOrder uint8
if err := binary.Read(r, binary.LittleEndian, &wkbByteOrder); err != nil {
return err
}
var byteOrder binary.ByteOrder
switch wkbByteOrder {
case 0:
byteOrder = binary.BigEndian
case 1:
byteOrder = binary.LittleEndian
default:
return fmt.Errorf("invalid byte order %d", wkbByteOrder)
}
var wkbGeometryType uint32
if err := binary.Read(r, byteOrder, &wkbGeometryType); err != nil {
return err
}
if err := binary.Read(r, byteOrder, p); err != nil {
return err
}
return nil
}
// Value impl.
func (p GeoPoint) Value() (driver.Value, error) {
return p.String(), nil
}
type Device struct {
gorm.Model
Id int `json:"id" gorm:"primaryKey"`
UserId int `json:"user_id" gorm:"uniqueIndex"`
LatestLocation GeoPoint `json:"latest_location" gorm:"type:geography(POINT, 4326)"`
CreatedAt time.Time
UpdatedAt time.Time
}
I am able to save data to the database and this is how it looks like in the database
But when i want to retrieve the record with the latitude and longitude, I get wrong data records and i am not sure why.
this is my code
location.go
package apisLocation
import (
"fmt"
db "atm/pkg/configs/database"
models "atm/pkg/models"
"strconv"
"github.com/gofiber/fiber/v2"
)
func GetLocation(c *fiber.Ctx) error {
userId, err := strconv.Atoi(c.Params("userId"))
if err != nil {
return c.Status(400).JSON(err.Error())
}
if checkIfUserExists(userId) {
return c.Status(400).JSON(fiber.Map{"error": "User does not exist"})
}
var device models.Device
db.DB.Db.Find(&device, models.Device{UserId: userId})
return c.Status(200).JSON(fiber.Map{"location": device.LatestLocation})
}
func checkIfUserExists(userId int) bool {
var device models.Device
db.DB.Db.Find(&device, models.Device{UserId: userId})
return device.Id == 0
}
when i run the GetLocation method, the response i get is not accurate, i get a value of this
"location": {
"lat": 1.7689674224598998e+71,
"lng": -3.639753837714837e+173
},
which isn't the lat and long that is saved in the database.
I think somehow when it is being decoded, something changes but i am not sure how to fix this issue.
Any help is appreciated
