Go 编组空映射[string]接口{}会导致;空";而不是零

Go 编组空映射[string]接口{}会导致;空";而不是零,go,Go,我有一个问题,如果我尝试执行以下操作,Go会将“null”插入到PostgreSQL数据库的jsonb列中,并且structs属性(在这种情况下是map[string]interface{}类型)为空: accessMembers, _ := json.Marshal(c.AccessMembers) 执行测试打印时,输出的值与存储到数据库中的值相同: fmt.Println(string(accessMembers)) // equals the string "null" 问题是我需要它

我有一个问题,如果我尝试执行以下操作,Go会将“null”插入到PostgreSQL数据库的jsonb列中,并且structs属性(在这种情况下是map[string]interface{}类型)为空:

accessMembers, _ := json.Marshal(c.AccessMembers)
执行测试打印时,输出的值与存储到数据库中的值相同:

fmt.Println(string(accessMembers)) // equals the string "null"
问题是我需要它是-nil(不是字符串,而是Golang nil),所以当我在下面的Exec函数中使用它时:

sqlStr := `UPDATE my_table SET access_members=$1 WHERE id=$2;`

_, err := db.Exec(sqlStr, accessMembers, c.Id)
它应该与doing:

_, err := db.Exec(sqlStr, nil, c.Id)
var accessMembers interface{} = nil

if c.AccessMembers != nil {
    j, _ := json.Marshal(c.AccessMembers)
    accessMembers = j
}
我尝试了很多不同的解决办法,我认为这些办法必须奏效,但没有奏效

例如

这将导致以下错误:“pq:json类型的输入语法无效”

我不明白为什么这与在Exec functions参数中显式写入nil不同,因为[]字节显然必须是nil,对吗

我做错了什么?以下是我希望它能起作用的方式:

回答:

_, err := db.Exec(sqlStr, nil, c.Id)
var accessMembers interface{} = nil

if c.AccessMembers != nil {
    j, _ := json.Marshal(c.AccessMembers)
    accessMembers = j
}
感谢thwd提供了基本的解决方案,并指出了数据库驱动程序如何以不同的方式封送nil,建议使用接口{}而不是[]字节


感谢DonSeba提醒我在使用资源封送、字符串转换和比较之前检查struct字段是否存在,这应该更昂贵。

您还没有初始化
AccessMembers

在决定封送该值之前,应检查该值是否存在

if c.AccessMembers == nil {
    c.AccessMembers = make(map[string]interface{})
}
如果您执行上述操作,则结果如下:

accessMembers, err := json.Marshal(c.AccessMembers)
将是一个有效的空json值
{}
,用于存储到数据库中并在以后检索该值

更新:

这里对“NULL”值进行了一些讨论:

我不明白为什么这与在Exec functions参数中显式写入nil不同,因为[]字节显然必须是nil,对吗

nil
有一个类型。对于类型
map[string]interface{}
[]byte
的数据库驱动程序封送
nil
的方式不同于
interface{}
(这是
db.Exec
的第二个参数的类型)。您应该能够做到:

var i interface{} = nil

j, _ := json.Marshal(c.AccessMembers)

if string(j) != "null" {
     i = j
}

sqlStr := `UPDATE content SET access_members=$1 WHERE id=$2;`

_, err := db.Exec(sqlStr, i, c.Id)

谢谢你的建议。它确实解决了错误,但插入的值仍然是我的jsonb列中的空映射“{}”,在这里,我需要将映射封送为NULL,就像我在Exec函数中直接输入-nil-作为参数一样。我已经阅读了该链接,但在我看来,该线程中没有真正的解决方案:/json.Marshal()无法“查看|访问”c.AccessMembers,它按其工作方式返回“NULL”。。。