Search code examples
mysqlgoslicevariadicgo-gorm

Golang Join array interface


I try to create bulk insert. I use gorm github.com/jinzhu/gorm

import (
    "fmt"
    dB "github.com/edwinlab/api/repositories"
)

func Update() error {
    tx := dB.GetWriteDB().Begin()
    sqlStr := "INSERT INTO city(code, name) VALUES (?, ?),(?, ?)"
    vals := []interface{}{}

    vals = append(vals, "XX1", "Jakarta")
    vals = append(vals, "XX2", "Bandung")

    tx.Exec(sqlStr, vals)

    tx.Commit()

    return nil
}

But I got an error:

Error 1136: Column count doesn't match value count at row 1 becuse i return wrong query

INSERT INTO city(code, name) VALUES ('XX1','Jakarta','XX2','Bandung', %!v(MISSING)),(%!v(MISSING), %!v(MISSING))

If I use manual query it works:

tx.Exec(sqlStr, "XX1", "Jakarta", "XX2", "Bandung")

It will generate:

INSERT INTO city(code, name) VALUES ('XX1', 'Jakarta'),('XX2', 'Bandung')

The problem is how to make array interface to generate string like "XX1", "Jakarta", ...

Thanks for help.


Solution

  • If you want to pass elements of a slice to a function with variadic parameter, you have to use ... to tell the compiler you want to pass all elements individually and not pass the slice value as a single argument, so simply do:

    tx.Exec(sqlStr, vals...)
    

    This is detailed in the spec: Passing arguments to ... parameters.

    Tx.Exec() has the signature of:

    func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)
    

    So you have to pass vals.... Also don't forget to check returned error, e.g.:

    res, err := tx.Exec(sqlStr, vals...)
    if err != nil {
        // handle error
    }