简体   繁体   中英

Go reflect with gorm library

I am using gorm package ( https://github.com/jinzhu/gorm ) as my database library in golang. I have many classes (database tables) like "Hotel" or "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. 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{} . 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. How should I implement GetFirstItem function. 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.

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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