golang支持pg的空间类型point的增加和查询

1,336 阅读1分钟

背景

最近因业务的需求,用到了postgresql的空间类型——point。
本来挺好的,可是当配合上golang写接口就开始不友好了,因为golang原生并不支持。
然后就开始慢慢查资料之路,关于golang的空间类型的CRUD非常少。
最后综合蛮多资料、以及pg的命令操作还要看了一些golang的源码总结了一下。

Show Code

type Point struct {
	lat float64
	lng float64
}

// 实现driver.Valuer接口
func (p *Point) Value() (driver.Value, error) {
	buf := new(bytes.Buffer)
	fmt.Fprintf(buf, "(%f, %f)", p.lat, p.lng)
	return buf.Bytes(), nil
}

func (p *Point) String() string {
	return fmt.Sprintf("(%v, %v)", p.lat, p.lng)
}

// 实现sql.scanner接口
func (p *Point) Scan(val interface{}) (err error) {
	if bb, ok := val.([]uint8); ok {
		tmp := bb[1 : len(bb)-1]
		coors := strings.Split(string(tmp[:]), ",")
		if p.lat, err = strconv.ParseFloat(coors[0], 64); err != nil {
			return err
		}
		if p.lng, err = strconv.ParseFloat(coors[1], 64); err != nil {
			return err
		}
	}
	return nil
}

解释

pg的point相关sql语句

CREATE TABLE tp(id varchar(20), p point); # 建表
INSERT INTO tp values ('123', '(22.02, 120.01)'); # 插入数据

golang的/usr/local/go/src/database/sql/sql.go中的NullString、NullInt64、NullInt32、NullFloat64、NullBool、NullTime等都实现Scan(value interface{}) error 和 Value() (driver.Value, error),对于这两个方法注释是这样的

Scan implements the Scanner interface.
Value implements the driver Valuer interface.

综合一些资料,查询会用到Scan接口,插入会用到Value接口

另外做一个小纠正,许多资料上插入point是

INSERT INTO tp values ('123', 'POINT (22.02 120.01)');

但我测试之后,这个行不太通。应该是和pg的版本有关,我的版本是12.3,用的是

INSERT INTO tp values ('123', '(22.02, 120.01)');

在写Value接口的时候一定要注意对应好正确的形式

问题

这个String()暂时还没有明白作用是什么,看代码应该是一个格式化返回,有兴趣和想法的大家可以补充。