postgresql使用gorm遇到的问题

[TOC]

背景

最近接手了一个使用postgresql的项目,说真的,第一次在项目中使用。
我使用的是iris+gorm, 踩到了坑,花了一天才解决。

Array字段问题

解决办法是使用github.com/lib/pq

使用示例

package models

import "github.com/lib/pq"

type Info struct {
    ID  uint64
    Title *string `gorm:"not null"`
    Pic pq.StringArray `gorm:"type:varchar(100)[]"`
}

JSON 字段问题

解决办法是自定义一个JSON类型, 在gorm的issue中找到的。

type JSON []byte
func (j JSON) Value() (driver.Value, error) {
    if j.IsNull() {
        return nil, nil
    }
    return string(j), nil
}
func (j *JSON) Scan(value interface{}) error {
    if value == nil {
        *j = nil
        return nil
    }
    s, ok := value.([]byte)
    if !ok {
        errors.New("Invalid Scan Source")
    }
    *j = append((*j)[0:0], s...)
    return nil
}
func (m JSON) MarshalJSON() ([]byte, error) {
    if m == nil {
        return []byte("null"), nil
    }
    return m, nil
}
func (m *JSON) UnmarshalJSON(data []byte) error {
    if m == nil {
        return errors.New("null point exception")
    }
    *m = append((*m)[0:0], data...)
    return nil
}
func (j JSON) IsNull() bool {
    return len(j) == 0 || string(j) == "null"
}
func (j JSON) Equals(j1 JSON) bool {
    return bytes.Equal([]byte(j), []byte(j1))
}

使用示例

package models

import "github.com/lib/pq"

type Info struct {
    PubRes JSON  `sql:"type:json" json:"object,omitempty"`
    AuditRes string
}

time字段问题

golang对应的是time.Time, 但是time是形如08:00:00的形式,导致解析失败。

解决办法也是自定义类型。

type LocalTime time.Time
//转为数据库对象
func (l LocalTime) Value() (driver.Value, error) {
    stamp := fmt.Sprintf("\"%s\"", time.Time(l).Format("15:04:05"))
    return stamp, nil
}
//数据库对象转过来
func (l *LocalTime) Scan(value interface{}) error {
    s, ok := value.(time.Time)
    if !ok {
        errors.New("Invalid Scan Source")
    }
    *l = LocalTime(s)
    return nil
}
//对象变字符串
func (l LocalTime) MarshalJSON() ([]byte, error) {
    stamp := fmt.Sprintf("\"%s\"", time.Time(l).Format("15:04:05"))
    return []byte(stamp), nil
}
//字符串变对象
func (l *LocalTime) UnmarshalJSON(data []byte) error {
    if l == nil {
        return errors.New("null point exception")
    }
    //去掉前后的"
    t, err := time.Parse("15:04:05", string(data[1:len(data)-1]))
    if err != nil {
        return err
    }
    *l = LocalTime(t)
    return nil
}

使用示例

type Merchant struct {
    Base
    ID uint64 `gorm:"primary_key" json:"id"`
    AutoPubTime *LocalTime `gorm:"type:time" json:"auto_pub_time,editable"`
}