2

I'm trying to store a Point variable in an SQL database using GORM on a go server, I tried looking everywhere but I haven't seen an answer that satisfies me yet

4

1 回答 1

3

对于标准库的包不支持的任何类型,database/sql也不是依赖于 的 3rd 方包,您可以实现和接口以添加对该类型的自定义支持。database/sqlgormValuerScanner

为了能够正确实现这两个接口,您首先需要找出目标数据库期望作为输入的内容以及作为该类型的输出返回的内容。对于 PostgreSQL 和 Point 类型,语法是(x,y).

因此,您可以执行以下操作:

  1. 声明类型。
type Point struct {
    X, Y float64
}
  1. 实现 Valuer 接口。
func (p Point) Value() (driver.Value, error) {
    out := []byte{'('}
    out = strconv.AppendFloat(out, p.X, 'f', -1, 64)
    out = append(out, ',')
    out = strconv.AppendFloat(out, p.Y, 'f', -1, 64)
    out = append(out, ')')
    return out, nil
}
  1. 实现 Scanner 接口。
func (p *Point) Scan(src interface{}) (err error) {
    var data []byte
    switch src := src.(type) {
    case []byte:
        data = src
    case string:
        data = []byte(src)
    case nil:
        return nil
    default:
        return errors.New("(*Point).Scan: unsupported data type")
    }

    if len(data) == 0 {
        return nil
    }

    data = data[1 : len(data)-1] // drop the surrounding parentheses
    for i := 0; i < len(data); i++ {
        if data[i] == ',' {
            if p.X, err = strconv.ParseFloat(string(data[:i]), 64); err != nil {
                return err
            }
            if p.Y, err := strconv.ParseFloat(string(data[i+1:]), 64); err != nil {
                return err
            }
            break
        }
    }
    return nil
}
于 2021-07-25T19:02:57.297 回答