介绍
该 Go 编程语言配备了丰富的工具链,使获取包和构建可执行功能非常容易。 Go 最强大的功能之一是能够为任何 Go 支持的外部平台交叉构建可执行功能。这使得测试和包分发变得更容易,因为您不需要访问特定平台才能为其分发您的包。
在本教程中,您将使用Go的工具从版本控制中获取一个包,并自动安装其可执行的程序,然后您将手动构建和安装可执行的程序,以便您熟悉该过程。
前提条件
要遵循本教程,您将需要:
- 一个 Ubuntu 20.04 服务器由以下设置(https://andsky.com/tech/tutorials/initial-server-setup-with-ubuntu-20-04),包括一个 sudo 非根用户和防火墙。
步骤1 - 创建一个简单的Go程序
现在安装了 Go,您可以尝试创建您的你好,世界!
。
首先,为您的 Go 工作区创建一个新目录,这就是 Go 将其文件构建的地方:
1mkdir hello
然后进入您刚刚创建的目录:
1cd hello
导入包时,您必须通过代码的自身模块来管理依赖性,您可以通过使用go mod init
命令创建一个go.mod
文件来做到这一点:
1go mod init hello
接下来,在您喜爱的文本编辑器中创建一个Hello, World!
Go文件:
1nano hello.go
将以下文本添加到您的hello.go
文件中:
1[label hello.go]
2package main
3
4import "fmt"
5
6func main() {
7 fmt.Println("Hello, World!")
8}
然后,通过按CTRL+X
,然后按Y
,然后按ENTER
来保存和关闭文件。
测试您的代码,检查它是否打印了你好,世界!
的问候:
1go run .
1[secondary_label Output]
2Hello, World!
go run
命令编译并从您创建的新hello
目录和您导入的路径的.go
源文件列表中运行Go包,但您也可以使用go build
创建可执行的文件,从而节省您一些时间。
步骤 2 — 构建一个可执行的
Go Run
命令为您的Hello World!
程序运行了代码,但您可能希望将您的程序构建成二进制来在您的系统上运行,而不仅仅是从源头。
1go build hello
如前所述,没有输出表示成功操作. 可执行的将生成在当前目录中,与包含包的目录相同的名称。
如果您位于包目录中,您可以跳过通往包的路径,然后简单地运行去构建
。
要指定可执行的不同的名称或位置,请使用-o
旗帜. 让我们构建一个名为hello
的可执行,并将其放置在当前工作目录中的构建
目录中:
1go build -o build/hello hello
此命令会创建可执行的文件,并在不存在的情况下创建 `./build’ 目录。
现在让我们来看看安装 executables。
步骤 3 — 安装一个可执行的
构建可执行文件会在当前目录或您选择的目录中创建可执行文件. 安装可执行文件是创建可执行文件并将其存储在$GOPATH/bin
中。
要安装一个可执行的,请使用去安装
,然后使用包导入路径. 再一次,请使用您的Hello, World!
程序来尝试:
1go install hello
就像「Go build」一樣,如果命令成功的話,你將不會看到任何輸出。 和以前一樣,執行程式的名稱與包含包的目錄相同,但這次執行程式儲存在「$GOPATH/bin」。 如果「$GOPATH/bin」是您的「$PATH」環境變量的一部分,執行程式將可在您的作業系統上任何地方使用。 您可以使用「哪個」命令來驗證其位置:
1which hello
您将看到以下输出:
1[secondary_label Output of which]
2/home/sammy/go/bin/hello
现在,你已经了解了go get
,go build
和go install
是如何工作的,以及它们是如何相关的,让我们探索最流行的Go功能之一:为其他目标平台创建可执行的功能。
步骤4 - 构建不同架构的执行程序
Go build
命令允许您在您的平台上为任何 Go 支持的目标平台构建可执行文件,这意味着您可以测试,发布和分发您的应用程序,而不会在您想要使用的目标平台上构建这些可执行文件。
通过设置指定目标操作系统和架构的所需环境变量来进行交叉编译,我们使用目标操作系统的变量GOOS
,目标架构的变量GOARCH
。
1GOOS=target-OS GOARCH=target-architecture go build package-import-path
操作系统和架构在运行go build
命令之前设置,这允许您仅使用当前命令执行的环境变量。
为了了解哪些操作系统和平台可用于构建可执行的,您可以使用dist
工具:
1go tool dist list
这将为您提供由 /
字符分开的操作系统和架构列表:
1[secondary_label Output]
2aix/ppc64
3android/386
4android/amd64
5android/arm
6android/arm64
7darwin/amd64
8darwin/arm64
9dragonfly/amd64
10freebsd/386
11freebsd/amd64
12freebsd/arm
13freebsd/arm64
14illumos/amd64
15ios/amd64
16ios/arm64
17js/wasm
18linux/386
19linux/amd64
20linux/arm
21linux/arm64
22linux/mips
23linux/mips64
24linux/mips64le
25linux/mipsle
26linux/ppc64
27linux/ppc64le
28linux/riscv64
29linux/s390x
30netbsd/386
31netbsd/amd64
32netbsd/arm
33netbsd/arm64
34openbsd/386
35openbsd/amd64
36openbsd/arm
37openbsd/arm64
38openbsd/mips64
39plan9/386
40plan9/amd64
41plan9/arm
42solaris/amd64
43windows/386
44windows/amd64
45windows/arm
金钱(警告)
警告: 跨编译的执行程序 Android 需要 Android NDK,和一些额外的设置,这是超出本教程的范围。
美元
使用列表中的值,我们可以像这样构建 64 位 Windows 的 Hello:
1GOOS=windows GOARCH=amd64 go build hello
再一次,没有输出表明操作是成功的。执行将创建在当前目录中,使用包名称作为其名称。
您应该在当前目录中有hello.exe
文件,您可以使用ls
命令验证。
1ls hello.exe
您将看到输出中列出的 hello.exe
文件:
1[secondary_label Output]
2hello.exe
<$>[注] 注 :您可以使用 -o
标志重新命名可执行的文件,或将其放置在不同的位置,但是,在为 Windows 构建可执行的文件并提供不同的名称时,请确保在设置可执行的名称时明确指定 .exe
suffix。
让我们来看看这个过程的脚本,以便更容易为多个目标环境发布软件。
步骤5 — 创建一个自动交叉编译的脚本
为许多平台创建可执行程序的过程可能有点无聊,但我们可以创建一个脚本来使事情变得更容易。
该脚本将采用包导入路径作为一个参数,通过预定义的操作系统和平台对列表迭代,并为每个对生成一个可执行的,将输出放置到当前目录中。
在项目目录中,在文本编辑器中创建一个名为go-executable-build.bash
的新文件:
1nano go-executable-build.bash
我们将以 shebang 行开始我们的脚本. 该行定义了哪个解释器在作为可执行程序运行时将该脚本解析。
1[label go-executable-build.bash]
2#!/usr/bin/env bash
要做到这一点,我们将使用$n
变量,其中n
是一个非负数。$0
变量包含你执行的脚本的名称,而$1
和更大将包含用户提供的参数。
1[label go-executable-build.bash]
2...
3package=$1
接下来,请确保用户提供此值. 如果没有提供该值,请离开脚本,并发出说明如何使用脚本的消息:
1[label go-executable-build.bash]
2...
3
4if [[ -z "$package" ]]; then
5 echo "usage: $0 <package-name>"
6 exit 1
7fi
此如果
语句检查了$package
变量的值。如果没有设置,我们会使用echo
来打印正确的使用,然后使用exit
终止脚本。
美元(注)
注意 :如果您想让此脚本与预定义的包一起工作,请更改包
变量以指向该导入路径:
1[label go-executable-build.bash]
2...
3package="github.com/user/hello"
美元
接下来,我们要从路径中提取包的名称。包的导入路径由 /
字符划分,而包的名称位于路径的尽头。
1[label go-executable-build.bash]
2package_split=(${package//\// })
该包名称应该是这个新的$package_split
数组的最后一个元素。在Bash中,您可以使用负数组索引从末端访问一个数组,而不是从开始。
1[label go-executable-build.bash]
2...
3package_name=${package_split[-1]}
在本教程中,我们将构建 64 位 Windows、32 位 Windows 和 64 位 macOS 的执行程序. 我们将将这些目标放置在一个组合中,格式为OS/Platform
,以便我们可以将每个对分为GOOS
和GOARCH
变量,使用相同的方法从路径中提取包名称。
1[label go-executable-build.bash]
2...
3platforms=("windows/amd64" "windows/386" "darwin/amd64")
接下来,我们将重复通过平台的数组,将每个平台输入分为GOOS
和GOARCH
环境变量的值,并使用这些来构建可执行的。
1[label go-executable-build.bash]
2...
3for platform in "${platforms[@]}"
4do
5 ...
6done
平台
变量将在每个迭代中包含一个平台
数组的输入,我们需要将平台
分为两个变量,即GOOS
和GOARCH
。
1[label go-executable-build.bash]
2for platform in "${platforms[@]}"
3do
4 platform_split=(${platform//\// })
5 GOOS=${platform_split[0]}
6 GOARCH=${platform_split[1]}
7
8done
接下来,我们将通过将包名称与操作系统和架构相结合来生成可执行的名称. 当我们为 Windows 构建时,我们还需要在文件名中添加.exe
字符串。
1[label go-executable-build.bash]
2for platform in "${platforms[@]}"
3do
4 platform_split=(${platform//\// })
5 GOOS=${platform_split[0]}
6 GOARCH=${platform_split[1]}
7
8 output_name=$package_name'-'$GOOS'-'$GOARCH
9
10 if [ $GOOS = "windows" ]; then
11 output_name+='.exe'
12 fi
13done
随着变量设置,我们使用go build
来创建可执行的行. 将此行添加到for
循环的体内,直接在完成
关键字上方:
1[label go-executable-build.bash]
2...
3 if [ $GOOS = "windows" ]; then
4 output_name+='.exe'
5 fi
6
7 env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
8
9done
最后,我们应检查一下是否存在可执行文件编制错误。 例如,如果我们试图构建一个我们没有来源的软件包,我们可能会遇到错误. 我们可以检查去建立
命令的返回代码是否为非零值。 变数"$"? 包含来自先前命令执行的返回代码。 如果去建设'返回除
0'以外的任何东西,就有一个问题,我们想退出剧本。 在去建立 ' 命令后,在
去建立 ' 关键词上方,将这个代码添加到 " for " 循环中.
1[label go-executable-build.bash]
2
3...
4
5 env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
6
7 if [ $? -ne 0 ]; then
8 echo 'An error has occurred! Aborting the script execution...'
9 exit 1
10 fi
有了这一点,我们现在有一个脚本,将从我们的Go包中构建多个执行程序。
1[label go-executable-build.bash]
2
3#!/usr/bin/env bash
4
5package=$1
6if [[ -z "$package" ]]; then
7 echo "usage: $0 <package-name>"
8 exit 1
9fi
10package_split=(${package//\// })
11package_name=${package_split[-1]}
12
13platforms=("windows/amd64" "windows/386" "darwin/amd64")
14
15for platform in "${platforms[@]}"
16do
17 platform_split=(${platform//\// })
18 GOOS=${platform_split[0]}
19 GOARCH=${platform_split[1]}
20 output_name=$package_name'-'$GOOS'-'$GOARCH
21 if [ $GOOS = "windows" ]; then
22 output_name+='.exe'
23 fi
24
25 env GOOS=$GOOS GOARCH=$GOARCH go build -o $output_name $package
26 if [ $? -ne 0 ]; then
27 echo 'An error has occurred! Aborting the script execution...'
28 exit 1
29 fi
30done
检查您的文件是否匹配前面的代码,然后保存文件并退出编辑器。
在我们可以使用脚本之前,我们必须用chmod
命令使其可执行:
1chmod +x go-executable-build.bash
最后,通过构建 hello 的执行程序来测试脚本:
1./go-executable-build.bash hello
如果一切顺利,你应该在当前的目录中有可执行的内容. 没有输出显示了成功的脚本执行情况. 你可以通过使用ls
命令来验证是否有可执行的内容:
1ls hello*
你应该看到这三个版本:
1[secondary_label Example ls output]
2hello-darwin-amd64 hello-windows-386.exe hello-windows-amd64.exe
要更改目标平台,只需在脚本中更改平台
变量。
结论
在本教程中,您已经学会了如何使用Go的工具来从版本控制系统中获取包,以及为不同的平台构建和交叉编译执行程序。
您还创建了一个脚本,您可以使用它来对多个平台进行单个包的交叉编译。
要确保您的应用程序正常工作,您可以查看 测试 和** 连续集成** 如 Travis-CI和 AppVeyor在 Windows 上进行测试。