Go打包和部署:从编译到运行的全指南

简介: 本文介绍了Go语言项目的打包和部署方法,包括使用`go run`、`go build`和`go install`命令进行编译,以及跨平台交叉编译。文章还提到了编译参数如`-x`、`-n`和`-race`等。此外,还讨论了如何利用第三方工具(如go-bindata)打包非Go文件,以及清理编译缓存和压缩二进制文件。最后,文中展示了如何使用supervisor和Docker进行部署,并提供了Nginx的反向代理配置示例。

今天我们来聊聊Go语言项目如何打包和部署。无论你是初学者还是资深开发者,了解如何将你的代码打包成可执行文件,并在不同环境下部署运行,都是一项非常重要的技能。

打包相关命令

Go语言提供了一些基本命令来帮助我们编译和打包程序。

基本命令

命令 含义
go run 编译并马上运行 go 程序(只接收 main 包下的文件作为参数)
go build 编译指定的源文件、软件包及其依赖项,但它不会运行编译后的二进制文件。(如果想要指定所生成的二进制文件为其他名称,则可以通过 -o 参数进行调整)
go install 编译并安装源文件、软件包到 $GOBIN 目录下。 可以执行 go install -x 查看它的编译过程。文件名称为 Go modules 的项目名,而不是目录名

编译参数

参数 含义
-x 打印编译过程中的所有执行命令
-n 打印编译过程中的所有执行命令,但不执行生成的二进制文件
-a 强制重新编译所有涉及的依赖
-o 指定生成的二进制文件名称
-p 指定编译过程中可以并发运行程序的数量
-work 打印临时工作目录的完整路径,在退出时不删除该目录
-race 启用数据竞争检测
-installsuffix 在软件包安装的目录中增加后缀标识,以保持输出与默认版本分开

跨平台交叉编译

Go语言支持跨平台交叉编译,允许我们在一个平台上编写代码,编译出在另一个平台上运行的程序。

编译Linux平台amd64架构的可执行文件

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o <application-name>

# 比如
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o <application-name> .

环境变量

变量名 含义
CGO_ENABLED 是否在Go代码中调用C代码
GOOS 目标操作系统
GOARCH 目标操作系统的架构

第三方打包工具

Go语言还有一些第三方工具,可以帮助我们将非.go文件(如静态文件、模板文件等)打包到二进制文件中。

使用go-bindata将数据文件转换成Go代码

  1. 安装go-bindata
go get -u github.com/go-bindata/go-bindata/...
  1. 将配置文件生成Go代码:
go-bindata -o configs/config.go -pkg configs configs/config.yaml
  1. 读取文件中的配置信息:
data, err := configs.Asset("configs/config.yaml")
if err == nil {
   
    fmt.Println(string(data))
}

编译缓存

查看和清理编译缓存:

go env GOCACHE
go clean -cache

压缩编译后的二进制文件

去除调试信息和符号表信息

go build -ldflags="-w -s"

使用upx工具压缩

编译信息写入

使用-ldflags设置编译信息:

go build -o app-service -ldflags \
"-X main.buildTime=`date +%Y-%m-%d,%H:%M:%S` -X main.buildVersion=1.0.0 -X 'main.goVersion=$(go version)' -X main.gitCommitID=`git rev-parse HEAD`"

在上述命令中,通过 -ldflags 命令的 -X 参数可以在链接时将信息写入变量中,其格式为:package_name.variable_name=value

  • 查看编译后的二进制文件和版本信息
./app-service -version

# output is:
# Build Time: 2022-03-27,13:50:26
# Build Version: 1.0.0
# Build Go Version: go version go1.16.3 darwin/amd64
# Build Git Commit Hash ID: b3473e9cc98148f5c94b53c1cada7de133143462

部署

使用supervisor部署

  1. 创建supervisor配置文件alex-blog.conf
  2. 使用supervisorctl管理服务。

创建 supervisor 相关配置信息

vim /etc/supervisor/conf.d/alex-blog.conf

# 程序名称,stop start 等管理时使用
[program:alex-blog]
# 进入该目录运行命令,确保了和项目相关的一些配置文件可以得到加载,比如 .env 文件
directory=/data/www/blog
# 以绝对路径的方式执行 alex-blog 二进制文件
command=/data/www/blog/alex-blog
# 重启时发送的信号,确保端口正常关闭
stopsignal=TERM
# 是否自启动
autostart=true
# 是否自动重启
autorestart=true
# 执行程序的用户
user=www-data
# 输出日志位置
stdout_logfile=/data/log/supervisor/blog/stdout.log
# 错误输出日志
stderr_logfile=/data/log/supervisor/blog/stderr.log

重载 Supervisor 配置文件

# 重载 supervisor 配置文件
supervisorctl reload

# 查看程序名称为 alex-blog 的程序状态
# 如果直接执行 `supervisorctl status` 命令的话,则是查看所有任务的状态
supervisorctl status alex-blog

# 关闭所有任务
supervisorctl shutdown

# 启动任务
supervisorctl start <程序名>

# 关闭任务
supervisorctl stop <程序名>

使用docker部署

  1. 编写Dockerfile并构建镜像。
  2. 运行容器。

先要在宿主机中项目根目录下进行编译

# 交叉编译生成 Linux 平台的可执行文件
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o hello-world

编写 Dockerfile 文件

# 基础镜像
FROM alpine:3.12
# 或者使用 Scratch 镜像
# FROM scratch

# 维护者
MAINTAINER alex

# docker build 时执行命令
RUN mkdir -p /go-project/demo \
&& ln -sf /dev/stdout /go-project/demo/storage/service.log

# 工作目录
WORKDIR /go-project/demo

# 拷贝
COPY hello-world /go-project/demo/hello-world
# 或者直接将当前目录下所有的文件拷贝到容器中
# COPY . /go-project/demo

# 这里暴露端口与否都行
# EXPOSE 8501

# docker run 时执行的命令
ENTRYPOINT ["./hello-world"]

Nginx配置

配置Nginx作为反向代理,服务静态资源和处理请求转发。


upstream go-project {
   
    # go-project HTTP Server 的 IP 及 端口
    server 127.0.0.1:9501;
}

server
{
   
    listen 80;
    server_name goblog.com;

    access_log   /data/log/nginx/goblog/access.log;
    error_log    /data/log/nginx/goblog/error.log;

    location /static/ {
   
      alias /www/wwwroot/gitlab/go-project/public/uploads/; #静态资源路径
    }

    location / {
   
        # 将客户端的 Host 和 IP 信息一并转发到对应节点
        proxy_redirect             off;
        proxy_set_header           Host             $http_host;
        proxy_set_header           X-Real-IP        $remote_addr;
        proxy_set_header           X-Forwarded-For  $proxy_add_x_forwarded_for;

        # 转发Cookie,设置 SameSite
        proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";

        # 执行代理访问真实服务器
        proxy_pass                 http://go-project;
    }

}

总结

通过今天的学习,我们了解了Go语言项目的打包和部署流程,包括使用基本命令进行编译、跨平台编译、使用第三方工具打包静态文件、编译缓存、压缩二进制文件以及使用supervisor和docker进行部署。

相关文章
|
1月前
|
编译器 测试技术 Go
Go语言的自给自足:编译自身的神奇之旅
Go语言的自给自足:编译自身的神奇之旅
|
4月前
|
算法 Java Go
运行时管理GO与Java的概要对比
【5月更文挑战第17天】本文介绍Go、Python和Java的运行时机制各异。Go是编译型语言,其runtime负责内存管理、GC和协程调度,强调性能和低延迟。Java的JVM兼顾跨平台和性能,使用字节码和JIT编译,其GC策略复杂且高效。三种语言在设计和优化上各有侧重,适用不同场景。
71 3
|
27天前
|
编译器 Go 开发者
Go 在编译时评估隐式类型的优点详解
【8月更文挑战第31天】
24 0
|
27天前
|
Kubernetes Cloud Native Go
云原生之旅:构建和部署一个简单的Go应用程序
【8月更文挑战第31天】在本文中,我们将探索如何利用云原生技术构建和部署一个Go语言编写的简单Web应用。通过实际操作示例,我们不仅能够了解云原生的基本概念,还能学习到如何在Kubernetes集群上运行和管理容器化应用。文章将引导读者从零开始,逐步搭建起自己的云原生环境,并实现代码的容器化与自动化部署,最终达到持续交付的目的。
|
2月前
|
Linux Go API
go创建web项目分别在windows和linux部署
go创建web项目分别在windows和linux部署
33 0
|
2月前
|
Go 持续交付
使用 Makefile 管理和部署 Go 项目
在软件开发中,`Makefile` 用于自动化任务,提升效率。在Go项目中,它简化构建和部署。`Makefile`集成了编译、打包、清理和部署等任务,减少错误,提高效率。通过定义规则和依赖,`make`工具执行任务。示例展示了如何创建`Makefile`进行Go应用的自动化部署,包括构建、传输、停启服务。通过`make deploy-dev`一键执行部署流程。`Makefile`不仅简化部署,还可扩展实现更多复杂自动化,提升开发流程的专业性和效率。
43 0
|
3月前
|
JavaScript
vue : 无法加载文件 D:\module\npm_module\npm_modules\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.c
vue : 无法加载文件 D:\module\npm_module\npm_modules\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.c
|
4月前
|
数据可视化 算法 Java
了解go语言运行时工具的作用
【5月更文挑战第16天】本文简介`runtime`库提供系统调用包装、执行跟踪、内存分配统计、运行时指标和剖析支持。`internal/syscall`封装系统调用,保证uintptr参数有效。`trace`用于执行跟踪,捕获各种事件,如goroutine活动、系统调用和GC事件。`ReadMemStats`提供内存分配器统计。`metrics`接口访问运行时定义的度量,包括CPU使用、GC和内存信息。`coverage`支持代码覆盖率分析,`cgo`处理C语言交互,`pprof`提供性能剖析工具集成。这些功能帮助优化和理解Go程序的运行行为。
61 6
|
jenkins 测试技术 持续交付
|
jenkins 测试技术 Go
持续集成及部署利器:Go
Go是一款先进的持续集成和发布管理系统,由ThoughtWorks开发。(不要和Google的编程语言Go混淆了!)其前身为Cruise,是ThoughtWorks在做咨询和交付交付项目时自己开发的一款开源的持续集成工具。
820 0