gpt4 book ai didi

sql - 如何避免可空 JSON 列上的​​扫描对 : *json. RawMessage 错误?

转载 作者:IT王子 更新时间:2023-10-29 01:06:38 29 4
gpt4 key购买 nike

几周前,我开始学习 go 并尝试在学习基础知识的同时构建一个简单的博客应用程序。

目前我正在尝试使用 database/sqlgithub.com/lib/pq 包来获取和保存博客文章。我不喜欢在不完全了解 native 行为和 go 基础知识的情况下使用 3rd 方包,如 sqlxgorm

我的 Post 结构是这样的:

type Post struct {
Id int
Title string
Body string
Tags json.RawMessage
}

当保留帖子时,我的 save() 函数可以正常工作:

func (p *Post) save() (int, error) {
const query = `INSERT INTO post (title, body, tags) VALUES($1, $2, $3) RETURNING id`
db := GetDB()
var postid int
err := db.QueryRow(query, p.Title, p.Body, p.Tags).Scan(&postid)
return postid, err
}

为了阅读最新的帖子,我写了一个小函数:

func getLatestPosts(page int) (*[]Post, error) {
const query = `SELECT id, title, body, tags FROM posts ORDER BY id DESC LIMIT 10`
var items []Post
db := GetDB()
rows, err := db.Query(query)
if err != nil {
return nil, err
}

for rows.Next() {
var item Post
if err := rows.Scan(&item.Id, &item.Title, &item.Body, &item.Tags); err != nil {
log.Fatal(err)
}
items = append(items, item)
}
return &items, err
}

这也有效,直到遇到标签列为空的帖子行,此时我收到以下错误:

2015/04/16 21:53:04 sql: Scan error on column index 4: unsupported driver -> Scan pair: -> *json.RawMessage

我的问题是,在扫描结果集时处理 nullable json 列的正确方法是什么?此错误是否与 lib/pq 相关?

我的模式是:

CREATE TABLE post (
"id" int4 NOT NULL DEFAULT nextval('post_id_seq'::regclass),
"title" varchar(255) NOT NULL COLLATE "default",
"body" text COLLATE "default",
"tags" json,
PRIMARY KEY ("id") NOT DEFERRABLE INITIALLY IMMEDIATE
);

这是一个已经存在的(非空)tags 字段内容:

 {
"black-and-white" : "Black and White",
"the-godfather" : "The Godfather"
}

有什么想法吗?

最佳答案

TL;DR:将您的结构更改为具有 Tags *json.RawMessage 或使用该类型的临时变量。

注意你可以search the Go source对于错误消息,如果您有兴趣,可以更好地了解幕后发生的事情(标准包大多是编写良好的 Go 代码的良好来源)。

我使用下表对新的 PostgreSQL-9.4.1 服务器进行了测试:

CREATE TABLE post (
"id" serial PRIMARY KEY,
"title" varchar(255) NOT NULL,
"body" text,
"tags" json
);

(顺便说一句,最好给出重新创建的命令,或者用于创建表的位置,而不是使用不能直接使用的形式。另外,当我熟悉 PostgreSQL 时我记得很少有 varchar 列不是错误的,而不仅仅是使用 text,可能有长度限制。)

将该表与我得到的结构类型一起使用:

converting Exec argument #2's type: unsupported type json.RawMessage, a slice

在插页上。更改为 []byte(p.Tags) 使它消失(但请参见下文),然后查询按原样进行。

当我将 NULL 值放入表中时,我只遇到了与查询时相同的错误。解决方案是将结构字段更改为 Tags *json.RawMessage。然后我可以删除我在插入时添加的转换,并且查询工作正常,将字段设置为 nil 或不适当。

如果这样做,请不要忘记在使用前检查 item.Tags 是否为 nil。或者,使数据库字段 NOT NULL

我不太熟悉 Go 的数据库支持,不知道需要一个指向 slice 的指针来处理 NULL 是否合理;我本来希望不会,因为 Go 已经区分了空 slice 和 nil slice 。

或者,您可以保留您的类型并使用这样的临时类型:

    var item post
var tmp *json.RawMessage
if err := rows.Scan(&item.Id, &item.Title, &item.Body, &tmp); err != nil {
log.Fatal(err)
}
if tmp != nil {
item.Tags = *tmp
}

当您使用 NULL 正文进行测试时,您可能会遇到类似的问题。使数据库列 NOT NULL 或使用 sql.NullString,在您的类型中或作为上面的临时列(使用 Valid 字段NullString 以查看是否应复制该字符串)。


一些其他的小注意事项:

  • golint 建议使用 ID 而不是 Id
  • 您没有提供您的GetDB 实现,我希望它只是获得共享/全局*sql.DB。您不想重复调用 sql.Open
  • 在您的两个函数中,您都可以使用 pre-prepared语句(在这些函数之外创建一次)。如果您经常调用这些函数,这可能会有所帮助。
  • 您的查询尝试使用“posts”表/ View 而不是“post”;我在剪切粘贴问题时猜错了?
  • 您的getLatestPosts 函数返回*[]Post;不要那样做。只需返回 []Post。您几乎不想使用指向 slice 的指针,当然也不想将其用作返回类型。

关于sql - 如何避免可空 JSON 列上的​​扫描对 : <nil> *json. RawMessage 错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29706727/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com