如何在Golang中捕获JSON序列化错误_Golangjson.Marshal错误处理示例
技术百科
P粉602998670
发布时间:2026-01-01
浏览: 次 json.Marshal 从不 panic,只返回 error;真正导致崩溃的是忽略 error 后使用 nil 切片、空指针或类型断言失败,正确做法是立即检查并处理 error。
为什么 json.Marshal 会 panic?它其实不会
很多人以为 json.Marshal 可能 panic,实际它**从不 panic**,而是返回 error。真正让你程序崩溃的,往往是忽略这个 error 后继续用 nil 的字节切片(比如传给 HTTP 响应或写文件),或在后续逻辑中触发空指针/类型断言失败。
-
json.Marshal只在遇到不可序列化值时返回非nil错误,例如含func、chan、未导出字段且无jsontag、循环引用等 - 错误类型是
*json.UnsupportedTypeError或*json.InvalidUTF8Error等,都实现了error接口,可直接判断 - 不要用
recover()拦截json.Marshal—— 它根本不会抛出 panic
正确处理 json.Marshal 错误的惯用写法
Go 中标准做法是「检查 error,立刻处理」。常见错误是只打印日志却不终止流程,导致下游收到空数据或乱码。
data := struct {
Name string `json:"name"`
Age int `json:"age"`
Fn func() `json:"-"` // 不导出 + 无 tag → 会出错
}{
Name: "Alice",
Age: 30,
}
b, err := json.Marshal(data)
if err != nil {
// ✅ 正确:区分错误类型,做针对性响应
switch e := err.(type) {
case *json.UnsupportedTypeError:
log.Printf("无法序列化字段 %s: %v", e.Type.String(), e.Error())
http.Error(w, "响应数据构造失败", http.StatusInternalServerError)
return
case *json.InvalidUTF8Error:
log.Printf("字符串含非法 UTF-8: %v", e)
http.Error(w, "数据编码异常", http.StatusBadRequest)
return
default:
log.Printf("JSON 序列化未知错误: %v", err)
http.Error(w, "服务内部错误", http.StatusInternalServerError)
return
}
}
w.Header().Set("Content-Type", "application/json")
w.Write(b)
哪些值会导致 json.Marshal 返回 error?
不是所有 Go 类型都能直译成 JSON。以下情况必然失败,且错误信息明确:
- 含有
func、chan、complex64/complex128类型字段(即使已导出) - 结构体字段未导出(首字母小写)且没加
json:"..."tag;若加了json:"-"则跳过,不报错 - map 的 key 类型不是
string、int、int32等基本可比较类型(如map[struct{X int}]string) - 字符串字段包含非法 UTF-8 字节(例如从二进制读取后未校验就赋值)
- 嵌套结构体存在循环引用(A 包含 B,B 又包含 A 指针)—— 这会触发
json: unsupported value: encountered a cycle
测试和调试 json.Marshal 错误的实用技巧
线上环境难复现循环引用或非法 UTF-8,建议在单元测试中主动构造边界 case。
- 用
reflect.ValueOf(v).Kind() == reflect.Func提前过滤掉含函数字段的结构体(适合封装自己的SafeMarshal) - 对用户输入的字符串,用
utf8.Va预检,避免传入
lid([]byte(s))json.Marshal后才报错 - 开启
go test -v并在测试中故意传入含chan int的结构体,确认错误分支被覆盖 - 注意:
json.Marshal(nil)是合法的,返回字面量null,不会出错
最常被忽略的是:错误处理后忘记 return,导致仍执行后续 w.Write(nil) —— 这会让客户端收到空响应而不报错,排查难度远大于直接返回 500。
# 的是
# 自己的
# 很多人
# 让你
# 都能
# 并在
# 而不
# 这会
# app
# http
# js
# json
# go
# golang
# 循环
# Error
# String
# int
# 编码
# 字节
# 指针
# 字符串
# 接口
# nil
# 序列化
# 报错
# 为什么
# red
# NULL
# 封装
# 结构体
# usb
# Struct
# 切片
# map
# 空指针
# switch
# kind
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win10如何更改开机密码_Windows10登录
- phpstudy本地环境mysql忘记密码_重置m
- Python项目维护经验_长期演进说明【指导】
- Windows10系统怎么查看防火墙状态_Win1
- 如何使用Golang实现Web表单数据绑定_自动映
- Win11如何设置自动关机 Win11定时关机命令
- c# 在高并发下使用反射发射(Reflection
- Win10怎么卸载迅雷_Win10彻底卸载迅雷方法
- Win11怎么设置默认图片查看器_Windows1
- 如何用::实现工具类方法调用_php静态工具类设计
- 如何使用Golang进行HTTP服务性能测试_测量
- Mac如何设置动态壁纸?(让桌面动起来)
- 小程序里php怎么变mp4_小程序调用php生成m
- Win11怎么关闭任务栏小图标_Windows11
- Windows10系统服务优化指南_Win10禁用
- c++中的CRTP是什么 c++奇异递归模板模式【
- Windows10系统怎么查看系统版本_Win10
- Windows音频驱动无声音原因解析_声卡驱动错误
- Windows10系统怎么查看CPU核心数_Win
- 电脑无法识别U盘怎么办 Windows磁盘管理与驱
- Python配置文件操作教程_JSONINIYAM
- mac怎么安装adb_MAC配置Android A
- Win10电脑怎么设置IP地址_Windows10
- Win11怎么关闭小组件_Win11禁用任务栏天气
- Windows电脑键盘突然失灵怎么办?(驱动与硬件
- Win11怎么设置DNS服务器_Windows11
- php串口通信波特率怎么选_根据硬件手册设置正确波
- Win11怎么更改电脑密码_Windows 11修
- Windows 11如何查看系统激活密钥_Wind
- How to Properly Use NumPy
- Win11怎么关闭键盘按键音_Win11禁用打字声
- C++如何将C风格字符串(char*)转换为std
- C++如何使用std::async进行异步编程?(
- Win10系统映像怎么恢复 Win10使用系统映像
- Mac的“调度中心”与“空间”怎么用_Mac多桌面
- Win11资源管理器卡顿怎么办 Win11文件资源
- Win11如何设置电源计划_Win11电源计划优化
- Windows如何使用BitLocker To G
- Win11怎么关闭用户账户控制UAC_Window
- Linux怎么禁止Root用户远程登录_Linux
- Python函数接口稳定性_版本演进解析【指导】
- PHP主流架构怎么监控运行状态_工具推荐【操作】
- Windows11怎样开启游戏模式_Windows
- Python字符串操作教程_切片拼接与格式化详解
- Win11如何设置计划任务 Win11定时执行程序
- Win10怎样安装Word样式库_Win10安装W
- Win11怎么设置虚拟桌面 Win11新建多桌面切
- 如何在Golang中实现CI/CD流水线自动化测试
- Python邮件系统自动化教程_批量发送解析与模板
- Win11怎么修改DNS服务器 Win11设置DN

lid([]byte(s))
QQ客服