The Go编程语言附带丰富的工具链,使获取包和构建可执行文件变得异常容易。 Go 最强大的功能之一是能够为任何 Go 支持的外部平台交叉构建可执行文件。这使得测试和包分发变得更加容易,因为您不需要访问特定平台即可为其分发包。
在本教程中,您将使用 Go 的工具从版本控制中获取包并自动安装其可执行文件。然后,您将手动构建并安装可执行文件,以便熟悉该过程。然后,您将为不同的体系结构构建可执行文件,并自动执行构建过程来为多个平台创建可执行文件。完成后,您将了解如何为 Windows 和 macOS 以及您想要支持的其他平台构建可执行文件。
要学习本教程,您将需要:
- 通过以下方式设置一台 Ubuntu 16.04 服务器Ubuntu 16.04 初始服务器设置指南,包括 sudo 非 root 用户和防火墙。
- 去安装,如所述如何在 Ubuntu 16.04 上安装 Go 1.6.
在从 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:
- go get -ugithub.com/mholt/caddy/caddy
该命令将需要一些时间才能完成,但在它获取包并安装它时您不会看到任何进度。没有输出实际上表明命令执行成功。
命令完成后,您将在以下位置找到 Caddy 的源代码:$GOPATH/src/github.com/mholt/caddy
。此外,由于 Caddy 有一个可执行文件,因此它会自动创建并存储在$GOPATH/bin
目录。通过使用验证这一点which
打印可执行文件的位置:
您将看到以下输出:
Output
/home/sammy/work/bin/caddy
Note: The go get
命令从 Git 存储库的默认分支安装包,在许多情况下是master
,或正在开发的分支。确保查看说明,通常位于存储库的README
文件,在使用之前go get
.
您可以使用 Git 命令,例如git checkout
在使用获得的源上选择不同的分支go get
命令。查看教程如何使用 Git 分支了解有关如何切换分支的更多信息。
让我们更详细地看看安装 Go 包的过程,首先从我们已经获得的包创建可执行文件。
The go get
命令下载了源代码并通过单个命令为我们安装了 Caddy 的可执行文件。但是您可能想自己重建可执行文件,或者从您自己的代码构建可执行文件。这go build
命令构建可执行文件。
虽然我们已经安装了 Caddy,但让我们再次手动构建它,这样我们就可以熟悉这个过程。执行go build
并指定包导入路径:
- 去构建 github.com/mholt/caddy/caddy
和之前一样,没有输出表明操作成功。可执行文件将在您的当前目录中生成,其名称与包含包的目录相同。在这种情况下,可执行文件将被命名为caddy
.
如果您位于包目录中,则可以省略包的路径并只需运行go build
.
要为可执行文件指定不同的名称或位置,请使用-o
旗帜。让我们构建一个名为的可执行文件caddy-server
并将其放在一个build
当前工作目录中的目录:
- 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.
现在让我们看看安装可执行文件。
构建可执行文件会在当前目录或您选择的目录中创建可执行文件。安装可执行文件是创建可执行文件并将其存储在$GOPATH/bin
. The go install
命令的工作方式就像go build
, but go install
负责将输出文件放置在适合您的位置。
要安装可执行文件,请使用go install
,后跟包导入路径。再次使用 Caddy 来尝试一下:
- go installgithub.com/mholt/caddy/caddy
就像与go build
,如果命令成功,您将看不到任何输出。和以前一样,创建的可执行文件的名称与包含包的目录的名称相同。但这一次,可执行文件存储在$GOPATH/bin
. If $GOPATH/bin
是你的一部分$PATH
环境变量,可执行文件可以从操作系统上的任何位置使用。您可以使用以下方式验证其位置which
命令:
您将看到以下输出:
其中的输出
/home/sammy/work/bin/caddy
现在你明白了如何go get
, go build
, and go install
工作以及它们之间的关系,让我们探讨一下最流行的 Go 功能之一:为其他目标平台创建可执行文件。
The go build
命令可让您为任何 Go 支持的目标平台构建可执行文件,在您的平台上。这意味着您可以测试、发布和分发您的应用程序,而无需在您希望使用的目标平台上构建这些可执行文件。
交叉编译通过设置指定目标操作系统和体系结构所需的环境变量来进行。我们使用变量GOOS
对于目标操作系统,以及GOARCH
对于目标架构。要构建可执行文件,命令将采用以下形式:
-
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:
-
env GOOS=windows GOARCH=amd64 go build github.com/mholt/caddy/caddy
再次没有输出表明操作成功。可执行文件将在当前目录中创建,使用包名称作为其名称。但是,由于我们为 Windows 构建了此可执行文件,因此名称以后缀结尾.exe
.
你应该有caddy.exe
文件位于当前目录中,您可以使用ls
命令。
你会看到caddy.exe
输出中列出的文件:
Output
caddy.exe
Note: 您可以使用-o
标志来重命名可执行文件或将其放置在不同的位置。但是,在为 Windows 构建可执行文件并提供不同的名称时,请务必明确指定.exe
设置可执行文件名称时的后缀。
让我们看一下编写此过程的脚本,以便更轻松地为多个目标环境发布软件。
为许多平台创建可执行文件的过程可能有点乏味,但我们可以创建一个脚本来使事情变得更容易。
该脚本将以包导入路径作为参数,迭代操作系统和平台对的预定义列表,并为每对生成一个可执行文件,并将输出放置在当前目录中。每个可执行文件都将以包名称命名,后跟目标平台和体系结构,格式如下package-OS-architecture
。这将是一个可以在任何项目上使用的通用脚本。
切换到您的主目录并创建一个名为的新文件go-executable-build.bash
在你的文本编辑器中:
-
cd ~
-
nano go-executable-build.bash
我们将以shebang线。此行定义当脚本作为可执行文件运行时哪个解释器将解析该脚本。添加以下行来指定bash
应该执行这个脚本:
go-可执行文件-build.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
接下来,确保用户提供了该值。如果未提供该值,则退出脚本并显示一条消息解释如何使用该脚本:
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
命令:
-
chmod +x go-executable-build.bash
最后,通过为 Caddy 构建可执行文件来测试脚本:
- ./go-executable-build.bash github.com/mholt/caddy/caddy
如果一切顺利,您的当前目录中应该有可执行文件。没有输出表明脚本执行成功。您可以验证是否使用创建的可执行文件ls
命令:
您应该看到所有三个版本:
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 托管网站.