如何使用GORM存储嵌入式结构?

时间:2015-02-13 15:29:53

标签: postgresql go

如果我有类似这样的类型

,如何使用GORM存储嵌入式结构
type A struct {
    point GeoPoint
}

type GeoPoint struct {
    Lat float64
    Lon float64
}

GORM尝试将其添加到新表中,但我想将其添加为另一个字段。

如何做到这一点?

4 个答案:

答案 0 :(得分:1)

对于任何人,谁正在寻找将结构放入GORM模型并使其自动编组和解组的方法。

此解决方案基于 chris 的答案。而且有效!

例如,我想将Parents中的Childrens数组作为经过编组的JSON:

type Child struct {
    Lat float64
    Lng float64
}

type ChildArray []Children

func (sla *ChildArray) Scan(src interface{}) error {
    return json.Unmarshal(src.([]byte), &sla)
}

func (sla ChildArray) Value() (driver.Value, error) {
    val, err := json.Marshal(sla)
    return string(val), err
}

type Parent struct {
    *gorm.Model    
    Childrens ChildArray `gorm:"column:childrens;type:longtext"`
}

答案 1 :(得分:0)

我对Gorm并不熟悉,但是对于 sqlx ,您将需要实现sql.Scanner和sql.Valuer接口,以将数据转换为postgres point类型。下面的代码不会检查错误,因此需要进行一些调整。

https://play.golang.org/p/2-Y-wSeAWnj

package main

import (
    "database/sql/driver"
    "fmt"
    "strconv"
    "strings"
)

type GeoPoint struct {
    Lat float64
    Lon float64
}

func (gp GeoPoint) Value() (driver.Value, error) {
    return fmt.Sprintf("(%d,%d)", gp.Lat, gp.Lon), nil
}

func (gp GeoPoint) Scan(src interface{}) error {
    raw := src.(string)
    coords := raw[1 : len(raw)-1]
    vals := strings.Split(coords, ",")
    gp.Lat, _ = strconv.ParseFloat(vals[0], 64)
    gp.Lon, _ = strconv.ParseFloat(vals[1], 64)
    return nil
}

func main() {
    gp := GeoPoint{Lat: 112, Lon: 53}
    d, _ := gp.Value()
    fmt.Printf("%+v\n", d)

    gp.Scan("(53, -110)")
    fmt.Printf("%+v\n", gp)
}

答案 2 :(得分:0)

首先,使用gorm绝不会将字段放在低位情况下。

如果确保将GeoPoint链接为Aid,则可以使用ForeingKey标记,例如 确保ID是表A的主键。

type A struct {
    Id int `gorm:"column:"id""`
    Point GeoPoint `gorm:"column:geo_point;ForeignKey:OrderId"`
}

type GeoPoint struct {
    Aid int
    Lat float64
    Lon float64
}

func main(){
    ...
    ...
    var as []A
    if e:=db.Model(&A{}).Find(&as).Error;e!=nil{
        handle(e)
    }
    fmt.Println(as)
}

如果未通过主键链接。您可以使用类似

的中间件
type A struct {
    Id int `gorm:"column:"id""`
    Point GeoPoint `gorm:"column:geo_point"`
}

func (a *A) AfterFind()error{
   return db.Model(&GeoPoint{}).First(&(a.Point)).Error
}

type GeoPoint struct {
    Aid int
    Lat float64
    Lon float64
}

func main(){
    ...
    ...
    var as []A
    if e:=db.Model(&A{}).Find(&as).Error;e!=nil{
        handle(e)
    }
    fmt.Println(as)
}

答案 3 :(得分:0)

您可以尝试:

   type A struct {
    point GeoPoint `gorm:"embedded"`
}