【问题标题】:convert interface{} directly to int in Golang, where interface stores a number as string在 Golang 中将 interface{} 直接转换为 int,其中 interface 将数字存储为字符串
【发布时间】:2018-03-30 06:50:24
【问题描述】:

我有一个 map[string]interface{} 因为解码为 JSON;对于普通数据,接口大多只是数字,但类型为字符串,如下所示:

var a interface{}
a="3"

然后所有的数据都会被存储到一个struct中。

type someStruct struct {
   ID string
   Number1 int
   Number2 int
   Number3 int
   Number4 int
}

所以我需要将 interface 转换为 int,但不能轻松有效地做到这一点,因为只有代码是 https://play.golang.org/p/oktbvTUbk93,如果你考虑到我应该处理所有可能的错误

我想直接将其转换为 int,我一直在寻找解决方案,但任何这种转换都可以按我的意愿工作https://play.golang.org/p/Dw67U6kZwHC

如果您想知道为什么我不直接将其解码为结构,因为它是动态数据,实际解码是这样发生的:

type dataIn struct {
   Code int         `json:"code"`
   ID   string      `json:"id"`
   Data interface{} `json:"data"`
}

然后我根据code和id来处理Data,都是不同的数据结构,所以不能直接用JSON处理

【问题讨论】:

  • 使用blank identifier 来使用值。例如,_, _ = ok, err
  • 如果问题空间很宽,您的代码也会很宽。这里没有魔法。做一些编程。
  • json 包可以将数字编码和解码为字符串:play.golang.org/p/MdrfqQjXLkw。如何处理不一致的字段,请参阅this question
  • @peterSO 如果我这样做,它将继续低效,因为会有一个变量分配,然后我可以将它存储到destine中
  • @Peter "如果你想知道为什么我不直接将它解码成结构,那是因为它是动态数据"

标签: json go go-interface


【解决方案1】:

创建一个帮助函数,在一个地方为您解析和验证:

func parseInt(i interface{}) (int, error) {
    s, ok := i.(string)
    if !ok {
        return 0, errors.New("not string")
    }
    return strconv.Atoi(s)
}

您可以在需要的地方使用它。这是一个完整的示例,其中我还使用了另一个帮助函数,它负责错误处理:

m := map[string]interface{}{
    "number1": "1",
    "number2": "2",
    "number3": "3",
    "number4": "4",
    "ID":      "asdsa",
    "Title":   "asdas",
}

getInt := func(key string) int {
    n, err := parseInt(m[key])
    if err != nil {
        panic(err) // Decide what you wanna do with error
    }
    return n
}

// converting to struct
data := element{
    ID:      m["ID"].(string),
    Title:   m["Title"].(string),
    Number1: getInt("number1"),
    Number2: getInt("number2"),
    Number3: getInt("number3"),
    Number4: getInt("number4"),
}

fmt.Printf("%+v\n", data)

上面的输出(在Go Playground上试试):

{ID:asdsa Title:asdas Number1:1 Number2:2 Number3:3 Number4:4}

还请注意,开源包github.com/icza/dyno 应该可以帮助您轻松处理动态对象。 (披露:我是作者。)例如它有一个dyno.GetInteger() 函数,它能够从多种类型(如整数、浮点数、字符串等)中提取int64 值。

【讨论】:

  • 您的解决方案非常简单,因为我尝试这样做。虽然这解决了实际问题,但有一个解决方案是为了不需要首先转换任何东西
【解决方案2】:

听起来你需要的是在你的主结构上自定义 unmarshal json 方法。首先,解组到您的主结构中以获取您的代码和 id,然后在 switch 语句中使用它们来确定用于其余数据的结构并解组到该结构中,在您的数据字段中搅拌该结构。

【讨论】:

  • 对于那种情况,我必须解组两次,我认为这是不可能的,请您添加一个示例
  • golang.org/pkg/encoding/json/#RawMessage 就是这种行为的一个很好的例子(看看解码例子)
  • 另外,这就是我所说的使用自定义解组方法的事情:play.golang.org/p/ZyKhnXQ-nFB
  • 我不知道我能做到这一点,而且自定义元帅似乎也是我需要的,因为使用 rawMessage 它会使我的代码更大,谢谢!
【解决方案3】:

我仍然没有得到你所说的结构是动态生成的部分。无论如何,您可以附加一个结构方法,它可以进行 int 转换。如果Data 类型为interface{} 的字段总是保存整数,你可以试试这个:

type DataIn struct {
  Code int         `json:"code"`
  ID   string      `json:"id"`
  Data interface{} `json:"data"`
}

func (s DataIn) toInt() int {
   switch t := s.Data.(type)
   case int:
     i, _ := strings.Atoi(fmt.Sprintf("%v",s.Data))
     return i
}

// using it
sampleData := someStruct{
  Number1: datain.toInt(),
}

【讨论】:

  • DataInt 不包含数字,它包含 map[string]interfarce{},其中接口内部是数字作为字符串
猜你喜欢
  • 2017-09-25
  • 2014-12-30
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-20
  • 1970-01-01
相关资源
最近更新 更多