Go 语言中解决浮点数精度问题的最佳实践
Go 里的浮点数精度问题并不是语言缺陷,而是 IEEE 754 二进制表示的天然结果。本文从 0.1 + 0.2 为什么失真讲起,再结合金额计算、精确比较和数据库设计,梳理整数、decimal、math/big 与误差比较四种常见方案的适用边界。
Go 里的浮点数精度问题并不是语言缺陷,而是 IEEE 754 二进制表示的天然结果。本文从 0.1 + 0.2 为什么失真讲起,再结合金额计算、精确比较和数据库设计,梳理整数、decimal、math/big 与误差比较四种常见方案的适用边界。

关闭 channel 不等于数据立刻消失。Go 的规则是:已发送的数据仍可继续读出,等缓冲区清空后,再读会拿到该类型零值,同时 `ok == false`。搞清这套行为,才能正确使用 `for range`、双返回值接收,以及避免向已关闭 channel 发送数据导致 panic。

很多 Go 开发者把 `for range` 只当成遍历 slice、map 的语法糖,但它还能直接处理数组、字符串和通道,而且每种类型的返回值和行为都不一样。本文按实际开发里的高频场景梳理 `for range` 的适用对象、简写方式与常见坑点,帮你判断什么时候能直接用,什么时候要额外注意副本、顺序和阻塞问题。

Go 1.21 起,`go.mod` 多了一个容易被忽略的 `toolchain` 指令。它不是替代 `go` 版本声明,而是把“最低语言版本”和“实际构建工具链版本”拆开管理,适合需要统一开发环境、控制补丁版本、逐步升级 Go 的项目。 Go 1.21 之后,`go.mod` 里的 `toolchain` 开始频繁出现在新项目中,但不少人看到它时,第一反应仍是“这和 `go` 指令到底差在哪”。

Go 语言并不是一开始就“用自己写自己”。它最早由 Google 团队先用 C 写出首个编译器,再逐步走向自举。理解这条路径,能更准确判断 Go 的成熟度、工具链设计,以及它为何常被视为务实的系统编程语言。

在 SQL 里同时统计“满足条件”和“不满足条件”的数量,看起来简单,但一旦遇到 NULL、分组和跨数据库差异,结果很容易偏。本文用可直接落地的写法说明为什么应优先使用两个 `SUM(CASE WHEN ...)`,并补齐分组比例、兼容性和 NULL 检查这几个关键点。

Go 的 `go/ast` 包并不只服务编译器,它也是 `gofmt`、静态检查、代码生成和文档提取等工具的基础。本文从 AST 是什么讲起,再结合遍历示例、典型用途和使用注意点,帮你判断它适合拿来做哪些自动化工作。

这道 Go 面试题的关键不在计算结果,而在类型规则:`float64` 不能使用 `|` 这类位运算符,代码会直接编译失败。文章从报错出发,解释 Go 为什么把位运算限定在整数类型,并补充浮点数的正确处理方式与需要操作位表示时的标准做法。

Go 里的 `struct{}` 常被称为“零大小类型”,但它为什么几乎不占空间、什么时候真能省内存、又有哪些边界条件,很多人并不清楚。本文从 `unsafe.Sizeof` 验证、`zerobase` 机制,到 Set、信号通道和无状态接收器等常见写法,系统说明空结构体该怎么用、哪里要谨慎。

Go 中关闭 channel 后仍然可以读,但读到什么取决于缓冲区是否还有未消费数据。本文用一段简单实验解释关闭后的读取规则、`ok` 判断方式,以及缓冲与无缓冲 channel 的差异,顺带梳理实际开发里更稳妥的关闭习惯。

Go 不允许直接对 map 元素取地址,这不是语法上的任性限制,而是为了避免元素在扩容、重哈希后地址变化带来的悬空指针。理解这一点后,就能更稳妥地选择“取出-修改-存回”或指针类型 map,并避开 range 遍历时的取址陷阱。

`//export` 是 Go 提供给 C 调用 Go 函数的一条关键通道,但它并不是写个注释就结束。本文用一个最小可运行示例,说明它的语法要求、编译方式、C 侧调用方法,以及内存、类型和平台相关的几个边界条件。
