Go 语言转换 JSON 结构时出现切片索引越界(index out of range)报错
报错核心原因
触发index out of range [0] with length 0的逻辑链路非常明确:
- 循环赋值时直接通过索引访问新版结构体的
Labels切片,但该切片是结构体零值,初始长度为0,没有可索引的实体元素。第一次取索引[0]时,自然会触发长度越界。 - 原逻辑默认新版切片已经预分配了和旧版数组等长的元素,但实际上Go中值类型结构体虽然会自动初始化嵌套的结构体字段,对应的切片字段依然是长度为0的空切片,不存在可供索引的位置。
- 附带的配置错误:定义
Labels元素的Value字段时,json标签漏了双引号,写的json:value无法被标准json包正确识别,后续序列化的字段名会不符合预期。
具体修复步骤
- 替换原有的硬索引赋值逻辑:不直接通过索引往空切片写值,而是根据旧版Niveau数组的实际长度,动态构造对应长度的
Labels切片,再赋值给新版结构体的对应字段。 - 把原有的
nil判断替换成更稳妥的长度判断len(xxx) > 0,避免长度为0但非nil的切片进入无效逻辑。 - 修正结构体字段的json标签格式,给标签值加上双引号。
- 把重复定义的匿名Label结构体抽成独立类型,减少重复代码、降低出错概率。
修改后的可运行代码
// 抽离重复定义的标签结构体 type LabelItem struct { Value string `json:"value"` } type AnnotV1 struct { Uuid string `json:"uuid"` Data struct { Niveau1 []string `json:"Niveau1"` Niveau2 []string `json:"Niveau2"` Niveau3 []string `json:"Niveau3"` } `json:"data"` User string `json:"user"` } type AnnotV2 struct { Uuid string `json:"uuid"` Annotation struct { Classif struct { Niveau1 struct { Labels []LabelItem `json:"labels"` } `json:"Niveau1"` Niveau2 struct { Labels []LabelItem `json:"labels"` } `json:"Niveau2"` Niveau3 struct { Labels []LabelItem `json:"labels"` } `json:"Niveau3"` } `json:"classifications"` } `json:"annotation"` User string `json:"user"` } func convert(oldAnnots []AnnotV1) (newAnnots []AnnotV2) { for _, element := range oldAnnots { var newAnnot AnnotV2 newAnnot.User = element.User newAnnot.Uuid = element.Uuid // Niveau1赋值逻辑 if len(element.Data.Niveau1) > 0 { labels := make([]LabelItem, 0, len(element.Data.Niveau1)) for _, annotVal := range element.Data.Niveau1 { labels = append(labels, LabelItem{Value: annotVal}) } newAnnot.Annotation.Classif.Niveau1.Labels = labels } // Niveau2赋值逻辑 if len(element.Data.Niveau2) > 0 { labels := make([]LabelItem, 0, len(element.Data.Niveau2)) for _, annotVal := range element.Data.Niveau2 { labels = append(labels, LabelItem{Value: annotVal}) } newAnnot.Annotation.Classif.Niveau2.Labels = labels } // Niveau3赋值逻辑 if len(element.Data.Niveau3) > 0 { labels := make([]LabelItem, 0, len(element.Data.Niveau3)) for _, annotVal := range element.Data.Niveau3 { labels = append(labels, LabelItem{Value: annotVal}) } newAnnot.Annotation.Classif.Niveau3.Labels = labels } newAnnots = append(newAnnots, newAnnot) } return }
额外注意:你提供的新版JSON示例存在层级缩进问题——示例中
Niveau3被嵌在了Niveau2的字段内部,但你定义的结构体中三个Niveau字段是平级放在classifications下的,需要根据实际的新版JSON结构调整嵌套层级,避免后续json序列化/反序列化匹配不上字段。
内容的提问来源于stack exchange,提问作者Oscar
相关产品推荐
相关产品推荐

