Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I build varidics of type interface in Go?

Tags:

sql

mysql

go

I'm building mysql query dynamically ( due the mysql IN clause) so I need to pass a list of arguments as the sql.Query function requires. Any idea how can do that ? I don't really understand how the variadic type works or how I can 'generate' it. If I pass a slice the sql complains that there is only one parameter instead of len(in clause params) thus I can only assume that the function sees the slice as a parameter instead a list ( variadic ) of parameters.

My query / code

var carsa []string
q := `SELECT field1,field2 FROM cooltable WHERE nicecars IN(?` + strings.Repeat(",?", len(ha.cars)-1) + ")"
hs := strings.Join(carsa, "','")
    hs = "'" + hs + "'"

    rows, err := cx.Query(q, country, hs)

sql Query

func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {

Edit: The actual code I'm trying to run fails with error sql: converting Exec argument #0's type: unsupported type []interface {}, a slice

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)

func main() {

    argsS := []string{"apple", "greph", "3rd"}

    db, err := sql.Open("mysql", dbUser+":"+dbPass+"@tcp("+dbHost+":3306)/"+dbName)
    if err != nil {
        return
    }
    query := `SELECT id,label FROM fruits WHERE country=? AND stack IN(?` + strings.Repeat(",?", len(args)-1) + ")"

    args := make([]interface{}, len(ha))
    args["country"] = interface{}("France")

    for i, v := range query {
        args[i] = interface{}(v)
    }

    rows, err := db.Query(q, args...)
    if err != nil {
        return
    }
    var id, label string

    for rows.Next() {
        if err = rows.Scan(&id, label); err != nil {
            fmt.Printf("%v", err)
        }
    }
}
like image 751
hey Avatar asked Oct 12 '25 18:10

hey


1 Answers

With the given function, you can call it with a variable argument list as:

var query string
var args []interface{}
// initialise variables
cx.Query(query, args...)

This is equivalent to calling Query with each of the elements in the args slice passed as separate arguments, as described in the language specification. Note also that the type of the slice needs to match the variadic function definition (so in this case a slice of interface{}.

Note also that the slice needs to represent the entire variadic argument list. So it would be an error to call cx.Query(q, country, hs...), for example. In cases like that, you will need to construct a slice that holds all the arguments you want to pass.


Following on from the question's update, to combine the fixed arguments with your variable ones you want your code to look something like this:

stacks := []string{"apple", "greph", "3rd"}

query := `SELECT id,label FROM fruits WHERE country=? AND stack IN(?` + strings.Repeat(",?", len(stacks)-1) + ")"

args := make([]interface{}, len(stacks)+1)
args[0] = "France"
for i := range stacks {
    args[i+1] = stacks[i]
}

rows, err := cx.Query(query, args...)
like image 122
James Henstridge Avatar answered Oct 14 '25 11:10

James Henstridge