使用Golang如何计算结构体类型接口{}中的元素数量?

8

我是一个刚接触Go语言的新手,但我一直在努力学习。

我正在尝试编写一些逻辑,需要检查结构体属性是否仅由一个元素组成,或者第一个元素是否仅有一个子元素。

主要结构体如下:

type ChartOptins struct {
    Filters Filter `json:"filters"`
    Charts interface{} `json:"charts"`
}

图表是由以下这样的结构数组组成的:

    $filters = array(
        "filters" => array(
            "DayStart" => "12-01-2015",
            "DayEnd" => "12-05-2015",
            "TimePeriods"=> array(
                array("qqq","www"),
            ),
            "lines" => array(
                "first","avokado","drunduki"
            )

        ),
        "charts" => array(
            "noagg" => array(
                array(
                    "name" => "HOLD",
                    "type" => "line"
                ),
                array(
                    "name" => "UKKR",
                    "type" => "line"
                ),
                array(
                    "name" => "SVO",
                    "type" => "line"
                ),
            ),
            "oracle" => array(
                array(
                    "name" => "TDD",
                    "type" => "line"
                ),
            ) 
        ),
    );

在 `ChartOptions` 结构体中,我解析了 POST 请求中的 JSON 数据。JSON 数据如下:
{ "filters": { "dayStart": "11-10-2015", "dayEnd": "21-10-2015", "timePeriods": [ [ "qqq", "www" ] ], "lines": [ "first", "avokado", "drunduki" ] }, "charts": { "noagg": [ { "name": "HOLD", "type": "line" } ] } }

所以,图表只能有一个来源和一个元素,或者在任意数量的来源中具有任意数量的元素。
"charts" : { "noagg": [ { "name": "HOLD", "type": "line" } ] }
or
"charts" : { "noagg": [ { "name": "HOLD", "type": "line" } , { "name": "TDD", "type": "line" } , { "name": "SVO", "type": "line" } ] }

当然,这是传递到go脚本的JSON元素,并且我将它们解析为interface{}。当我尝试使用len()时,Go说我不能在interface上使用它。

如何最好地处理元素数量,以及实现这样的检查的最佳方法是什么?


尝试使用reflect包。 - sfault
你能给一些例子吗? - Altenrion
不要将其解析为 interface{}(如果您是 Go 的新手,则根本不应使用它),而是解析为某个适当的结构体,其中包含一个 noagg 切片,并对该切片执行 len 操作。 - Volker
我也会尝试使用切片来完成这个任务,但是为此需要声明每个切片的结构类型直到树的底部... - Altenrion
2个回答

7
这里有一个保持接口的示例: https://play.golang.org/p/Eu6Hj6ddSE 只需将 Charts interface{} 更改为 Charts []interface{} 如果 v 是您的 ChartOptins,则使用 .() 运算符在接口上获取 len。
fmt.Println(len(v.Charts.([]interface{})))

3

据我理解,您只需要定义结构以正确映射JSON。可以像这样:

package main

import (
    "encoding/json"
    "fmt"
    "strings"
)

type ChartOptins struct {
    Filters map[string]interface{} `json:"filters"`
    Charts  map[string][]Chart     `json:"charts"`
}

type Chart struct {
    Name string `json:"name"`
    Type string `json:"type"`
}

func main() {
    const jsonStream = `{
        "filters": { "dayStart": "oneortwo", "dayEnd": "oneorthree", "timePeriods": [ [ "qqq", "www" ] ], "lines": [ "first", "avokado", "drunduki" ] }, 
        "charts": { "noagg": [ { "name": "HOLD", "type": "line" }, { "name": "UKKR", "type": "line" }, { "name": "SVO", "type": "line" } ], "oracle": [ { "name": "TDD", "type": "line" } ] } 
    }`

    var co ChartOptins
    json.NewDecoder(strings.NewReader(jsonStream)).Decode(&co)

    fmt.Println(co)

    for k, v := range co.Charts {
        fmt.Printf("key: %v\n", k)
        for _, ch := range v {
            fmt.Printf("Name: %v, type: %v\n", ch.Name, ch.Type)
        }
    }
}

我需要源名称是动态的,这就是为什么我使用接口的原因。我发现可以使用map[string]Charts,但现在我遇到了无法将数组解析到我的新结构体中的错误。“source”的名称可以是x、y、...、n,并且在同一时刻可能会有多个源。 - Altenrion
我知道这个结构。但是我无法发送额外的“名称”属性。我将在问题中写出主数组的结构。已更新问题正文。 - Altenrion
它可以是列表中的一项,但列表是动态的。我的意思是现在只有3个源元素。但以后可能会有10个或更多的数据源,用于图表。 - Altenrion
我编写了整个测试数组,它以JSON格式从POST传递到Go应用程序中..在我的问题正文中。 - Altenrion
我收到了错误信息:JSON 解码错误:json:无法将对象解组为类型为字符串的 Go 值这是我的 JSON:{ "filters": { "dayStart": "oneortwo", "dayEnd": "oneorthree", "timePeriods": [ [ "qqq", "www" ] ], "lines": [ "first", "avokado", "drunduki" ] }, "charts": { "noagg": [ { "name": "HOLD", "type": "line" }, { "name": "UKKR", "type": "line" }, { "name": "SVO", "type": "line" } ], "oracle": [ { "name": "TDD", "type": "line" } ] } } 或许这样更容易理解? - Altenrion
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接