Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot use args (type []string) as type []interface {} [duplicate]

Tags:

go

my golang sqlite insert function. i'm using this package "github.com/mattn/go-sqlite3"

func Insert(args ...string)(err error){
  db, err:=sql.Open("sqlite3","sqlite.db")
  if err !=nil {
    return
  }
  q, err := db.Prepare(args[0])
  if err !=nil{
    return
  }
  _,err = q.Exec(args[1:]...)
  return
 }
main (){
  err := Insert("INSERT INTO table(first,last) VALUES(?,?)","Nantha","nk")
  if err !=nil{
  fmt.Println(err.Error())
    return
  }
}

i'm getting this error

cannot use args (type []string) as type []interface {} in argument to q.Exec

like image 948
Ram Avatar asked Apr 02 '26 12:04

Ram


1 Answers

The error is pretty clear, the function expects type []interface{} but you're passing in a value of type []string. You have to first convert []string to []interface{} before passing it to Exec. And the way to do that is to loop over the strings and add each one to a new slice of interface{}.

https://golang.org/doc/faq#convert_slice_of_interface


As an alternative approach, you can change the Insert argument types.

func Insert(query string, args ...interface{}) (err error) {
    db, err := sql.Open("sqlite3", "sqlite.db")
    if err != nil {
        return err
    }
    q, err := db.Prepare(query)
    if err != nil {
        return err
    }
    _, err = q.Exec(args...)
    return err
}

func main() {
    err := Insert("INSERT INTO table(first,last) VALUES(?,?)", "Nantha", "nk")
    if err !=nil{
        fmt.Println(err.Error())
        return
    }
}

Please note that you're using the database/sql package incorrectly. Many of the objects returned from that package's functions/methods need to be closed to release the underlying resources.

This is true for *sql.DB returned by Open, *sql.Stmt returned by Prepare, *sql.Rows returned by Query, etc.

So your function should look closer to something like this:

func Insert(query string, args ...interface{}) (err error) {
    db, err := sql.Open("sqlite3", "sqlite.db")
    if err != nil {
        return err
    }
    defer db.Close()

    q, err := db.Prepare(query)
    if err != nil {
        return err
    }
    defer q.Close()

    _, err = q.Exec(args...)
    return err
}

Also note that sql.DB is reusable, that means that you don't have to sql.Open a new instance every time you need to talk to the database.

From the docs on Open:

The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections. Thus, the Open function should be called just once. It is rarely necessary to close a DB.

If you keep doing it the way you're doing it, openning a new DB every time you call Insert or any other function that needs to talk to the DB, your program will perform worse than if you had a single DB and have your functions reuse that.

like image 185
mkopriva Avatar answered Apr 04 '26 07:04

mkopriva



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!