Go jsontext Token 怎样在读取 token 数值(输入边界)
在 Go 1.27 的 encoding/json/jsontext 中,Token 表示 JSON 词法层的一个 token。读取数字时,关键不是直接调用 Int() 或 Uint(),而是先确认 Kind() == jsontext.KindNumber,再根据业务需要选择整数或浮点读取方法。
官方文档:https://pkg.go.dev/encoding/json/jsontext
安全读取 token 数值可以记成四步:先判数字类型,再选 accessor;用errors.Is识别语法或范围错误;最后注意ReadToken返回值可能依赖 Decoder 缓冲区。Int、Uint出错时仍可能返回一个合理值,不能只看数值不看 error。
KindNumber只说明 token 是 JSON 数字,不保证它适合目标 Go 类型。Int和Uint可能发生向零截断,超范围时会返回饱和值并带错误。- 从
Decoder.ReadToken得到的原始 token,在下一次 Decoder 调用后不应继续依赖;需要保存时先Clone。
先用 Kind 确认 token 真的是数字
Token 不只表示数字,还可以表示 null、布尔值、字符串以及对象和数组的起止分隔符。数字 accessor 对错误的 token 类型会 panic,因此输入来自外部 JSON 时,第一层判断应放在读取方法之前。
下面的辅助函数只把 JSON 数字交给 Int,其它 token 直接返回带上下文的错误。注释中的每个判断都对应一个输入边界,业务层可以再把错误映射成自己的字段错误。
package main
import (
"fmt"
"encoding/json/jsontext"
)
func readInt(tok jsontext.Token) (int64, error) {
// 先挡住字符串、布尔值和结构分隔符,避免 Int 对非数字 token 触发 panic。
if tok.Kind() != jsontext.KindNumber {
return 0, fmt.Errorf("expected JSON number, got %s", tok.Kind())
}
// Int 会解析带符号的整数语义,返回值是否可用必须和 error 一起判断。
n, err := tok.Int()
if err != nil {
return 0, fmt.Errorf("read integer %q: %w", tok.String(), err)
}
return n, nil
}
这里的 KindNumber 是必要条件,但不是完整的业务校验。例如 token 文本可以是带小数或指数的 JSON 数字,是否允许这类输入要交给 Int 的错误结果和业务规则共同决定。

Int、Uint 和 Float 的选择不要混用
有符号计数、可能出现负值的偏移量适合 Int();业务字段明确不允许负数且范围对应 uint64 时才使用 Uint()。普通 JSON 数字需要小数或指数语义时使用 Float()。Float32() 只适合调用方已经知道这个 token 按 32 位精度生成的场景,不能为了节省一个变量宽度就默认使用。
func readCount(tok jsontext.Token) (uint64, error) {
// 无符号计数不接受非数字 token,负数和不符合无符号整数语义的文本交给 Uint 报错。
if tok.Kind() != jsontext.KindNumber {
return 0, fmt.Errorf("count must be a JSON number, got %s", tok.Kind())
}
n, err := tok.Uint()
if err != nil {
return 0, fmt.Errorf("invalid count %q: %w", tok.String(), err)
}
return n, nil
}
func readRatio(tok jsontext.Token) (float64, error) {
// 比例允许小数,因此不能用 Int;Float 按 64 位精度读取 JSON 数字。
if tok.Kind() != jsontext.KindNumber {
return 0, fmt.Errorf("ratio must be a JSON number, got %s", tok.Kind())
}
n, err := tok.Float()
if err != nil {
return 0, fmt.Errorf("invalid ratio %q: %w", tok.String(), err)
}
return n, nil
}
不要把字符串形式的 "12" 当成数字 token 来调用这些方法。Token.String() 对字符串返回解码后的字符串值,对数字返回原始 JSON 表示;它适合放进错误信息或日志,但不能代替 Kind() 做类型判断。
语法错误、范围错误和截断要分开处理
Int() 与 Uint() 会用与 strconv.ErrSyntax、strconv.ErrRange 匹配的错误说明问题。范围错误时仍可能返回一个合理值,超出目标整数表示范围时还会饱和到最近的可表示值,所以生产代码应先处理 error,再决定是否把结果交给业务层。
import (
"errors"
"fmt"
"strconv"
"encoding/json/jsontext"
)
func classifyInt(tok jsontext.Token) (int64, error) {
// 先确认调用前提,数值方法本身不会替调用方检查 Kind。
if tok.Kind() != jsontext.KindNumber {
return 0, fmt.Errorf("not a number: %s", tok.Kind())
}
n, err := tok.Int()
if err == nil {
return n, nil
}
// ErrSyntax 表示输入形态不符合当前整数读取语义,例如负号/小数规则不匹配。
if errors.Is(err, strconv.ErrSyntax) {
return 0, fmt.Errorf("integer syntax is invalid for %q: %w", tok.String(), err)
}
// ErrRange 表示不能无损放进 int64;即使 n 有值,也不能当成精确结果。
if errors.Is(err, strconv.ErrRange) {
return 0, fmt.Errorf("integer is out of int64 range: %w", err)
}
return 0, fmt.Errorf("read integer: %w", err)
}
文档明确说明整数读取会忽略小数部分并向零截断,因此 12.9 这类输入不能在业务上默认视为“合法整数”。如果字段必须是整数,应在 token 层保留原始表示并增加格式约束,不能把截断后的结果悄悄写回数据库或计数器。

ReadToken 返回值需要注意 Clone
如果 token 是通过 Decoder.ReadToken 得到的,它的原始 JSON 文本可能由 Decoder 的内部缓冲区支持。下一次调用 Decoder 的方法后,这个 token 不应再被当成独立值使用。需要把 token 放进队列、缓存、异步任务或错误记录时,先调用 Clone()。
func keepNumber(dec *jsontext.Decoder) (jsontext.Token, error) {
tok, err := dec.ReadToken()
if err != nil {
return jsontext.Token{}, err
}
if tok.Kind() != jsontext.KindNumber {
return jsontext.Token{}, fmt.Errorf("expected number, got %s", tok.Kind())
}
// 跨过下一次 Decoder 调用仍要使用,因此复制脱离 Decoder 缓冲区的 token。
return tok.Clone(), nil
}
相反,jsontext.Int(42)、jsontext.Uint(42)、jsontext.Float(0.5) 等构造出来的 token 本身已经独立保存,不需要为了生命周期再次 Clone。这一区别只影响 token 的存活时间,不会改变数字解析的类型或范围规则。
常见问题
调用 Token.Int 之前一定要判断 Kind 吗?
只要 token 来源不受你完全控制,就应该判断。Int、Uint 会对非数字 token panic,提前判断能把输入问题转成普通 error。
Uint 能读取负数吗?
不能把负数当作无符号整数接受。应让 Uint 返回错误,并按 strconv.ErrSyntax 或 strconv.ErrRange 分类处理。
为什么 Int 返回了数值还要看 error?
因为语法不匹配或超出 int64 范围时,文档允许返回一个合理值或饱和值。只有 error 为 nil 时,才适合把该数值当作无损读取结果。
Token.Clone 会把数字转换成别的类型吗?
不会。Clone 只把依赖 Decoder 缓冲区的原始 token 复制成独立 token,不负责类型转换、范围检查或业务校验。
Go go/doc/comment.Parser 怎样解析文档注释
- 上一篇
- Go go/doc/comment.Parser 怎样解析文档注释
- 下一篇
- Go utf8.RuneLen 怎样判断 rune 占用几个字节
-
- Golang · Go教程 | 24分钟前 |
- Go net/http Protocols.SetUnencryptedHTTP2 怎样启用明文 HTTP/2
- 178浏览 收藏
-
- Golang · Go教程 | 27分钟前 |
- Go parquet-go 怎么把结构体切片写成 Parquet 文件
- 121浏览 收藏
-
- Golang · Go教程 | 28分钟前 |
- Go crypto/mldsa 怎样在生成 ML-DSA 签名(输入边界)
- 112浏览 收藏
-
- Golang · Go教程 | 31分钟前 |
- Go build.Context.MatchFile 怎样按构建标签筛选源文件
- 309浏览 收藏
-
- Golang · Go教程 | 34分钟前 | go · unicode · utf-8 · rune UTF-8 unicode/utf8 Go utf8.RuneLen 字节宽度
- Go utf8.RuneLen 怎样判断 rune 占用几个字节
- 226浏览 收藏
-
- Golang · Go教程 | 57分钟前 |
- Go go/doc/comment.Parser 怎样解析文档注释
- 195浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go sync.Map.Clear 怎样快速清空临时索引
- 107浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go net/http NewFileTransportFS 怎样让 HTTP 客户端读取 fs.FS
- 103浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go text/template block 怎样覆盖基础模板的默认内容
- 338浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go json/v2 UnmarshalRead 怎样在从 Reader 解码 JSON(输入边界)
- 417浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go log/slog Record.Clone 怎样复制结构化日志记录
- 312浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go json/v2 FormatDurationAsNano 怎样编码 time.Duration
- 314浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 677次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 696次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 738次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 707次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 543次使用
-
- 接口返回 200 但前端仍报错怎么办:从响应格式到跨域一步步排查
- 2026-06-14 332浏览
-
- Go map 并发写 panic 怎么办:从共享 map 到可控写入路径
- 2026-06-30 123浏览
-
- golang生成JSON以及解析JSON
- 2023-01-17 329浏览
-
- Go如何实现json字符串与各类struct相互转换
- 2023-01-07 377浏览
-
- Go中使用gjson来操作JSON数据的实现
- 2023-01-07 141浏览

