Getting invalid operation: mymap["title"] (type interface {} does not support indexing) when trying to index a map

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

Getting invalid operation: mymap["title"] (type interface {} does not support indexing) when trying to index a map

问题

我有一个存储在map中的数据,并且我想通过键索引到map中获取值。

mdi, err := page.Metadata()
fmt.Println(mdi["title"])

然而,我一直收到错误消息invalid operation: mdi["title"] (type interface {} does not support indexing)。我感到困惑,因为数据是一个map,我应该能够通过索引来获取值。为了确保类型清楚,我还尝试将值转换为字符串:

title, ok := mdi["title"].(string)
checkOk(ok)
fmt.Println(title)

然而,我得到了相同的错误消息。我做错了什么?

英文:

I have data that's in a map, and I want to index into the map by key to get a value.

mdi, err := page.Metadata()
fmt.Println(mdi["title"])

However I keep getting the error message invalid operation: mdi["title"] (type interface {} does not support indexing). I am confused, because the data is a map and I should be able to index into it to get the value. In case the type wasn't clear, I also tried to cast the value to a string:

title, ok := mdi["title"].(string)
checkOk(ok)
fmt.Println(title)

However, I got the same error message. What am I doing wrong?

答案1

得分: 100

这里的数据类型是关键。mdi实际上不是一个映射,而是一个interface{},它可以是任何类型 - 映射、字符串、整数。你需要首先将其断言为具有预期键/值类型的映射,或者按照JSON和Go中概述的笨拙的case开关进行操作。

mdi, err := page.Metadata()
md, ok := mdi.(map[string]interface{})
fmt.Println(md["title"])
英文:

The data type here was the key. mdi was not actually a map, but an interface{}, which could be anything - a map, a string, an int. You need to assert it to a map with expected key/value types first, or do the awkward case switch outlined in JSON and Go.

mdi, err := page.Metadata()
md, ok := mdi.(map[string]interface{})
fmt.Println(md["title"])

答案2

得分: 0

我不确定你是否能控制page.Metadata的行为,但如果可以的话,这种情况下有更好的方法。假设你的代码如下所示:

package main

import (
   "encoding/json"
   "log"
)

func Metadata() (interface{}, error) {
   y := []byte(`{"metadata": {"title": "Stack Overflow"}}`)
   var m map[string]interface{}
   e := json.Unmarshal(y, &m)
   if e != nil {
      return nil, e
   }
   return m["metadata"], nil
}

func main() {
   m, e := Metadata()
   if e != nil {
      log.Fatal(e)
   }
   s := m["title"]
   println(s == "Stack Overflow")
}

你会得到与你之前遇到的相同错误。但你可以将其改为以下形式:

type Map map[string]interface{}

func (m Map) M(s string) Map {
   return m[s].(map[string]interface{})
}

func (m Map) S(s string) string {
   return m[s].(string)
}

func Metadata() (Map, error) {
   y := []byte(`{"metadata": {"title": "Stack Overflow"}}`)
   var m Map
   e := json.Unmarshal(y, &m)
   if e != nil {
      return nil, e
   }
   return m.M("metadata"), nil
}

func main() {
   m, e := Metadata()
   if e != nil {
      log.Fatal(e)
   }
   s := m.S("title")
   println(s == "Stack Overflow")
}

然后,每当你需要索引时,只需根据你想要返回的内容调用相应的方法。如果需要返回[]interface{}类型的切片,你也可以添加Slice方法,并根据需要添加其他方法,例如返回整数。最后,如果你想检查Map是否包含某个键,可以这样做:

if m["title"] != nil {
   s := m.S("title")
   println(s == "Stack Overflow")
}
英文:

I'm not sure if you have control over what page.Metadata does, but if you do, a better way is available for this situation. Say your code looks like this:

package main

import (
   "encoding/json"
   "log"
)

func Metadata() (interface{}, error) {
   y := []byte(`{"metadata": {"title": "Stack Overflow"}}`)
   var m map[string]interface{}
   e := json.Unmarshal(y, &m)
   if e != nil {
      return nil, e
   }
   return m["metadata"], nil
}

func main() {
   m, e := Metadata()
   if e != nil {
      log.Fatal(e)
   }
   s := m["title"]
   println(s == "Stack Overflow")
}

You'd get the same error you got. But you can change it to this:

type Map map[string]interface{}

func (m Map) M(s string) Map {
   return m
展开收缩
.(map[string]interface{}) } func (m Map) S(s string) string { return m
展开收缩
.(string) } func Metadata() (Map, error) { y := []byte(`{"metadata": {"title": "Stack Overflow"}}`) var m Map e := json.Unmarshal(y, &m) if e != nil { return nil, e } return m.M("metadata"), nil } func main() { m, e := Metadata() if e != nil { log.Fatal(e) } s := m.S("title") println(s == "Stack Overflow") }

Then whenever you need to index, you just call the appropriate method depending on what you are wanting to return. You can also add Slice if need be []interface{}, and further methods from what I put, for example if you need to return integer. Finally, if you want to check if Map contains key, you can do this:

if m["title"] != nil {
   s := m.S("title")
   println(s == "Stack Overflow")
}

huangapple
  • 本文由 发表于 2014年8月9日 08:23:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/25214036.html
匿名

发表评论

匿名网友

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

确定