上线必须用 go build 编译二进制文件而非 go run;nginx 需透传四类请求头,gin 需配置信任代理;router.run() 必须显式指定监听地址;线上需用 systemd 或 docker 正确托管进程并捕获日志。

直接跑 go run 不能上线
本地开发用 go run main.go 很方便,但上线必须用编译后的二进制文件。Go 是静态链接语言,go run 会边编译边运行,依赖 Go 环境、源码、模块缓存,服务器上几乎从不装 Go 编译器——既不安全也不必要。
- 上线前必须执行
go build -o myapp main.go,生成独立可执行文件 - Linux 服务器部署时,推荐加跨平台编译参数:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o myapp main.go,避免动态链接 libc 等问题 - 别把
go.mod、go.sum或vendor/一起传上去——二进制已含全部逻辑,多传反而增加攻击面
Nginx 反向代理怎么配才不丢头信息
Gin 默认不信任代理转发的请求头,如果 Nginx 不显式透传关键字段,c.ClientIP() 会变成 127.0.0.1,c.Request.Host 可能错乱,健康检查或日志统计全崩。
- 必须在 Nginx
location块里加这四行:proxy_set_header Host $host、proxy_set_header X-Real-IP $remote_addr、proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for、proxy_set_header X-Forwarded-Proto $scheme - Gin 侧要启用信任代理:
router.SetTrustedProxies([]string{"127.0.0.1", "::1"})(若 Nginx 和 Go 同机);若走内网 IP 段,填对应网段如"192.168.0.0/16" - 漏配
X-Forwarded-Proto会导致重定向跳http://而不是https://,前端登录态、Cookie 的Secure标志直接失效
router.Run() 绑定地址写错会监听失败
开发时写 router.Run() 默认监听 0.0.0.0:8080,看似省事,但上线时若没指定地址,可能因端口被占、权限不足(非 root 无法 bind 1–1023)、或 Docker 容器网络配置冲突而静默失败。
- 上线务必显式指定监听地址:
router.Run(":8080")(监听所有 IPv4/IPv6 接口)或router.Run("127.0.0.1:8080")(仅本地,配合 Nginx 用) - 别写
router.Run("localhost:8080")——某些系统解析为 IPv6 地址,导致只监听::1,Nginx 用127.0.0.1连不上 - 启动后用
lsof -i :8080或ss -tulpn | grep :8080确认进程确实在监听,别只信日志里的 “Starting server on…”
没有进程守护,重启后服务就没了
手动执行 ./myapp 启动,关掉终端或 SSH 断连,进程立刻退出。线上服务必须由系统级进程管理器接管。
- 推荐用
systemd:写一个/etc/systemd/system/myapp.service,核心项包括Type=simple、ExecStart=/opt/myapp/myapp、Restart=always、User=www-data - 别用
nohup ./myapp &或screen——它们无法自动拉起崩溃进程,也不受系统启动/关机流程控制 - 如果用 Docker,确保
ENTRYPOINT ["./myapp"]且不带sh -c包裹,否则信号(如 SIGTERM)无法正确传递给 Gin 主进程,导致优雅关闭失效
真正容易被忽略的是日志落盘和标准错误捕获——systemd 默认把 stdout/stderr 收进 journal,但很多人没配 journalctl -u myapp -f 查日志,出问题只能干瞪眼。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











