arraysgogenericsgo-gorm

How to create a generic array in GO?


I have a function that needs to receive a GORM model as a parameter, and depending on the model I receive as a parameter, I need to create an Array(Slice) based on the type of the struct(gorm model) I receive. How do I create the "records" array of the model type I received?

func main() {
    db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
    if err != nil {
        panic(err)
    }

    db.AutoMigrate(&models.Empresa{}, &models.Estabelecimento{})
    processFiles(db, "EMPRE", models.Empresa{})
    processFiles(db, "ESTABE", models.Estabelecimento{})
}

func processFiles(db *gorm.DB, contains string, model interface{}) {
    for _, fileName := range getCSVFiles(contains) {
        fmt.Println("Processing file", fileName)

        file, err := os.Open(filepath.Join(csvPath, fileName))
        if err != nil {
            panic(err)
        }
        defer file.Close()

        reader := csv.NewReader(file)
        reader.Comma = ';'

        records := ??? //create array by model struct type

        if err := gocsv.UnmarshalCSVWithoutHeaders(reader, &records); err != nil {
            panic(err)
        }
        fmt.Printf("Creating records in database... ")
        db.CreateInBatches(records, 50)
        fmt.Println("Done")
    }
}

Solution

  • Pass a pointer to the slice as an argument instead of creating the slice.

    func processFiles(db *gorm.DB, contains string, records interface{}) {
        for _, fileName := range getCSVFiles(contains) {
            fmt.Println("Processing file", fileName)
    
            file, err := os.Open(filepath.Join(csvPath, fileName))
            if err != nil {
                panic(err)
            }
            defer file.Close()
    
            reader := csv.NewReader(file)
            reader.Comma = ';'
    
            // note that argument is records, not &records
            if err := gocsv.UnmarshalCSVWithoutHeaders(reader, records); err != nil {
                panic(err)
            }
            fmt.Printf("Creating records in database... ")
            db.CreateInBatches(records, 50)
            fmt.Println("Done")
        }
    }
    

    The caller looks like this:

    var records []models.Empresa
    processFiles(db, "EMPRE", &records)