最直接生成png用github.com/skip2/go-qrcode库,调用qrcode.writefile并检查error;需自定义颜色或透明背景时,须用qrcode.encode+image/draw手动绘制。

用 qrcode 库生成 PNG 最直接
Go 官方没有内置二维码支持,得靠第三方库。目前最稳定、维护活跃、API 清晰的是 github.com/skip2/go-qrcode。它不依赖 CGO,纯 Go 实现,编译后单文件可运行,适合 CLI 工具或微服务嵌入。
常见错误是直接用 qrcode.WriteFile 却忽略返回的 error —— 比如路径不可写、尺寸超出限制(默认最大 1024×1024),或内容过长导致纠错等级自动降级却没感知。
实操建议:
- 始终检查
qrcode.WriteFile返回的error,尤其在容器或无权限目录下运行时 - 显式传入尺寸和纠错等级,别依赖默认值:
qrcode.WriteFile("hello", "out.png", qrcode.Medium, 256) - 若需透明背景或自定义颜色,
WriteFile不支持,得用Encode+ 手动绘图(见下一条)
需要自定义颜色或透明背景?用 qrcode.Encode + image/draw
qrcode.WriteFile 只能输出黑白 PNG,没法改前景色、背景色,也不能加 logo 或圆角。这时候必须走底层:调用 qrcode.Encode 得到 *image.Gray,再用标准库 image/draw 和 image/color 重绘。
容易踩的坑是直接对 *image.Gray 的像素做 Set,但它的 Bounds() 坐标系和最终 PNG 尺寸不一致 —— Encode 返回的是逻辑模块(module)矩阵,不是像素图;必须先缩放再绘制。
示例关键步骤:
- 用
qrcode.Encode("data", qrcode.Medium, 256)获取*image.Gray - 创建目标
*image.RGBA,尺寸 = 模块数 × 每模块像素(如 256×256 → 每模块 4px,则 canvas 为 1024×1024) - 遍历原图每个模块坐标
(x, y),用双层循环填充对应像素块(别用Set单点,性能差且易错位) - 前景色用
color.NRGBA{0, 128, 255, 255},背景色设为color.Transparent即可支持透明 PNG
qrcode.Low 和 qrcode.Highest 对内容长度敏感
纠错等级不是“越高越好”。qrcode.Highest 虽容错强,但会显著缩短可编码字节数——比如 UTF-8 字符串,在 Medium 下能塞 900 字符,换 Highest 可能只剩 500。实际项目中常因盲目选最高级,导致扫码失败却不报错(库静默截断)。
使用场景判断优先级:
- 纯数字短码(如订单号)→
qrcode.Low足够,体积小、扫码快 - 含中文/URL 的中等长度文本 →
qrcode.Medium是默认平衡点 - 需打印在易磨损表面(如快递面单)→ 选
qrcode.High,别上Highest,除非你确认内容长度远低于该等级上限 - 用
qrcode.GetQRCode可提前检查编码是否成功,避免 runtime panic
Web 服务中生成二维码要防并发写同名文件
在 HTTP handler 里直接用 qrcode.WriteFile("qrcode.png", ...) 是危险操作:多个请求同时写同一路径会覆盖或报 text file busy 错误(尤其 Linux 上)。更糟的是,有些系统会缓存文件句柄,导致返回旧图。
正确做法永远基于请求上下文生成唯一路径或直接返回 bytes:
- 用
qrcode.Encode得到*image.PNG,再用png.Encode(w, img)直接写入http.ResponseWriter - 若必须存文件,路径里加入时间戳或随机字符串:
fmt.Sprintf("qrcode_%d_%s.png", time.Now().UnixNano(), randStr(6)) - 定期清理临时目录(别依赖“下次覆盖”,磁盘可能撑爆)
- 注意
Content-Type设为image/png,否则浏览器当下载处理
真正麻烦的从来不是“怎么画出方块”,而是尺寸缩放时的像素对齐、多语言内容的 UTF-8 编码边界、以及高并发下 IO 的竞态——这些细节不报错,但扫出来就是模糊或失败。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











