如何在Golang中从Postgres数组中获取一个切片?

huangapple go评论86阅读模式
英文:

How do I get a slice from a Postgres array in Golang?

问题

假设我有一个像这样的 PostgreSQL 查询:

SELECT
  id,
  ARRAY_AGG(code) AS code
FROM
  codes
WHERE id = '9252781'
GROUP BY id;

我的返回结果如下:

id       | codes
---------+-------------
9252781  | {H01,H02}

idcodes 都是 varchar 类型。

在 Golang 中,当我遍历结果的行时,它会卡住,没有错误,也没有任何提示。

英文:

Let's say I have a postgres query like:

SELECT
  id,
ARRAY_AGG(code) AS code
  FROM
    codes
WHERE id = '9252781' 
GROUP BY id;

My return looks like:

 id        |  codes
-----------+-------------
 9252781   | {H01,H02}

Both id and codes are varchar.

In Golang when I scan along the rows for my result, it just freezes. No error, nothing.

答案1

得分: 5

如果你正在使用github.com/lib/pq的PostgreSQL驱动程序,你可以使用它们的pq.Array辅助函数来扫描和存储PostgreSQL数组。

var id string
var arr []string

row := db.QueryRow(`SELECT '9252781', ARRAY['H01','H02']`)
if err := row.Scan(&id, pq.Array(&arr)); err != nil {
    log.Fatal(err)
}

log.Println(id, arr)
// 9252781 [H01 H02]
英文:

If you're using the github.com/lib/pq postgres driver you can use their pq.Array helper function to scan and store postgres arrays.

var id string
var arr []string

row := db.QueryRow(`SELECT '9252781', ARRAY['H01','H02']`)
if err := row.Scan(&id, pq.Array(&arr)); err != nil {
	log.Fatal(err)
}

log.Println(id, arr)
// 9252781 [H01 H02]

答案2

得分: 1

我不想使用额外的驱动程序(github.com/lib/pq),而且我没有找到任何pgx的方法来实现,除非创建自己的类型。

所以我创建了一个:

type Tags []string
func (t *Tags) Scan(v interface{}) error {
        if v == nil {
                *t = Tags{}
                return nil
        }
        s, ok := v.(string)
        if !ok {
                return fmt.Errorf("从数据库接收到的值应为字符串,但得到了 [%+v]", v)
        }
        s = strings.TrimPrefix(s, "{")
        s = strings.TrimSuffix(s, "}")
        *t = strings.Split(s, ",")
        return nil
}
func (t *Tags) Value() (driver.Value, error) {
        s := fmt.Sprintf("{%v}", strings.Join(([]string)(*t), ","))
        return s, nil
}

然后你可以像这样扫描从数据库返回的行:

...
    err := rows.Scan(
        ...
        &Tags,
        ...
    )

然后你可以直接在你的Exec查询中使用它。

这段代码可以很好地处理数组中的常量,但如果要在逗号和括号中使用它,你需要做更多的工作。

英文:

I don't want to use a additional driver (github.com/lib/pq), and I did not found any pgx way to do it other than creating my own type.

So I did one:

type Tags []string
func (t *Tags) Scan(v interface{}) error {
        if v == nil {
                *t = Tags{}
                return nil
        }
        s, ok := v.(string)
        if !ok {
                return fmt.Errorf("Scan is expected to receive a string from database, but got [%+v]", v)
        }
        s = strings.TrimPrefix(s, "{")
        s = strings.TrimSuffix(s, "}")
        *t = strings.Split(s, ",")
        return nil
}
func (t *Tags) Value() (driver.Value, error) {
        s := fmt.Sprintf("{%v}", strings.Join(([]string)(*t), ","))
        return s, nil
}

then you can scan the row returned from database like:

...
    err := rows.Scan(
        ...
        &Tags,
        ...
    )

and you can use it directly you your Exec queries.

This code works well with constants in arrays, but you need more work if want to use it in commas and brackets.

huangapple
  • 本文由 发表于 2017年4月29日 13:31:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/43692136.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定