go源文件必须用utf-8编码,否则编译报illegal utf-8 sequence;docker中time.now()返回utc因缺tzdata,需安装或挂载时区文件;跨时区处理禁用time.local,须用time.loadlocation加载iana时区并复用;数据库存utc,api返回带+08:00格式;goproxy与goprivate须配对设置私有模块代理。

Go源文件必须用UTF-8编码,别信编辑器默认设置
VS Code、GoLand 默认可能用 UTF-8,但 Vim 或某些终端里打开的 .go 文件实际是 ISO-8859-1,一编译就报 illegal UTF-8 sequence。这不是语法错,是字节流解析失败。
- 在 VS Code 右下角点编码名 → 选 “Save with Encoding” → 强制存为
UTF-8 - GoLand:Settings → Editor → File Encodings → 把 Global Encoding、Project Encoding 全设成
UTF-8 - Vim:确认
.vimrc有set encoding=utf-8和set fileencoding=utf-8 - CI 流水线里加检查:
file *.go | grep -v 'UTF-8',发现非 UTF-8 就 fail
容器里 time.Now() 返回 UTC?不是 bug,是缺 tzdata
本地跑 time.Now() 显示北京时间,Docker 里却变成 UTC——不是代码问题,是 Alpine/Debian 镜像没装时区数据,/usr/share/zoneinfo/Asia/Shanghai 根本不存在,time.LoadLocation("Asia/Shanghai") 直接 panic。
- Alpine 镜像:Dockerfile 加
RUN apk add --no-cache tzdata - Debian/Ubuntu 镜像:加
RUN apt-get update && apt-get install -y tzdata && rm -rf /var/lib/apt/lists/* - 更轻量做法:启动容器时挂载宿主机时区文件,
-v /etc/localtime:/etc/localtime:ro,比装包快,也避免镜像膨胀 - 别信
ENV TZ=Asia/Shanghai—— Go 的time包完全不读这个变量
跨时区时间处理,别碰 time.Local
time.Local 看似省事,但它把环境不确定性带进业务逻辑:开发机是 CST,CI 是 UTC,K8s Pod 可能又是别的;一旦用 t.In(time.Local) 做格式化或截断,结果就不可复现。
- 所有明确时区场景,都用
time.LoadLocation("Asia/Shanghai")加载并复用*time.Location实例,别每次调用都重新解析 - 字符串解析必须用
time.ParseInLocation,layout 要跟时区标识严格匹配:"2006-01-02T15:04:05+08:00"对应"+08:00","2006-01-02T15:04:05Z"对应"Z" - 数据库存时间,一律转
t.UTC()再入库;API 返回时间,用t.In(shanghai).Format("2006-01-02T15:04:05+08:00"),末尾+08:00比Z更明确告诉前端这是东八区时间 - 别写
time.LoadLocation("CST")—— IANA 不认缩写,会返回nil,后续t.In(loc)panic
GOPROXY 和 GOPRIVATE 必须配对设,否则私有模块拉不下来
国内团队用公司内网 GitLab 托管私有模块,但 go mod tidy 总卡在 proxy.golang.org 或 goproxy.cn,报 module not found ——不是网络问题,是 GOPRIVATE 没配,Go 工具链仍试图走代理查私有域名。
- 执行
go env -w GOPROXY=https://goproxy.cn,direct - 再执行
go env -w GOPRIVATE=gitlab.example.com/myorg/*(替换成你的真实域名和路径前缀) - 验证:
go env GOPRIVATE输出应是你设的值;go list -m all | grep private应能正常列出私有模块 - CI 脚本里也要显式设这两个变量,不能只靠本地配置
time.LoadLocation 成功不代表它加载的是你预期的偏移——Asia/Shanghai 在夏令时不存在,但 America/New_York 会自动切,而 Europe/London 同样如此;真正要校验的,是运行时 time.Now().In(loc).Zone() 返回的偏移值,不是字符串名。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











