为了账号安全,请及时绑定邮箱和手机立即绑定

go 中转换数据结构:panic: 运行时错误:索引超出范围

go 中转换数据结构:panic: 运行时错误:索引超出范围

Go
吃鸡游戏 2023-07-10 14:27:11
我在 go 中有一个数据结构:type APIMain struct {    CodeConv string    `json:"codeConv"`    Start    time.Time `json:"start"`    End      time.Time `json:"end"`    Details  []struct {        IDPrm string `json:"idPrm"`        Keys  []struct {            Timestamp time.Time `json:"timestamp"`            Value     float64   `json:"value"`        } `json:"keys"`    } `json:"details"`}我需要将其转换为:type DataGroupedByTS struct {    CodeConv string    `json:"codeConv"`    Start    time.Time `json:"start"`    End      time.Time `json:"end"`    Details  []struct {        Timestamp time.Time `json:"timestamp"`        Keys      []struct {            IDPrm string  `json:"idPrm"`            Value float64 `json:"value"`        } `json:"keys"`    } `json:"details"`}我得到: panic: runtime error: index out of range这是我的方法,但它在循环的第一行失败:func groupByTimestamp(apiMain datacheck.APIMain) DataGroupedByTS {    var dataGrouped DataGroupedByTS    dataGrouped.CodeConv = apiMain.CodeConv    dataGrouped.Start = apiMain.Start    dataGrouped.Start = apiMain.Start    dataGrouped.End = apiMain.End    var iDetail = 0    var iKey = 0    for _, detail := range apiMain.Details {        for _, key := range detail.Keys {            dataGrouped.Details[iDetail].Timestamp = key.Timestamp  // <-- failing here            dataGrouped.Details[iDetail].Keys[iKey].IDPrm = detail.IDPrm            dataGrouped.Details[iDetail].Keys[iKey].Value = key.Value            iKey++        }        iDetail++    }    return dataGrouped}基本上,数据最初按 分组IDPrm,我需要按时间戳对其进行分组。我该怎么做呢?有没有帮手可以帮忙做这件事?
查看完整描述

2 回答

?
MM们

TA贡献1886条经验 获得超2个赞

问题

原因很简单:


var dataGrouped DataGroupedByTS

将 的字段初始化dataGrouped为类型 的所谓零值DataGroupedByTS。


任何复合类型的零值T都由与 的每个字段对应的类型的零值组成T。


因此对于


type DataGroupedByTS struct {

    CodeConv string    `json:"codeConv"`

    Start    time.Time `json:"start"`

    End      time.Time `json:"end"`

    Details  []struct {

        Timestamp time.Time `json:"timestamp"`

        Keys      []struct {

            IDPrm string  `json:"idPrm"`

            Value float64 `json:"value"`

        } `json:"keys"`

    } `json:"details"`

}

零值是


type DataGroupedByTS struct {

    CodeConv: "",

    Start:    time.Time(0),

    End:      time.Time(0),

    Details:  nil,           // watch this!

}

这是因为 的类型Details是[]struct{ ... },即某些结构体的切片,并且任何切片的零值都是nil。


然后,您继续尝试在某个索引处写入不存在的切片(好吧,该切片没有分配任何后备数组来保存其数据)。这会合理地失败,并出现“恐慌:运行时错误:索引超出范围”:未分配的切片有零个元素,因此索引 0 处没有元素,并且没有任何可分配的内容。


修复

两种方式:


预分配目标切片:


    var dataGrouped DataGroupedByTS

    // ...

    dataGrouped.Details = make([]struct{...}, len(apiMain.Details))

    for _, detail := range apiMain.Details {

    // ...

追加到切片,而不是就地更新其元素:


    var dataGrouped DataGroupedByTS

    // ...

    for _, detail := range apiMain.Details {

        dataGrouped.Details = append(dataGrouped.Details, detail)

        // ...

append切片就可以了nil。



查看完整回答
反对 回复 2023-07-10
?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

我的两分钱:请问该对象是否为空,因为恐慌错误明确表示“索引超出范围”,并检查 for 循环中的下边界和上边界。



查看完整回答
反对 回复 2023-07-10
  • 2 回答
  • 0 关注
  • 144 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信