【问题标题】:Golang Postgresql ArrayGolang Postgresql 数组
【发布时间】:2022-04-08 01:55:38
【问题描述】:

如果我有一个返回如下内容的表:

id: 1
names: {Jim, Bob, Sam}

names 是一个 varchar 数组。

如何在 Go 中将其扫描回 [] 字符串? 我正在使用 lib/pg

现在我有类似的东西

rows, err := models.Db.Query("SELECT pKey, names FROM foo")
for rows.Next() {
            var pKey int
            var names []string
            err = rows.Scan(&pKey, &names)
}

我不断得到:

panic: sql: Scan error on column index 1: unsupported Scan, storing driver.Value type []uint8 into type *[]string

看来我需要使用 StringArray https://godoc.org/github.com/lib/pq#StringArray

但是,我认为我对 Go 太陌生,无法准确理解如何使用: func (a *StringArray) Scan(src interface{})

【问题讨论】:

    标签: postgresql go


    【解决方案1】:

    你是对的,你可以使用StringArray但你不需要调用

    func (a *StringArray) Scan(src interface{})
    

    自己调用,当你传递任何实现Scanner接口的东西时,rows.Scan会自动调用它。

    所以您需要做的是将您的[]string转换*StringArray 并将其传递给rows.Scan,如下所示:

    rows, err := models.Db.Query("SELECT pKey, names FROM foo")
    for rows.Next() {
                var pKey int
                var names []string
                err = rows.Scan(&pKey, (*pq.StringArray)(&names))
    }
    

    【讨论】:

    • 这成功了!那么,这究竟是在做什么呢?是简单的(函数)(参数)吗?
    • 是类型转换,Type(value);有时,在这种情况下,您需要在类型周围加上括号,例如(*Type)(value)。更多信息和示例在这里:golang.org/ref/spec#Conversions
    【解决方案2】:

    长话短说,像这样使用来将 pgSQL 数组转换为 GO 数组,这里第 5 列是一个数组:

    var _temp3  []string
                for rows.Next() {
                    // ScanRows scan a row into temp_tbl
                    err := rows.Scan(&_temp, &_temp0, &_temp1, &_temp2, pq.Array(&_temp3))
    

    详细说明:

    要插入包含数组值的行,请使用 pq.Array 函数,如下所示:

     // "ins" is the SQL insert statement
    ins := "INSERT INTO posts (title, tags) VALUES ($1, $2)"
    
    // "tags" is the list of tags, as a string slice
    tags := []string{"go", "goroutines", "queues"}
    
    // the pq.Array function is the secret sauce
    _, err = db.Exec(ins, "Job Queues in Go", pq.Array(tags))
    

    要将 Postgres 数组值读入 Go 切片,请使用:

    func getTags(db *sql.DB, title string) (tags []string) {
        // the select query, returning 1 column of array type
        sel := "SELECT tags FROM posts WHERE title=$1"
    
        // wrap the output parameter in pq.Array for receiving into it
        if err := db.QueryRow(sel, title).Scan(pq.Array(&tags)); err != nil {
            log.Fatal(err)
        }
    
        return
    }
    

    注意:在 lib/pq 中,只有某些 Go 类型的切片可以传递给 pq.Array()。

    另一个示例,其中 pgSQL 中的 varchar 数组在运行时在第 5 列中生成,例如:

       --> predefined_allow false admin iam.create {secrets,configMap} 
    

    我将其转换为,

    Q := "SELECT ar.policy_name, ar.allow, ar.role_name, pro.operation_name, ARRAY_AGG(pro.resource_id) as resources FROM iam.authorization_rules ar LEFT JOIN iam.policy_rules_by_operation pro ON pro.id = ar.operation_id GROUP BY ar.policy_name, ar.allow, ar.role_name, pro.operation_name;"
            tx := g.db.Raw(Q)
            rows, _ := tx.Rows()
            defer rows.Close()
            var _temp   string
            var _temp0   bool
            var _temp1  string
            var _temp2  string
            var _temp3  []string
            for rows.Next() {
                // ScanRows scan a row into temp_tbl
                err := rows.Scan(&_temp, &_temp0, &_temp1, &_temp2, pq.Array(&_temp3))
                if err != nil {
                    return nil, err
                }
                fmt.Println("Query Executed...........\n", _temp, _temp0, _temp1, _temp2, _temp3)
            }
    

    输出:

    Query Executed...........
    predefined_allow false admin iam.create [secrets configMap]
    

    【讨论】:

      猜你喜欢
      • 2015-08-09
      • 2020-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-23
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      相关资源
      最近更新 更多