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

我在 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,我需要按时间戳对其进行分组。


我该怎么做呢?有没有帮手可以帮忙做这件事?


吃鸡游戏
浏览 147回答 2
2回答

MM们

问题原因很简单:var dataGrouped DataGroupedByTS将 的字段初始化dataGrouped为类型 的所谓零值DataGroupedByTS。任何复合类型的零值T都由与 的每个字段对应的类型的零值组成T。因此对于type DataGroupedByTS struct {&nbsp; &nbsp; CodeConv string&nbsp; &nbsp; `json:"codeConv"`&nbsp; &nbsp; Start&nbsp; &nbsp; time.Time `json:"start"`&nbsp; &nbsp; End&nbsp; &nbsp; &nbsp; time.Time `json:"end"`&nbsp; &nbsp; Details&nbsp; []struct {&nbsp; &nbsp; &nbsp; &nbsp; Timestamp time.Time `json:"timestamp"`&nbsp; &nbsp; &nbsp; &nbsp; Keys&nbsp; &nbsp; &nbsp; []struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IDPrm string&nbsp; `json:"idPrm"`&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Value float64 `json:"value"`&nbsp; &nbsp; &nbsp; &nbsp; } `json:"keys"`&nbsp; &nbsp; } `json:"details"`}零值是type DataGroupedByTS struct {&nbsp; &nbsp; CodeConv: "",&nbsp; &nbsp; Start:&nbsp; &nbsp; time.Time(0),&nbsp; &nbsp; End:&nbsp; &nbsp; &nbsp; time.Time(0),&nbsp; &nbsp; Details:&nbsp; nil,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// watch this!}这是因为 的类型Details是[]struct{ ... },即某些结构体的切片,并且任何切片的零值都是nil。然后,您继续尝试在某个索引处写入不存在的切片(好吧,该切片没有分配任何后备数组来保存其数据)。这会合理地失败,并出现“恐慌:运行时错误:索引超出范围”:未分配的切片有零个元素,因此索引 0 处没有元素,并且没有任何可分配的内容。修复两种方式:预分配目标切片:&nbsp; &nbsp; var dataGrouped DataGroupedByTS&nbsp; &nbsp; // ...&nbsp; &nbsp; dataGrouped.Details = make([]struct{...}, len(apiMain.Details))&nbsp; &nbsp; for _, detail := range apiMain.Details {&nbsp; &nbsp; // ...追加到切片,而不是就地更新其元素:&nbsp; &nbsp; var dataGrouped DataGroupedByTS&nbsp; &nbsp; // ...&nbsp; &nbsp; for _, detail := range apiMain.Details {&nbsp; &nbsp; &nbsp; &nbsp; dataGrouped.Details = append(dataGrouped.Details, detail)&nbsp; &nbsp; &nbsp; &nbsp; // ...append切片就可以了nil。

宝慕林4294392

我的两分钱:请问该对象是否为空,因为恐慌错误明确表示“索引超出范围”,并检查 for 循环中的下边界和上边界。
打开App,查看更多内容
随时随地看视频慕课网APP