简体   繁体   English

去反射与gorm库

[英]Go reflect with gorm library

I am using gorm package ( https://github.com/jinzhu/gorm ) as my database library in golang. 我正在使用gorm软件包( https://github.com/jinzhu/gorm )作为我在golang中的数据库库。 I have many classes (database tables) like "Hotel" or "Package". 我有很多类(数据库表),例如“ Hotel”或“ Package”。 Duplicating code is not good programming practice. 复制代码不是好的编程习惯。 As a silly example - lets assume I want to get first object from each table. 作为一个愚蠢的例子-假设我想从每个表中获取第一个对象。 I can write this method ( GetFirstHotel , GetFirstPackage ...) for each object. 我可以为每个对象编写此方法( GetFirstHotelGetFirstPackage ...)。 But better way would be to have just a single method GetFirstItem , where I would use first param to create object with same class as parameter, then pass it to gorm, which will fill it with data from database, then return it as interface{} . 但是更好的方法是只有一个方法GetFirstItem ,在这里我将使用第一个参数创建具有与参数相同的类的对象,然后将其传递给gorm,它将用数据库中的数据填充它,然后将其返回为interface{} I tried to use reflect for that, but failed, because I probably don't understand it much. 我尝试为此使用反射,但失败了,因为我可能不太了解。

Maybe I just didn't discover some function in gorm library, or I can't use reflect package properly. 也许我只是没有在gorm库中发现某些功能,或者我不能正确使用反射包。 How should I implement GetFirstItem function. 我应该如何实现GetFirstItem函数。 Is it possible to have this implemented, or should I rather repeat my code? 是否可以实现此功能,还是我应该重复我的代码?

package main

import (
    "github.com/jinzhu/gorm"
)

var db gorm.DB

type Hotel struct {
    ID   int64
    Name string
    Lat  float64
    Lon  float64
}

type Package struct {
    ID   int64
    Name string
    Text string
}

func GetFirstHotel() (hotel Hotel) {
    db.First(&hotel)
}

func GetFirstPackage() (pack Package) {
    db.First(&pack)
}

func main() {
    var firstHotel, firstPackage interface{}

    //first method
    firstHotel = GetFirstHotel()
    firstPackage = GetFirstPackage()

    //method i want to use
    firstHotel = GetFirstItem(Hotel{})
    firstPackage = GetFirstItem(Package{})
}

func GetFirstItem(item interface{}) interface{} {
    //how to implement this?
    //probably with some use of reflect package
}

The db.First method returns db reference and hydrates the row into the passed structure. db.First方法返回db引用,并将行合并为传递的结构。

The closest to your desired method is 最接近所需方法的是

func GetFirstItem(item interface{}) error {
    return db.First(item).Error
}

This simply requires you keep a reference to the parameter 这只是需要保留对参数的引用

var firstHotel &Hotel{}
err := GetFirstItem(firstHotel)

Returning the hydrated object for all types would required type parameters (generics). 返回所有类型的水合对象将需要类型参数(泛型)。 I think you'll find the current situation is workable within limits. 我认为您会发现当前情况在一定范围内是可行的。

see also: Why no generics in Go? 另请参阅: 为什么Go中没有泛型?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM