英文:
Implement Scan interface to read json array into map
问题
我正在从PostgreSQL中获取一个JSON数组,并希望将其读入一个map中。我能够将值解组为[]string
切片,但实际上我想要的是一个map[string]bool
。
我为该列编写了一个自定义类型,具有一个Scan接口,该接口首先将JSON数组转换为字符串切片,然后将每个字符串读入自定义的map类型作为键。
type custMap map[string]bool
func (m *custMap) Scan(src interface{}) error {
b, ok := src.([]byte)
if !ok {
return error(errors.New("Error Scanning Array"))
}
s := make([]string, 0)
json.Unmarshal(b, &s)
for _, v := range s {
(*m)[v] = true
}
return nil
}
type data struct {
vals custMap `json:"vals"`
}
我尝试扫描的查询返回一个具有名为vals的列的行,该列是一个JSON数组:["some", "arr", "vals"]
,其中自定义类型的使用方式如下:
var d models.data
sqlDB.QueryRow().Scan(&d.vals)
我期望的输出是一个具有以下结构的结构体:
{ vals: map[string]bool { "some": true, "arr": true, "vals": true } }
这段代码可以编译通过,但是运行时会出现"assignment to entry in nil map"的恐慌错误。
如何修复我的Scan函数?使用map类型是否可能实现这个目标?
英文:
I am fetching a JSON array from PostgreSQL, and I would like to read it into a map. I am able to Unmarshal the values into a []string
slice, but what I actually want is a map[string]bool
.
I've written a custom type for the column with a Scan interface that converts the JSON array into a slice of strings first, then reads each string into the custom map type as keys.
type custMap map[string]bool
func (m *custMap) Scan(src interface{}) error {
b, ok := src.([]byte)
if !ok {
return error(errors.New("Error Scanning Array"))
}
s := make([]string, 0)
json.Unmarshal(b, &s)
for _, v := range s {
(*m)[v] = true
}
return nil
}
type data struct {
vals custMap `json: "vals"`
}
The query I am trying to scan returns a row with a column vals which is a JSON array: ["some", "arr", "vals"]
, where the custom type is used like so:
var d models.data
sqlDB.QueryRow().Scan(&d.vals)
My expected output is a struct with the following shape
{ vals: map[string]bool { "some": true, "arr": true, "vals": true }
This compiles fine, but my code panics with "assignment to entry in nil map"
How can I fix my Scan function? Is it even possible to do this with a map type?
答案1
得分: 2
你正在调用未初始化的映射类型*custMap
上的Scan
方法。请使用以下方式之一初始化d.vals
:
d.vals = custMap{}
或者
d.vals = make(custMap)
其他答案已经提供了解释。
英文:
You are calling your method Scan
of type *custMap
on a unitialised map. Initialize d.vals
either like
d.vals = custMap{}
or
d.vals = make(custMap)
Other answers already provide an explanation.
答案2
得分: 1
《Go编程语言规范》
映射类型
映射是一组无序的元素,其中元素类型称为元素类型,由另一种类型称为键类型的一组唯一键索引。未初始化的映射的值为nil。
使用内置函数make创建一个新的空映射值,该函数接受映射类型和可选的容量提示作为参数:
make(map[string]int)
make(map[string]int, 100)
初始容量不限制其大小:映射会根据存储在其中的项目数量进行扩展,除了nil映射。nil映射等同于空映射,只是不能添加元素。
我没有看到使用make
来初始化你的映射:"一个nil
映射等同于一个空映射,只是不能添加元素。"
英文:
> The Go Programming Language Specification
>
> Map types
>
> A map is an unordered group of elements of one type, called the
> element type, indexed by a set of unique keys of another type, called
> the key type. The value of an uninitialized map is nil.
>
> A new, empty map value is made using the built-in function make, which
> takes the map type and an optional capacity hint as arguments:
>
> make(map[string]int)
> make(map[string]int, 100)
>
> The initial capacity does not bound its size: maps grow to accommodate
> the number of items stored in them, with the exception of nil maps. A
> nil map is equivalent to an empty map except that no elements may be
> added.
I don't see a make
to initialize your map: "A nil
map is equivalent to an empty map except that no elements may be added."
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论