0

0

如何在Golang中捕获JSON序列化错误_Golangjson.Marshal错误处理示例

P粉602998670

P粉602998670

发布时间:2026-01-01 16:15:08

|

850人浏览过

|

来源于php中文网

原创

json.Marshal 从不 panic,只返回 error;真正导致崩溃的是忽略 error 后使用 nil 切片、空指针或类型断言失败,正确做法是立即检查并处理 error。

如何在golang中捕获json序列化错误_golangjson.marshal错误处理示例

为什么 json.Marshal 会 panic?它其实不会

很多人以为 json.Marshal 可能 panic,实际它**从不 panic**,而是返回 error。真正让你程序崩溃的,往往是忽略这个 error 后继续用 nil字节切片(比如传给 HTTP 响应或写文件),或在后续逻辑中触发空指针/类型断言失败。

  • json.Marshal 只在遇到不可序列化值时返回非 nil 错误,例如含 funcchan、未导出字段且无 json tag、循环引用等
  • 错误类型是 *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。以下情况必然失败,且错误信息明确:

  • 含有 funcchancomplex64/complex128 类型字段(即使已导出)
  • 结构体字段未导出(首字母小写)且没加 json:"..." tag;若加了 json:"-" 则跳过,不报错
  • map 的 key 类型不是 stringintint32 等基本可比较类型(如 map[struct{X int}]string
  • 字符串字段包含非法 UTF-8 字节(例如从二进制读取后未校验就赋值)
  • 嵌套结构体存在循环引用(A 包含 B,B 又包含 A 指针)—— 这会触发 json: unsupported value: encountered a cycle

测试和调试 json.Marshal 错误的实用技巧

线上环境难复现循环引用或非法 UTF-8,建议在单元测试中主动构造边界 case。

LongShot
LongShot

LongShot 是一款 AI 写作助手,可帮助您生成针对搜索引擎优化的内容博客。

下载

立即学习go语言免费学习笔记(深入)”;

  • reflect.ValueOf(v).Kind() == reflect.Func 提前过滤掉含函数字段的结构体(适合封装自己的 SafeMarshal
  • 对用户输入的字符串,用 utf8.Valid([]byte(s)) 预检,避免传入 json.Marshal 后才报错
  • 开启 go test -v 并在测试中故意传入含 chan int 的结构体,确认错误分支被覆盖
  • 注意:json.Marshal(nil) 是合法的,返回字面量 null,不会出错

最常被忽略的是:错误处理后忘记 return,导致仍执行后续 w.Write(nil) —— 这会让客户端收到空响应而不报错,排查难度远大于直接返回 500。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

174

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

225

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

335

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

388

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

193

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

188

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

191

2025.06.17

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

62

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.1万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号