GoLang存储读取数据库Geography Point类型经纬度值异常问题
问题解决:Geography Point读取数值异常
你的问题出在GeoPoint的Scan方法中,直接通过binary.Read读取整个结构体时,字段顺序与WKB格式的坐标存储顺序不匹配,同时读取逻辑存在错误,导致经纬度数值被错误解析。
错误原因
WKB格式的POINT数据,在字节序和几何类型之后,存储顺序是X(经度)在前,Y(纬度)在后;而你的GeoPoint结构体字段顺序是Lat(纬度)在前、Lng(经度)在后。直接读取整个结构体时,会把经度值读到Lat字段,纬度值读到Lng字段,加上字节序的影响,最终输出完全错误的数值。
修改后的Scan方法
替换原有Scan方法的实现:
// Scan implements the sql.Scanner interface. func (p *GeoPoint) Scan(val interface{}) error { // 处理空值情况 if val == nil { p.Lat = 0 p.Lng = 0 return nil } 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 } // 验证是否为POINT类型(WKB中POINT的类型码是1) if wkbGeometryType != 1 { return fmt.Errorf("invalid geometry type: expected POINT(1), got %d", wkbGeometryType) } // 按WKB顺序先读取经度(X),再读取纬度(Y) var lng float64 var lat float64 if err := binary.Read(r, byteOrder, &lng); err != nil { return err } if err := binary.Read(r, byteOrder, &lat); err != nil { return err } p.Lng = lng p.Lat = lat return nil }
额外优化说明
- 空值处理:新增的空值判断逻辑,避免数据库字段为
NULL时触发解析错误。 - 几何类型验证:确保只有POINT类型的数据被解析,防止非预期的地理数据导致异常。
修改完成后重新测试读取接口,就能得到与数据库存储一致的正确经纬度数值。
内容的提问来源于stack exchange,提问作者Kingsley Simon
相关产品推荐
相关产品推荐

