Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams
somevars := []int{1, 2, 3, 4}
rows, err = db.Query("SELECT c1,c2 FROM table"+tid+" WHERE c1 IN($1,$2,$3,$4);", somevars)

Got this:

sql: converting argument $1 type: unsupported type []int, a slice of int

Any way to make a slice of arguments work with lib/pq?

You are replacing IN with =. Will they do the same thing in this case? Where is this documented? – Johan Walles Dec 14, 2022 at 9:06
somevars := []interface{}{1, 2, 3, 4}
rows, err = db.Query(
    "SELECT c1,c2 FROM table"+tid+" WHERE c1 IN($1,$2,$3,$4);",
    somevars...)

Here the ... expands a slice to multiple arguments, similar to the python *args. It's documented in the language spec.

The db.Query API supports this so called variadic parameter.

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

Here interface{} is known as the empty interface, and it can hold values of any type. See the Go tour example here. So one can use it like

db.Query(stmt, var1, var2)

where var1 var2 could be of different types.

In your case, you can also pass the slice elements explicitly

db.Query(stmt,
         somevars[0], somevars[1], somevars[2], somevars[3])

But it is rather verbose and requires extra work when the slice length changes.

Note that if instead of the interface slice somevars, we use intvars := []int {1, 2, 3, 4} and expand intvars in db.Query(), the compiler will complain on intvars...

cannot use []int literal (type []int) as type []interface {} in assignment

Type conversion intvars.([]interface{}) doesn't work either. This is documented in the language spec FAQ. And there is also a dedicated wiki page for it

It is disallowed by the language specification because the two types do not have the same representation in memory.

The intuitive picture of golang interface is an object with two fields, one field stores a type, and the other stores a pointer.

This is cool! But i need to convert the int slice to a type interface and that's a few extra lines of code. – Gabriel Dec 31, 2018 at 14:20 There is no need for type conversion. int type (and all types) satisfies interface{} type. See this example. – nos Dec 31, 2018 at 17:09

A more generalizable solution is to use the sqlx library: https://jmoiron.github.io/sqlx/#inQueries

// assume db is an initialized database handle
somevars := []int{1,2,3,4}
query, args, err := sqlx.In("SELECT * FROM table WHERE id IN (?)", somevars)
if err != nil {
  return err
query = db.Rebind(query)
result := db.Select(query, args...)

This solution will work with multiple database drivers and slices of unknown length.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.