实现Scan接口,将JSON数组读入到map中。

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

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."

huangapple
  • 本文由 发表于 2017年6月2日 15:22:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/44323087.html
匿名

发表评论

匿名网友

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

确定