drutcs7210 2013-05-15 03:05
浏览 22

键入递归golang函数调用

I am working on adding 'array wildcards' to a Go project on Github called jsonget. Here's an example of what I mean by array wildcards:

 > echo "[{product:'coffee', price:2.10}, {product:'beer', price:3.80}]" | jsonget '*.price'

[2.10, 3.80]

The code for my branch is here

The problem I am running into is with typing, when GetValue encounters a * character, it recurses, calling GetValue on the subexpression, but the type always comes back as a string.

For example, in the test file, I give it this piece of json:

    {
      "inventory": [
          {"name": "mountain bike", "price": 251.0},
          {"name": "red wagon", "price": 90.10},
          {"name": "kinesis advantage", "price": 300.0},
          {"name": "a ticket to Mars", "price": 1200000000.0}
      ]
    }

Then query out inventory[*].price, expecting [251,90.1,300,1.2e+09], but instead getting ["251","90.1","300","1.2e+09"].

I would like to avoid using reflection here, but I don't see another way to do this.

  • 写回答

1条回答 默认 最新

  • dsxrq28228 2013-05-15 12:25
    关注

    I apologise if i've misunderstood your question, but hopefully this helps.

    I think that you're either going to have to use reflection or a type switch (http://golang.org/doc/effective_go.html#type_switch , which probably uses reflection behind the scenes, not sure on that).

    It shouldn't be too hard to modify your existing valueToString function to include a type switch. Possibly rename it to convertValue or something more generic, and put a type switch in it. If the value is an int, return an int, else return a string.

    For example:

    func convertValue(value interface{}) (text string, i int, err error) { // Was valueToString
        if value == nil && *printNulls == false {
            return "", nil, nil
        }
    
        textBytes, err := json.Marshal(value)
        if err != nil {
            return "", nil, err
        }
        switch value := value.(type) {
        default:
            text = string(textBytes)
            text = quotedString.ReplaceAllString(text, "$1")
            return text, nil, nil
        case int:
            i = textBytes
            return nil, i, nil
        }
    }
    

    That will hopefully string() everything except the values that the type switch detects as ints, which will be returned as they are.

    There's probably a cleaner way of doing it, but it would almost certainly involve a large code refactor. The major downside is that now you need to check if a value is nil before using it.

    I'm not sure if there's a way to make a single function able to return one value of various types as I'm pretty sure it would play havoc with type safety. If it is possible, I can only imagine doing it by returning an empty interface in the function definition. Sounds messy.

    EDIT: Check out Andrew Gerrand's blog post http://blog.golang.org/2011/01/json-and-go.html , especially the bit near the bottom about decoding generic data. It should help.

    评论

报告相同问题?

悬赏问题

  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line