【问题标题】:sql: converting argument $1 type: unsupported type []int, a slice of insql:转换参数 $1 类型:不支持的类型 []int,in 的一部分
【发布时间】:2019-05-27 17:36:15
【问题描述】:

有这个:

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

知道了:

sql:转换参数 $1 类型:不支持的类型 []int,int 切片

有什么方法可以让一部分参数与 lib/pq 一起工作?

【问题讨论】:

    标签: postgresql go


    【解决方案1】:

    pq.Array 就是答案:

    somevars := []int{1, 2, 3, 4}
    rows, err = db.Query("SELECT c1,c2 FROM table"+tid+" WHERE c1 = any($1);", pq.Array(somevars))
    

    【讨论】:

      【解决方案2】:

      另一种解决方案是

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

      这里... 将一个切片扩展为多个参数,类似于python *args。它记录在in the language spec

      db.Query API 支持这个所谓的可变参数。

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

      这里interface{}被称为空接口,它可以保存任何类型的值。请参阅Go tour example here。所以可以像这样使用它

      db.Query(stmt, var1, var2)

      其中var1 var2 可以是不同的类型。

      在您的情况下,您也可以显式传递切片元素

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

      但它相当冗长,当切片长度发生变化时需要额外的工作。

      请注意,如果我们使用intvars := []int {1, 2, 3, 4} 而不是interface 切片somevars 并在db.Query() 中扩展intvars,编译器将报错intvars...

      不能在赋值中使用 []int 字面量(类型 []int)作为类型 []interface {}

      类型转换intvars.([]interface{}) 也不起作用。这记录在language spec FAQ 中。还有一个dedicated wiki page for it

      语言规范不允许这样做,因为这两种类型在内存中的表示形式不同。

      golanginterface的直观图是一个有两个字段的对象,一个字段存储一个类型,另一个存储一个指针。

      【讨论】:

      • 这太酷了!但我需要将 int 切片转换为类型接口,这是几行额外的代码。
      • 不需要类型转换。 int 类型(和所有类型)满足 interface{} 类型。见this example
      • 哦,所以一定是在 linter 里买东西。会检查的,谢谢!
      • 我刚试过,确实不行。我会更新答案。
      【解决方案3】:

      更通用的解决方案是使用sqlx 库: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...)
      

      此解决方案适用于多个数据库驱动程序和未知长度的切片。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-21
        • 2020-12-03
        • 1970-01-01
        • 2018-09-01
        • 2013-10-04
        • 2021-06-16
        • 2014-06-16
        相关资源
        最近更新 更多