Golang Postgresql 数组

10
如果我有一个返回类似以下内容的表格:
id: 1
names: {Jim, Bob, Sam}

names是一个varchar数组。

我该如何在Go中将其扫描回[]string呢?我正在使用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{})

2个回答

11
您是正确的,您可以使用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))
}

这个有效!那么,它到底在做什么?它只是(函数)(参数)吗? - Chemdream
1
这是一种类型转换,Type(value);有时,就像在这种情况下一样,您需要在类型周围加上括号,例如 (*Type)(value)。更多信息和示例请参见:https://golang.org/ref/spec#Conversions - mkopriva
1
pq.StringArray 无法处理 null,但 PostgreSQL 数组可以包含 NULL。更好的方法是使用 pq.Array(),就像 ak89224 的答案中所示,结合 sql.NullString 使用。 - Jonas

4

长话短说,使用如下方式将pgSQL数组转换为GO数组,在此处第五列作为一个数组:

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]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接