前段时间给程序加了个功能,打印时间按照时区打印,具体看起来是这样
loc, _ := time.LoadLocation("Asia/Chongqing") return time.Now().In(loc).Format("2006-01-02 15:04:05")
在本地运行没有丝毫问题,于是就想当然的推到了线上,结果线上的环境在进行到这步的时候直接panic了,嗯,看来是过于的自信导致了问题,明显loc是nil了,那么打印下错误吧,结果看到了这么一行:
open /usr/local/go/lib/time/zoneinfo.zip: no such file or directory
于是瞬间就明白了,我们线上使用的是docker镜像,复制到容器里的go程序也是编译好的二进制文件,所以容器里没有go环境,导致在本地能正常运行的程序在线上因为缺少对应文件而panic。
知道了问题,就好解决了,当然这里可以直接换加了go环境的镜像,但是明显这样违背了docker作为线上生产环境的初衷,即最小可用,加入了go环境会直接把大量的冗余数据加入到容器中,使单个容器的体积直接倍增,所以我们只需要把这个特定依赖的文件复制到容器中即可,在Dockerfile中加入这样一段:
COPY ./zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip // 这里我把这个文件也在本地复制到了我的项目中,因为我们的打包上线工作由线上的CI服务来完成,如果是在本地打包,那么可以直接复制原文件 COPY /usr/local/go/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip
最后说一句,下划线无视error什么的,是真不可取啊,吸取教训把上面的代码也换成了
loc, err := time.LoadLocation("Asia/Chongqing") if err != nil { LogError("parse location err:", err) loc = time.Local } return time.Now().In(loc).Format("2006-01-02 15:04:05")