使用Golang合并含相同uid的相似数据切片并生成JSON
嘿,这个场景在Go里处理起来其实挺清晰的,核心思路就是利用uid作为唯一标识,先把两个切片的数据聚合到一个map里做字段合并,再转回切片序列化就行。我给你一步步拆解:
步骤1:解析两个端点的响应到结构体切片
首先,既然两个端点都基于同一个Item结构体返回JSON,那我们可以直接用json.Unmarshal把它们的响应字节解析成[]Item类型:
// 先定义你的结构体(按你提供的补充完整) type NestedVal struct { // 这里根据你的实际嵌套字段定义,比如: ID string `json:"id"` } type Item struct { Uid string `json:"uid"` Val1 string `json:"param1,omitempty"` Val2 []NestedVal `json:"param2,omitempty"` Val5 int `json:"param5,omitempty"` Val6 string `json:"param6,omitempty"` } // 假设resp1是第一个端点返回的JSON字节,resp2是第二个端点的 var items1, items2 []Item // 解析第一个响应 if err := json.Unmarshal(resp1, &items1); err != nil { log.Fatalf("解析第一个端点响应失败: %v", err) } // 解析第二个响应 if err := json.Unmarshal(resp2, &items2); err != nil { log.Fatalf("解析第二个端点响应失败: %v", err) }
步骤2:用Map按UID合并数据
因为uid是唯一共同属性,我们可以创建一个map[string]Item,键是uid,值是合并后的Item。遍历两个切片,把非空的字段合并到对应的条目里:
// 初始化map存储合并后的Item itemMap := make(map[string]Item) // 先把第一个切片的所有元素存入map for _, item := range items1 { itemMap[item.Uid] = item } // 遍历第二个切片,合并字段到已有条目(或新增条目) for _, item := range items2 { existingItem, exists := itemMap[item.Uid] if !exists { // 如果这个uid在map里不存在,直接添加 itemMap[item.Uid] = item continue } // 开始合并字段:只覆盖/补充非空的字段 if item.Val1 != "" { existingItem.Val1 = item.Val1 } // 对于切片类型Val2:把新的元素追加到原有切片后面 existingItem.Val2 = append(existingItem.Val2, item.Val2...) // 注意:如果Val5业务上允许0作为有效值,这里的判断要调整(比如改成指针类型) if item.Val5 != 0 { existingItem.Val5 = item.Val5 } if item.Val6 != "" { existingItem.Val6 = item.Val6 } // 更新map里的合并后条目 itemMap[item.Uid] = existingItem }
步骤3:转切片并序列化为JSON
最后把map里的值转成切片,再用json.Marshal(或MarshalIndent美化输出)序列化成JSON:
// 把map的值转成切片 mergedItems := make([]Item, 0, len(itemMap)) for _, item := range itemMap { mergedItems = append(mergedItems, item) } // 序列化为JSON mergedJSON, err := json.MarshalIndent(mergedItems, "", " ") if err != nil { log.Fatalf("序列化合并后数据失败: %v", err) } // 输出结果,或者返回给调用方 fmt.Println(string(mergedJSON))
关键注意事项
- 字段合并规则:上面的逻辑是“用第二个切片的非空字段覆盖第一个的”,如果你的业务需要其他规则(比如保留第一个的非空字段、对冲突字段做特殊处理),直接修改合并字段的判断逻辑就行。
- 值类型的零值问题:比如
Val5是int类型,零值是0,如果你的业务场景中0是有效的值,那上面的item.Val5 != 0判断就会把有效的0当成“未设置”。这时候建议把Val5改成指针类型*int,这样就能通过nil来判断是否是未设置的状态。 - 嵌套字段合并:如果
NestedVal里还有需要合并的字段,你需要在合并Val2的时候,针对每个嵌套元素做更细粒度的合并逻辑。
内容的提问来源于stack exchange,提问作者user4468000
相关产品推荐
相关产品推荐

