如何在 Ubuntu 16.04 上为多个平台构建 Go 可执行文件

2023-11-07

介绍

The Go编程语言附带丰富的工具链,使获取包和构建可执行文件变得异常容易。 Go 最强大的功能之一是能够为任何 Go 支持的外部平台交叉构建可执行文件。这使得测试和包分发变得更加容易,因为您不需要访问特定平台即可为其分发包。

在本教程中,您将使用 Go 的工具从版本控制中获取包并自动安装其可执行文件。然后,您将手动构建并安装可执行文件,以便熟悉该过程。然后,您将为不同的体系结构构建可执行文件,并自动执行构建过程来为多个平台创建可执行文件。完成后,您将了解如何为 Windows 和 macOS 以及您想要支持的其他平台构建可执行文件。

先决条件

要学习本教程,您将需要:

  • 通过以下方式设置一台 Ubuntu 16.04 服务器Ubuntu 16.04 初始服务器设置指南,包括 sudo 非 root 用户和防火墙。
  • 去安装,如所述如何在 Ubuntu 16.04 上安装 Go 1.6.

步骤 1 — 从版本控制安装 Go 程序

在从 Go 包创建可执行文件之前,我们必须获取其源代码。这go get工具可以从 GitHub 等版本控制系统获取包。在引擎盖下,go get将包克隆到子目录中$GOPATH/src/目录。然后,如果适用,它会通过构建其可执行文件并将其放置在$GOPATH/bin目录。如果您按照先决条件教程中的描述配置了 Go,则$GOPATH/bin目录包含在您的$PATH环境变量,确保您可以从系统上的任何位置使用已安装的软件包。

The syntax for the go get command is go get package-import-path. The package-import-path is a string that unique identifies a package. It’s often the location of the package in a remote repository like Github, or a directory within the $GOPATH/src/ directory on your machine.

常用的是go get-u标志,指示go get获取包及其依赖项,或者更新这些依赖项(如果它们已存在于计算机上)。

在本教程中,我们将安装Caddy,一个用 Go 编写的 Web 服务器。每球童的指示x,我们将使用github.com/mholt/caddy/caddy为包导入路径。使用go get获取并安装 Caddy:

  1. go get -ugithub.com/mholt/caddy/caddy

该命令将需要一些时间才能完成,但在它获取包并安装它时您不会看到任何进度。没有输出实际上表明命令执行成功。

命令完成后,您将在以下位置找到 Caddy 的源代码:$GOPATH/src/github.com/mholt/caddy。此外,由于 Caddy 有一个可执行文件,因此它会自动创建并存储在$GOPATH/bin目录。通过使用验证这一点which打印可执行文件的位置:

  1. which caddy

您将看到以下输出:

Output
/home/sammy/work/bin/caddy

Note: The go get命令从 Git 存储库的默认分支安装包,在许多情况下是master,或正在开发的分支。确保查看说明,通常位于存储库的README文件,在使用之前go get.

您可以使用 Git 命令,例如git checkout在使用获得的源上选择不同的分支go get命令。查看教程如何使用 Git 分支了解有关如何切换分支的更多信息。

让我们更详细地看看安装 Go 包的过程,首先从我们已经获得的包创建可执行文件。

第 2 步 — 构建可执行文件

The go get命令下载了源代码并通过单个命令为我们安装了 Caddy 的可执行文件。但是您可能想自己重建可执行文件,或者从您自己的代码构建可执行文件。这go build命令构建可执行文件。

虽然我们已经安装了 Caddy,但让我们再次手动构建它,这样我们就可以熟悉这个过程。执行go build并指定包导入路径:

  1. 去构建 github.com/mholt/caddy/caddy

和之前一样,没有输出表明操作成功。可执行文件将在您的当前目录中生成,其名称与包含包的目录相同。在这种情况下,可执行文件将被命名为caddy.

如果您位于包目录中,则可以省略包的路径并只需运行go build.

要为可执行文件指定不同的名称或位置,请使用-o旗帜。让我们构建一个名为的可执行文件caddy-server并将其放在一个build当前工作目录中的目录:

  1. go build -o build/caddy-server github.com/mholt/caddy/caddy

This command creates the executable, and also creates the ./build directory if it doesn’t exist.

现在让我们看看安装可执行文件。

第 3 步 — 安装可执行文件

构建可执行文件会在当前目录或您选择的目录中创建可执行文件。安装可执行文件是创建可执行文件并将其存储在$GOPATH/bin. The go install命令的工作方式就像go build, but go install负责将输出文件放置在适合您的位置。

要安装可执行文件,请使用go install,后跟包导入路径。再次使用 Caddy 来尝试一下:

  1. go installgithub.com/mholt/caddy/caddy

就像与go build,如果命令成功,您将看不到任何输出。和以前一样,创建的可执行文件的名称与包含包的目录的名称相同。但这一次,可执行文件存储在$GOPATH/bin. If $GOPATH/bin是你的一部分$PATH环境变量,可执行文件可以从操作系统上的任何位置使用。您可以使用以下方式验证其位置which命令:

  1. which caddy

您将看到以下输出:

其中的输出
/home/sammy/work/bin/caddy

现在你明白了如何go get, go build, and go install工作以及它们之间的关系,让我们探讨一下最流行的 Go 功能之一:为其他目标平台创建可执行文件。

第 4 步 — 为不同架构构建可执行文件

The go build命令可让您为任何 Go 支持的目标平台构建可执行文件,在您的平台上。这意味着您可以测试、发布和分发您的应用程序,而无需在您希望使用的目标平台上构建这些可执行文件。

交叉编译通过设置指定目标操作系统和体系结构所需的环境变量来进行。我们使用变量GOOS对于目标操作系统,以及GOARCH对于目标架构。要构建可执行文件,命令将采用以下形式:

  1. env GOOS=target-OS GOARCH=target-architecture go build package-import-path

The env命令在修改后的环境中运行程序。这允许您仅将环境变量用于当前命令执行。命令执行后,变量将被取消设置或重置。

下表显示了可能的组合GOOS and GOARCH您可以使用:

GOOS - Target Operating System GOARCH - Target Platform
android arm
darwin 386
darwin amd64
darwin arm
darwin arm64
dragonfly amd64
freebsd 386
freebsd amd64
freebsd arm
linux 386
linux amd64
linux arm
linux arm64
linux ppc64
linux ppc64le
linux mips
linux mipsle
linux mips64
linux mips64le
netbsd 386
netbsd amd64
netbsd arm
openbsd 386
openbsd amd64
openbsd arm
plan9 386
plan9 amd64
solaris amd64
windows 386
windows amd64

Warning:Android 交叉编译可执行文件需要安卓NDK以及一些超出本教程范围的附加设置。

使用表中的值,我们可以像这样构建适用于 Windows 64 位的 Caddy:

  1. env GOOS=windows GOARCH=amd64 go build github.com/mholt/caddy/caddy

再次没有输出表明操作成功。可执行文件将在当前目录中创建,使用包名称作为其名称。但是,由于我们为 Windows 构建了此可执行文件,因此名称以后缀结尾.exe.

你应该有caddy.exe文件位于当前目录中,您可以使用ls命令。

  1. ls球童程序

你会看到caddy.exe输出中列出的文件:

Output
caddy.exe

Note: 您可以使用-o标志来重命名可执行文件或将其放置在不同的位置。但是,在为 Windows 构建可执行文件并提供不同的名称时,请务必明确指定.exe设置可执行文件名称时的后缀。

让我们看一下编写此过程的脚本,以便更轻松地为多个目标环境发布软件。

第 5 步 — 创建脚本以自动交叉编译

为许多平台创建可执行文件的过程可能有点乏味,但我们可以创建一个脚本来使事情变得更容易。

该脚本将以包导入路径作为参数,迭代操作系统和平台对的预定义列表,并为每对生成一个可执行文件,并将输出放置在当前目录中。每个可执行文件都将以包名称命名,后跟目标平台和体系结构,格式如下package-OS-architecture。这将是一个可以在任何项目上使用的通用脚本。

切换到您的主目录并创建一个名为的新文件go-executable-build.bash在你的文本编辑器中:

  1. cd ~
  2. nano go-executable-build.bash

我们将以shebang线。此行定义当脚本作为可执行文件运行时哪个解释器将解析该脚本。添加以下行来指定bash 应该执行这个脚本:

go-可执行文件-build.bash
#!/usr/bin/env bash

We want to take the package import path as a command line argument. To do this, we will use $n variable, where n is a non-negative number. The variable $0 contains the name of the script you executed, while $1 and greater will contain user-provided arguments. Add this line to the script, which will take the first argument from the command line and store it in a variable called package:

go-可执行文件-build.bash
...
package=$1

接下来,确保用户提供了该值。如果未提供该值,则退出脚本并显示一条消息解释如何使用该脚本:

go-可执行文件-build.bash
...

if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi

This if语句检查的值$package多变的。如果没有设置,我们使用echo打印正确的用法,然后使用终止脚本exit. exit接受一个返回值作为参数,它应该是0对于成功执行,任何非零值对于不成功执行。我们用1因为脚本没有成功。

Note:如果您想让此脚本与预定义的包一起使用,请更改package变量指向该导入路径:

go-可执行文件-build.bash
...
package="github.com/user/hello"

接下来,我们要从路径中提取包名称。包导入路径由以下分隔/字符,包名称位于路径末尾。首先,我们将包导入路径拆分为一个数组,使用/作为分隔符:

go-可执行文件-build.bash
package_split=(${package//\// })

包名称应该是这个新的最后一个元素$package_split大批。在 Bash 中,您可以使用负数组索引从末尾而不是开头访问数组。添加此行以从数组中获取包名称并将其存储在名为的变量中package_name:

go-可执行文件-build.bash
...
package_name=${package_split[-1]}

Now, you’ll need to decide what platforms and architectures you want build executables for. In this tutorial, we’ll build executables for Windows 64-bit, Windows 32-bit, and 64-bit macOS. We will put these targets in an array with the format OS/Platform, so we can split each pair into GOOS and GOARCH variables using the same method we used to extract the package name from the path. Add the platforms to the script:

go-可执行文件-build.bash
...
platforms=("windows/amd64" "windows/386" "darwin/amd64")

接下来,我们将迭代平台数组,将每个平台条目拆分为GOOS and GOARCH环境变量,并使用它们来构建可执行文件。我们可以通过以下方式做到这一点for loop:

go-可执行文件-build.bash
...
for platform in "${platforms[@]}"
do
	...
done

The platform变量将包含来自platforms每次迭代中的数组。我们需要分开platform到两个变量 -GOOS and GOARCH。将以下行添加到for loop:

go-可执行文件-build.bash
for platform in "${platforms[@]}"
do
	platform_split=(${platform//\// })
	GOOS=${platform_split[0]}
	GOARCH=${platform_split[1]}
	
done

接下来,我们将通过将包名称与操作系统和体系结构相结合来生成可执行文件的名称。当我们为 Windows 构建时,我们还需要添加.exe文件名的后缀。将此代码添加到for loop:

go-可执行文件-build.bash
for platform in "${platforms[@]}"
do
	platform_split=(${platform//\// })
	GOOS=${platform_split[0]}
	GOARCH=${platform_split[1]}
	
    output_name=$package_name'-'$GOOS'-'$GOARCH

	if [ $GOOS = "windows" ]; then
		output_name+='.exe'
	fi
done

设置变量后,我们使用go build创建可执行文件。将此行添加到正文中for循环,就在done关键词:

go-可执行文件-build.bash
...
	if [ $GOOS = "windows" ]; then
		output_name+='.exe'
	fi
	
	env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package

done

最后,我们应该检查构建可执行文件是否存在错误。例如,如果我们尝试构建一个没有源代码的包,我们可能会遇到错误。我们可以检查go build命令的返回代码为非零值。变量$?包含前一个命令执行的返回代码。如果go build返回除0,出现了问题,我们想要退出脚本。将此代码添加到for循环,之后go build命令和上面的done关键词。

go-可执行文件-build.bash

...

	env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package

	if [ $? -ne 0 ]; then
   		echo 'An error has occurred! Aborting the script execution...'
		exit 1
	fi

这样,我们现在就有了一个脚本,可以从 Go 包构建多个可执行文件。这是完成的脚本:

go-可执行文件-build.bash

#!/usr/bin/env bash

package=$1
if [[ -z "$package" ]]; then
  echo "usage: $0 <package-name>"
  exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}
	
platforms=("windows/amd64" "windows/386" "darwin/amd64")

for platform in "${platforms[@]}"
do
	platform_split=(${platform//\// })
	GOOS=${platform_split[0]}
	GOARCH=${platform_split[1]}
	output_name=$package_name'-'$GOOS'-'$GOARCH
	if [ $GOOS = "windows" ]; then
		output_name+='.exe'
	fi	

	env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
	if [ $? -ne 0 ]; then
   		echo 'An error has occurred! Aborting the script execution...'
		exit 1
	fi
done

验证您的文件是否与前面的代码匹配。然后保存文件并退出编辑器。

在使用该脚本之前,我们必须使用以下命令使其可执行chmod命令:

  1. chmod +x go-executable-build.bash

最后,通过为 Caddy 构建可执行文件来测试脚本:

  1. ./go-executable-build.bash github.com/mholt/caddy/caddy

如果一切顺利,您的当前目录中应该有可执行文件。没有输出表明脚本执行成功。您可以验证是否使用创建的可执行文件ls命令:

  1. ls caddy*

您应该看到所有三个版本:

ls 输出示例
caddy-darwin-amd64 caddy-windows-386.exe caddy-windows-amd64.exe

要更改目标平台,只需更改platforms脚本中的变量。

结论

在本教程中,您学习了如何使用 Go 的工具从版本控制系统获取包,以及如何为不同平台构建和交叉编译可执行文件。

您还创建了一个脚本,可用于为多个平台交叉编译单个包。

为了确保您的应用程序正常工作,您可以查看testing and 持续集成 like 特拉维斯-CI and AppVeyor用于在 Windows 上进行测试。

如果您对 Caddy 及其使用方法感兴趣,请查看如何在 Ubuntu 16.04 上使用 Caddy 托管网站.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Ubuntu 16.04 上为多个平台构建 Go 可执行文件 的相关文章

随机推荐

  • Java线程等待、通知和notifyAll示例

    java中的Object类包含三个final方法 允许线程就资源的锁定状态进行通信 这些方法是wait notify and 通知全部 那么今天我们就来研究一下java程序中的wait notify和notifyAll Java中的等待 通
  • Systemd 要点:使用服务、单位和期刊

    介绍 近年来 Linux 发行版越来越多地从其他 init 系统过渡到systemd The systemd工具套件提供了快速灵活的初始化模型 用于从启动开始管理整个机器 在本指南中 我们将向您快速介绍您在管理应用程序时需要了解的最重要的命
  • Primefaces FileUpload 组件示例教程

    今天我们将研究 Primefaces FileUpload 组件 HTML 为您提供file输入标签来选择文件 但是我们需要更多信息才能将文件上传到服务器 Primefaces 为您提供现成的解决方案 消除了这种负担文件上传组件帮助您创建漂
  • 如何在 CentOS 7 上为 Nginx 创建自签名 SSL 证书

    介绍 TLS 或传输层安全 及其前身SSL代表安全套接字层 是用于将正常流量包装在受保护的加密包装器中的 Web 协议 使用此技术 服务器可以在服务器和客户端之间安全地发送流量 而不会出现消息被外部各方拦截的可能性 证书系统还帮助用户验证他
  • 如何在 Angular Material 中使用自定义 SVG 图标

    介绍 The 角材料库提供了一套采用 Material Design 风格的 Angular 组件 其中一个这样的组件是
  • 如何在 Ubuntu 12.04 上安装 MongoDB

    Status 已弃用 本文介绍不再受支持的 Ubuntu 版本 如果您当前运行的服务器运行 Ubuntu 12 04 我们强烈建议您升级或迁移到受支持的 Ubuntu 版本 升级到Ubuntu 14 04 从 Ubuntu 14 04 升级
  • React Router v6 抢先体验

    在撰写本文时 React Router v6 仍处于 alpha 阶段 但现在是时候开始使用它并探索未来的发展了 本指南将带您了解新功能 变化 如您所知 主要维护者分叉了反应路由器项目创建一个轻量级替代品 称为到达路由器2018年初 在此期
  • 在 Linux 中减小 PDF 文件大小

    在我们的 Linux 系统中 如果我们有一个很大的 PDF 文件 我们可能想减小它的大小 在本教程中 我们将了解在 Linux 中减小 PDF 大小或压缩 PDF 文件的不同方法 让我们找出一些命令行和 GUI 方法来处理这个问题 在 Li
  • 如何在 FreeBSD 10.1 上安装 Apache、MySQL 和 PHP (FAMP) 堆栈

    介绍 FAMP 堆栈类似于 Linux 上的 LAMP 堆栈 是一组开源软件 通常安装在一起以使 FreeBSD 服务器能够托管动态网站和 Web 应用程序 FAMP 是首字母缩略词 代表FfreeBSD 操作系统 A阿帕奇 网络服务器 M
  • 如何使用 JSON.parse() 和 JSON.stringify()

    介绍 The JSON object在所有现代浏览器中都可用 有两种有用的方法来处理 JSON 格式的内容 parse and stringify JSON parse JSON parse 获取 JSON 字符串并将其转换为 JavaSc
  • C++ 中的字符串连接:连接字符串的 4 种方法

    在本文中 我们将揭示在中执行字符串连接的各种方法C 语言 该方法在编程时可用于多种目的 但总的来说 这个概念与组合来自不同位置的两个字符串并将它们放在一起是相同的 C 中的字符串连接技术 在 C 中连接字符串时可以考虑以下技术 C 连接 运
  • 如何在 CentOS 7 上安装和使用 PostgreSQL

    介绍 关系数据库管理系统是许多网站和应用程序的关键组件 它们提供了一种结构化的方式来存储 组织和访问信息 PostgreSQLPostgres 或 Postgres 是一个关系数据库管理系统 提供 SQL 查询语言的实现 它是许多小型和大型
  • 如何在 VPS 上使用 Nginx 设置 FastCGI 缓存

    Prelude Nginx 包含一个 FastCGI 模块 该模块具有用于缓存 PHP 后端提供的动态内容的指令 设置此功能无需额外的页面缓存解决方案 例如反向代理 想想Varnish 或特定于应用程序的插件 还可以根据请求方法 URL c
  • DNS 术语、组件和概念简介

    介绍 DNS 即域名系统 通常是学习如何配置网站和服务器的一个非常困难的部分 了解 DNS 的工作原理将帮助您诊断配置网站访问的问题 并让您更深入地了解幕后发生的事情 在本指南中 我们将讨论一些基本的 DNS 概念 这些概念将帮助您开始使用
  • Web 服务面试问题 - SOAP、RESTful

    欢迎来到 Web 服务面试问题及其详细答案 最近我写了很多关于 Web 服务的文章 我们如何用 Java 创建 SOAP 和 RESTful Web 服务 Web 服务面试问题 Here I am providing you a list
  • 如何在 CentOS 6 上使用 Logstash 和 Kibana 集中日志

    状态 已弃用 本文介绍不再受支持的 CentOS 版本 如果您当前运行的服务器运行 CentOS 6 我们强烈建议您升级或迁移到受支持的 CentOS 版本 Reason CentOS 6 于 2020 年 11 月 30 日达到生命周期终
  • Java 是按值传递,而不是按引用传递

    介绍 许多 Java 程序员质疑 Java 是否按值传递 or 通过引用传递 本文总结了为什么 Java 总是按值传递 首先 按值传递和按引用传递是什么意思 按值传递 将方法参数值复制到另一个变量 然后将复制的对象传递给方法 该方法使用副本
  • 如何在 Angular 中使用 Chart.js 和 ng2-charts

    介绍 Chart js是一个流行的 JavaScript 图表库ng2 charts是 Angular 2 的包装器 用于将 Chart js 集成到 Angular 中 在本教程中 您将使用 Chart js 和ng2 charts在 A
  • 将 CSV 文件读入 R 中的数据帧

    借助 R 提供的特定函数 将 CSV 文件读入数据帧要容易得多 什么是 CSV 文件 CSV 扩展为逗号 分隔 值 在此文件中 存储的值用逗号分隔 存储数据的过程要容易得多 为什么 CSV 是最常用的数据存储文件格式 将数据存储在 Exce
  • 如何在 Ubuntu 16.04 上为多个平台构建 Go 可执行文件

    介绍 The Go编程语言附带丰富的工具链 使获取包和构建可执行文件变得异常容易 Go 最强大的功能之一是能够为任何 Go 支持的外部平台交叉构建可执行文件 这使得测试和包分发变得更加容易 因为您不需要访问特定平台即可为其分发包 在本教程中