
本文详解 go 语言中将 json 数组(如 github events api 返回的数据)反序列化为 []struct 类型时的常见错误与正确实践,重点解决“type does not support indexing”问题,并提供可直接运行的初始化、解码与访问方案。
在 Go 中解析 JSON 数组到结构体切片时,一个典型误区是误用 new() 初始化自定义切片类型(如 type GITHUB_EVENT []struct{...}),导致变量实际为 *GITHUB_EVENT(即指向切片的指针),而非切片本身。此时即使 json.Unmarshal 成功写入数据,尝试通过 eventDataJSON[0] 访问元素会触发编译错误:type GITHUB_EVENT does not support indexing —— 因为指针类型不支持索引操作。
✅ 正确做法是让变量直接持有切片值(而非指针),并确保 Unmarshal 接收其地址以完成填充。推荐以下三种等效且安全的方式:
方式一:使用 var 声明(最简洁、推荐)
var eventDataJSON GITHUB_EVENT
err := json.Unmarshal([]byte(eventDataRAW), &eventDataJSON)
if err != nil {
log.Fatal(err)
}
fmt.Println(eventDataJSON[0].Id) // ✅ 可直接索引方式二:使用 make() 显式初始化空切片
eventDataJSON := make(GITHUB_EVENT, 0)
err := json.Unmarshal([]byte(eventDataRAW), &eventDataJSON)
if err != nil {
log.Fatal(err)
}
fmt.Println(eventDataJSON[0].Id) // ✅ 切片已就位,可索引方式三:避免 new() —— 若坚持用 new(),必须解引用后访问
eventDataJSON := new(GITHUB_EVENT) // → *GITHUB_EVENT
err := json.Unmarshal([]byte(eventDataRAW), eventDataJSON)
if err != nil {
log.Fatal(err)
}
fmt.Println((*eventDataJSON)[0].Id) // ✅ 必须加 * 解引用⚠️ 注意事项:
- new(T) 总是返回 *T 且将内存置零,对切片类型而言,结果是 *[]struct{}(即 nil 指针),而 json.Unmarshal 能向 nil 切片指针写入数据,但后续访问需显式解引用;
- make(T, n) 仅适用于 slice/map/channel,它分配并初始化底层数据结构,返回的是 T 类型值(非指针),语义更清晰、代码更健壮;
- 实际项目中建议配合错误处理与空切片校验(如 len(eventDataJSON) > 0),防止 panic;
- 结构体字段首字母必须大写(导出)才能被 json 包访问,示例中已满足该要求。
综上,优先采用 var eventDataJSON GITHUB_EVENT 方式——它语义明确、无需手动初始化、符合 Go 的惯用法,同时保证 eventDataJSON 是可直接索引的切片值,彻底规避指针索引陷阱。










