我在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没有元素,也没有任何分配给。
。修复
两种方式:
在目标切片中进行预先分配:
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
切片。
我的两分钱:您能否请对象是否为无效用于循环。