在GO中转换数据结构:恐慌:运行时错误:索引不在范围内



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

我应该怎么做?有没有可以帮助这样做的帮助者?

问题

原因很简单:

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

您然后继续尝试将一些索引写入不存在的切片(嗯,切片,而没有任何分配的备用阵列以持有其数据(。这与"恐慌:运行时错误:索引范围内"合理失败:一个未分配的切片的元素为零,因此index 0没有元素,也没有任何分配给。

修复

两种方式:

  1. 在目标切片中进行预先分配:

        var dataGrouped DataGroupedByTS
        // ...
        dataGrouped.Details = make([]struct{...}, len(apiMain.Details))
        for _, detail := range apiMain.Details {
        // ...
    
  2. 附加在切片上,而不是更新其元素:

        var dataGrouped DataGroupedByTS
        // ...
        for _, detail := range apiMain.Details {
            dataGrouped.Details = append(dataGrouped.Details, detail)
            // ...
    

    可以使用appendnil切片。

我的两分钱:您能否请对象是否为无效用于循环。

最新更新