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条)

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改