doumi1944 2019-07-31 14:25
浏览 54
已采纳

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

I have a data structure in 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"`
}

that I need to transform to:

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"`
}

I get:

 panic: runtime error: index out of range

Here is my method but it is failing on the first line of loop:

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
}

Basically, data originally comes grouped by IDPrm, and I need to group it by timestamp.

How should I do that ? Is there any helpers that could help doing it ?

  • 写回答

2条回答 默认 最新

  • doucheng1063 2019-07-31 16:12
    关注

    The problem

    The reason is simple:

    var dataGrouped DataGroupedByTS
    

    initializes the fields of dataGrouped to the so-called zero value for the type DataGroupedByTS.

    The zero value of any compound type T consists of the zero-values for types corresponding to each of the fields of T.

    So, for

    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"`
    }
    

    the zero value would be

    type DataGroupedByTS struct {
        CodeConv: "",
        Start:    time.Time(0),
        End:      time.Time(0),
        Details:  nil,           // watch this!
    }
    

    That's because the type of Details is []struct{ ... }, that is, a slice of some structs, and the zero-value of any slice is nil.

    You then go on and attempt to write at some index into a non-existing slice (well, the slice without any backing array allocated to hold its data). This reasonably fails with "panic: runtime error: index out of range": an unallocated slice has zero elements, so there is no element at index 0, and there is nothing to assign to.

    The fix

    Two ways:

    1. Preallocate the destination slice:

          var dataGrouped DataGroupedByTS
          // ...
          dataGrouped.Details = make([]struct{...}, len(apiMain.Details))
          for _, detail := range apiMain.Details {
          // ...
      
    2. Append to a slice, rather than updating its elements in place:

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

      It's OK to append to a nil slice.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器