Go模块教程
# 创建你的 Go 模块
这是教程的第一部分,介绍了 Go 语言的一些基本功能。如果你刚开始使用Go语言,一定要看一下教程:Go 入门,它介绍了 Go 命令、Go 模块和非常简单的 Go 代码。
在本教程中,您将创建两个模块。第一种是打算由其他库或应用程序导入的库。第二个是将使用第一个的调用方应用程序。
本教程的顺序包括七个简短的主题,每个主题都说明了语言的不同部分。
- 创建一个模块——编写一个小模块,其中包含可以从另一个模块调用的函数。
- 从另一个模块调用您的代码--导入并使用您的新模块。
- 返回并处理错误--添加简单的错误处理。
- 返回一个随机的 greetings——处理切片中的数据(Go 的动态大小数组)。
- 为多个人返回 greetings--将键/值对存储在映射中。
- 添加测试--使用 Go 内置的单元测试功能来测试代码。
- 编译并安装应用程序--在本地编译并安装代码。
注意: 有关其他课程, 参见 Go 语言中文文档.
# 学习准备
- 一些编程经验。这里的代码非常简单,但了解函数、循环和数组会有所帮助。
- 用于编辑代码的工具。您拥有的任何文本编辑器都可以正常工作。大多数文本编辑器都很好地支持 Go。最受欢迎的是 VSCode(免费)、GoLand(付费)和 Vim(免费)。
- 一个命令终端。Go 在 Linux 和 Mac 上以及 Windows 中的 PowerShell 或 cmd 上使用任何终端都能很好地工作。
# 开发一个其他人也能使用的模块
首先创建 Go 模块。在一个模块中,您可以为一组离散且有用的函数收集一个或多个相关的包。例如,您可以创建一个包含包的模块,这些包具有进行财务分析的功能,以便其他编写财务应用程序的人可以使用您的工作。有关开发模块的更多信息,请参阅开发和发布模块。
Go 代码被分组到包中,包被分组到模块中。您的模块指定运行代码所需的依赖项,包括 Go 版本及其所需的一组其他模块。
当您在模块中添加或改进功能时,您将发布模块的新版本。编写调用模块中函数的代码的开发人员可以导入模块的更新包,并在将其投入生产使用之前使用新版本进行测试。
- 打开一个命令提示符并 cd 到您的主目录。 在 Linux 或 Mac 上:
cd
在 Windows 上:
cd %HOMEPATH%
- 为 Go 模块的源代码创建一个主目录。
例如,在主目录中使用以下命令:
mkdir greetings
cd greetings
- 使用 go-mod-init 命令初始化模块。
运行 go-mod-init 命令,给它你的模块路径——在这里,使用 example.com/greetings。如果你发布了一个模块,这必须是 go 工具可以下载你的模块的路径。那将是您的代码存储库。
$ go mod init example.com/greetings
go: creating new go.mod: module example.com/greetings
go-mod-init 命令创建一个 go.mod 文件来跟踪代码的依赖关系。到目前为止,该文件只包括模块的名称和代码支持的 Go 版本。但当你添加依赖项时,go.mod 文件会列出你的代码所依赖的版本。这可以保持构建的可复制性,并让你直接控制要使用的模块版本。
- 在文本编辑器中,创建一个用于编写代码的文件,并将其命名为 greetings.go。
- 将以下代码粘贴到 greetings.go 文件中并保存该文件。
package greetings
import "fmt"
// Hello returns a greeting for the named person.
func Hello(name string) string {
// Return a greeting that embeds the name in a message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
这是您的第一份模块代码。它会向任何需要问候的来访者返回 greetings。您将在下一步中编写调用此函数的代码。
在此代码中,您:
- 声明一个 greetings 包以容纳相关函数。
- 实现 Hello 函数以返回 greetings。
- 此函数接受一个类型为字符串的名称参数。该函数还返回一个字符串。在 Go 中,名称以大写字母开头的函数可以由不在同一个包中的函数调用。这在 Go 中被称为导出名称。有关导出名称的详细信息,请参阅 Go tour 中的导出名称。
- 声明一个消息变量来保存您的 greetings。 在 Go 中,:=运算符是在一行中声明和初始化变量的快捷方式(Go 使用右侧的值来确定变量的类型)。从长远来看,你可能会这样写:
var message string
message = fmt.Sprintf("Hi, %v. Welcome!", name)
*使用fmt包的Sprintf函数可以创建一条问候消息。第一个参数是一个格式字符串,Sprintf将name参数的值替换为%v格式谓词。插入name参数的值将完成greetings文本。 * 将格式化的greetings文本返回给呼叫者。
下一课,您将从另一个模块调用此函数。
# 从其他模块中调用你的代码
在上一节中,您创建了一个 grteeings 模块。在本节中,您将编写代码来调用刚刚编写的模块中的 Hello 函数。您将编写可以作为应用程序执行的代码,并调用 grteeings 模块中的代码。
注意:本主题是从创建 Go 模块开始的多部分教程的一部分。
- 为 Go 模块的源代码创建一个 hello 目录。
创建此目录后,您应该在层次结构的同一级别同时拥有 hello 和 greetings 目录,如下所示:
<home>/
|-- greetings/
|-- hello/
例如,如果命令提示符位于 greetings 目录中,则可以使用以下命令:
cd ..
mkdir hello
cd hello
- 为即将编写的代码启用依赖项跟踪。 要为代码启用依赖项跟踪,请运行 go-mod-init 命令,为其提供代码所在模块的名称。
出于本教程的目的,请使用 example.com/hello 作为模块路径。
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
- 在文本编辑器的 hello 目录中,创建一个用于编写代码的文件,并将其命名为 hello.go。
- 编写代码调用 Hello 函数,然后打印函数的返回值。 要做到这一点,请将以下代码粘贴到 hello.go 中。
package main
import (
"fmt"
"example.com/greetings"
)
func main() {
// Get a greeting message and print it.
message := greetings.Hello("Gladys")
fmt.Println(message)
}
在此代码中,您:
- 声明一个主程序包。在 Go 中,作为应用程序执行的代码必须在主包中。
- 导入两个包:example.com/greetings 和 fmt 包。这使您的代码可以访问这些包中的函数。导入 example.com/greetings(包含在您之前创建的模块中的包)可以访问 Hello 函数。您还可以导入 fmt,它具有处理输入和输出文本的功能(例如将文本打印到控制台)。
- 通过调用问候软件包的 Hello 功能来获得返回的 greetings。
- 编辑 example.com/hello 模块以使用您本地的 example.com/hellos 模块。
对于生产使用,您可以从其存储库中发布 example.com/helles 模块(带有反映其发布位置的模块路径),Go 工具可以在那里找到它来下载。目前,由于您尚未发布该模块,您需要调整 example.com/hello 模块,以便它可以在本地文件系统中找到 example.com/hellos 代码。
要做到这一点,请使用 go mod edit 命令编辑 example.com/hello 模块,将 go 工具从其模块路径(模块不在的地方)重定向到本地目录(模块所在的地方)。
- 在 hello 目录中的命令提示符下,运行以下命令:
go mod edit -replace example.com/greetings=../greetings
该命令指定 example.com/greetings 应替换为../greetings,用于查找依赖项。运行该命令后,hello 目录中的 go.mod 文件应包含一个 replace 指令:
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
- 在 hello 目录中的命令提示符下,运行 go mod 整洁命令来同步 example.com/hello 模块的依赖项,添加代码所需但尚未在模块中跟踪的依赖项。
go mod tidy
go: found example.com/greetings in example.com/greetings v0.0.0-00010101000000-000000000000
命令完成后,example.com/hello 模块的 go.mod 文件应该如下所示:
module example.com/hello
go 1.16
replace example.com/greetings => ../greetings
require example.com/greetings v0.0.0-00010101000000-000000000000
该命令在 greetings 目录中找到了本地代码,然后添加了一个 require 指令,指定 example.com/hello 需要 example.com/greetings。您在 hello.go 中导入 greetings 包时创建了此依赖项。
模块路径后面的数字是一个伪版本号——一个生成的数字,用来代替语义版本号(模块还没有)。
要引用已发布的模块,go.mod 文件通常会省略 replace 指令,并使用末尾带有标记版本号的 require 指令。
require example.com/greetings v1.1.0
有关版本号的更多信息,请参阅模块版本号 (opens new window)。
- 在 hello 目录中的命令提示符下,运行您的代码以确认它是否工作。
$ go run .
Hi, Gladys. Welcome!
恭喜!您已经编写了两个功能模块。
在下一个主题中,您将添加一些错误处理。
# 返回与错误处理
处理错误是实体代码的一个基本特征。在本节中,您将添加一些代码,从 greetings 模块返回一个错误,然后在调用者中进行处理。
注意:本主题是从创建 Go 模块开始的多部分教程的一部分。
- 在 greetings/greetings.go 中,添加下面突出显示的代码。
如果你不知道该向谁打招呼,那么问候是没有意义的。如果名称为空,则向调用方返回一个错误。将以下代码复制到 greetings.go 中并保存该文件。
package greetings
import (
"errors"
"fmt"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return "", errors.New("empty name")
}
// If a name was received, return a value that embeds the name
// in a greeting message.
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
在此代码中,您:
- 更改函数,使其返回两个值:一个字符串和一个错误。您的调用者将检查第二个值以查看是否发生错误。(任何 Go 函数都可以返回多个值。有关详细信息,请参阅Effective Go. (opens new window)。)
- 导入 Go 标准库错误包,以便您可以使用其 errors.New 函数。
- 添加 if 语句以检查无效请求(名称应为空字符串),如果请求无效则返回错误。errors.New 函数返回一个错误,其中包含您的消息。
- 在成功返回中添加 nil(表示没有错误)作为第二个值。这样,调用者就可以看到函数成功了。
- 在 hello/hello.go 文件中,处理 hello 函数现在返回的错误以及非错误值。
将以下代码粘贴到 hello.go 中。
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Request a greeting message.
message, err := greetings.Hello("")
// If an error was returned, print it to the console and
// exit the program.
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned message
// to the console.
fmt.Println(message)
}
在此代码中,您:
- 将 log 日志包配置为在其日志消息的开头打印命令名(“问候语:”),不带时间戳或源文件信息。
- 将两个 Hello 返回值(包括错误)分配给变量。
- 将 Hello 参数从 Gladys 的名称更改为空字符串,这样您就可以尝试错误处理代码。
- 查找非零错误值。在这种情况下继续下去是没有意义的。
- 使用标准库的 log 包中的函数来输出错误信息。如果出现错误,则使用 log 日志包的 Fatal 函数打印错误并停止程序。
- 在 hello 目录的命令行中,运行 hello.go 以确认代码是否有效。
现在您传入了一个空名称,您将得到一个错误。
$ go run .
greetings: empty name
exit status 1
这是 Go 中常见的错误处理:将错误作为值返回,以便调用方可以检查它。
接下来,您将使用 Go 切片来返回随机选择的问候语。
# 返回随机问候语
在本节中,您将更改代码,使其不再每次返回一个问候语,而是返回几个预定义的问候语消息中的一个。
注意:本主题是从创建 Go 模块开始的多部分教程的一部分。
为此,您将使用 Go 切片类型。切片就像一个数组,只是它的大小随着添加和删除项目而动态变化。切片(Slice)是 Go 语言最有用的类型之一。
您将添加一个小片段来包含三条问候消息,然后让代码随机返回其中一条消息。有关切片(Slice)的更多信息,请参阅 Go 官方博客中的Go 切片 (opens new window)。
在 greetings/greetings.go 中,更改代码,使其看起来如下所示。
package greetings
import (
"errors"
"fmt"
"math/rand"
"time"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// init sets initial values for variables used in the function.
func init() {
rand.Seed(time.Now().UnixNano())
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return a randomly selected message format by specifying
// a random index for the slice of formats.
return formats[rand.Intn(len(formats))]
}
在此代码中,您:
- 添加一个 randomFormat 函数,该函数可为问候语返回随机选择的格式。请注意,randomFormat 以小写字母开头,使其只能由自己包中的代码访问(换句话说,它不导出)。
- 在 randomFormat 中,用三种消息格式声明一个 formats 切片。在声明切片时,可以省略括号中的大小,如下所示:[]字符串。这告诉 Go,片下面的数组大小可以动态更改。
- 使用 math/rand 包生成一个随机数,用于从切片中选择项目。
- 添加一个 init 函数,用当前时间为 rand 包设定种子。Go 在初始化全局变量后,在程序启动时自动执行 init 函数。有关 init 函数的更多信息,请参阅Effective Go (opens new window)。
- 在 Hello 中,调用 randomFormat 函数来获取要返回的消息的格式,然后将格式和名称值一起使用来创建消息。
- 像以前一样返回消息(或错误)。
- 在 hello/hello.go 中,更改代码,使其看起来如下所示。
您只是将 Gladys 的名字(或者其他名字,如果您愿意的话)作为参数添加到 Hello.go 中的 Hello 函数调用中。
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// Request a greeting message.
message, err := greetings.Hello("Gladys")
// If an error was returned, print it to the console and
// exit the program.
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned message
// to the console.
fmt.Println(message)
}
- 在 hello 目录的命令行中,运行 hello.go 以确认代码是否有效。多次运行它,可以注意到问候语发生了变化。
$ go run .
Great to see you, Gladys!
$ go run .
Hi, Gladys. Welcome!
$ go run .
Hail, Gladys! Well met!
接下来,您将使用一个 Slice 切片来问候多个人。
# 为多人返回问候语
在您将对模块代码进行的最后一次更改中,您将添加在一个请求中获得多人问候的支持功能。换句话说,您将处理多值输入,然后将该输入中的值与多值输出配对。要做到这一点,您需要将一组名称传递给一个函数,该函数可以为每个名称返回一个问候语。
注意:本主题是从创建 Go 模块开始的多部分教程的一部分。
但有一个问题。将 Hello 函数的参数从单个名称更改为一组名称将更改函数的签名。如果您已经发布了 example.com/greetings 模块,并且用户已经编写了调用 Hello 的代码,那么这种更改将破坏他们的程序。
在这种情况下,更好的选择是用不同的名称编写一个新函数。新功能将采用多个参数。这保留了旧功能以实现向后兼容性。
- 在 greetings/greetings.go 中,更改代码,使其看起来如下所示:
package greetings
import (
"errors"
"fmt"
"math/rand"
"time"
)
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
// Hellos returns a map that associates each of the named people
// with a greeting message.
func Hellos(names []string) (map[string]string, error) {
// A map to associate names with messages.
messages := make(map[string]string)
// Loop through the received slice of names, calling
// the Hello function to get a message for each name.
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
// In the map, associate the retrieved message with
// the name.
messages[name] = message
}
return messages, nil
}
// Init sets initial values for variables used in the function.
func init() {
rand.Seed(time.Now().UnixNano())
}
// randomFormat returns one of a set of greeting messages. The returned
// message is selected at random.
func randomFormat() string {
// A slice of message formats.
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
// Return one of the message formats selected at random.
return formats[rand.Intn(len(formats))]
}
在此代码中,您:
- 添加一个 Hellos 函数,该函数的参数是一组名称,而不是一个单独的名称。此外,您还可以将其返回类型之一从 string 更改为 map,以便返回映射到问候语的名称。
- 让新的 Hellos 函数调用现有的 Hello 函数。这有助于减少重复,同时保留两个功能。
- 创建一个消息 map,将每个接收到的名称(作为关键字)与生成的消息(作为值)关联起来。在 Go 中,您可以使用以下语法初始化映射:make(map[key-type]value-type)。您可以使用 Hellos 函数将此映射返回给调用者。有关地图的更多信息,请参阅 Go 博客上的Go maps in action (opens new window)。
- 循环查看函数接收到的名称,检查每个名称是否都有非空值,然后将消息与每个名称关联起来。在这个 for 循环中,range 返回两个值:循环中当前项的索引和项值的副本。您不需要索引,所以您使用 Go blank 标识符(下划线)来忽略它。有关详细信息,请参阅 Effective Go 中的The blank identifier (opens new window)。
- 在 hello/hello.go 调用代码中,传递一组名称,然后打印返回的名称/消息 Map 的内容。
在 hello.go 中,更改您的代码,使其看起来如下所示。
package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
// Set properties of the predefined Logger, including
// the log entry prefix and a flag to disable printing
// the time, source file, and line number.
log.SetPrefix("greetings: ")
log.SetFlags(0)
// A slice of names.
names := []string{"Gladys", "Samantha", "Darrin"}
// Request greeting messages for the names.
messages, err := greetings.Hellos(names)
if err != nil {
log.Fatal(err)
}
// If no error was returned, print the returned map of
// messages to the console.
fmt.Println(messages)
}
通过这些更改,您:
- 创建一个名称变量,作为包含三个名称的切片类型。
- 将 names 变量作为参数传递给 Hellos 函数。
- 在命令行中,切换到包含 hello/hello.go 的目录,然后使用 go-run 确认代码是否有效。
- 输出应该是将名称与消息关联起来的映射的字符串表示,如下所示:
$ go run .
map[Darrin:Hail, Darrin! Well met! Gladys:Hi, Gladys. Welcome! Samantha:Hail, Samantha! Well met!]
本主题介绍了用于表示名称/值对的映射。它还引入了通过为模块中的新功能或更改的功能实现新功能来保持向后兼容性的想法。有关向后兼容性的更多信息,请参阅保持模块兼容 (opens new window)。
接下来,您将使用内置的 Go 功能为代码创建一个单元测试。
# 创建单元测试
现在您已经将代码放到了一个稳定的位置(顺便说一句,做得很好),添加一个测试。在开发过程中测试代码可能会暴露出在您进行更改时出现的错误。在本主题中,您将为 Hello 函数添加一个测试。
注意:本主题是从创建 Go 模块开始的多部分教程的一部分。
Go 内置的对单元测试的支持使得在进行测试时更容易。具体来说,使用命名约定、Go 的测试包和 Go 测试命令,您可以快速编写和执行测试。
- 在 greetings 目录中,创建一个名为 greetings_test.go 的文件。
以_test.go 结尾的文件名告诉 go-test 命令此文件包含测试函数。
- 在 greetings_test.go 文件中,录入以下代码并保存文件:
package greetings
import (
"testing"
"regexp"
)
// TestHelloName calls greetings.Hello with a name, checking
// for a valid return value.
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b`+name+`\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
// TestHelloEmpty calls greetings.Hello with an empty string,
// checking for an error.
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}
在此代码中,您:
- 在与您正在测试的代码相同的包中实现测试函数。
- 创建两个测试函数来测试问候语。Hello 函数。测试函数名称的形式为 TestName,其中 Name 表示特定测试的内容。此外,测试函数将指向测试包的 testing.T 类型的指针作为参数。您可以使用此参数的方法从测试中进行报告和日志记录。
- 执行两项测试:
- TestHelloName 调用 Hello 函数,传递一个名称值,该函数应该能够使用该名称值返回有效的响应消息。如果调用返回错误或意外响应消息(其中不包括您传入的名称),则使用 t 参数的 Fatalf 方法将消息打印到控制台并结束执行。
- TestHelloEmpty 使用一个空字符串调用 Hello 函数。此测试旨在确认您的错误处理是否有效。如果调用返回非空字符串或没有错误,则使用 t 参数的 Fatalf 方法将消息打印到控制台并结束执行。
- 在 greetings 目录的命令行中,运行 go test 命令来执行测试。
go test 命令在测试文件(名称以_test.go 结尾)中执行测试函数(名称以 test 开头)。您可以添加-v 标志来获得详细的输出,其中列出了所有测试及其结果。
测试应该通过。
$ go test
PASS
ok example.com/greetings 0.364s
$ go test -v
=== RUN TestHelloName
--- PASS: TestHelloName (0.00s)
=== RUN TestHelloEmpty
--- PASS: TestHelloEmpty (0.00s)
PASS
ok example.com/greetings 0.372s
- 中断 greetings.Hello 函数用于查看未通过的测试。
TestHelloName 测试函数检查您指定为 Hello 函数参数的名称的返回值。要查看失败的测试结果,请更改 greetings.Hello 函数,使其不再包含名称。
在 greetings/greetings.go 中,粘贴以下代码来代替 Hello 函数。请注意,高亮显示的行会更改函数返回的值,就好像名称参数被意外删除了一样。
// Hello returns a greeting for the named person.
func Hello(name string) (string, error) {
// If no name was given, return an error with a message.
if name == "" {
return name, errors.New("empty name")
}
// Create a message using a random format.
// message := fmt.Sprintf(randomFormat(), name)
message := fmt.Sprint(randomFormat())
return message, nil
}
- 在 greetings 目录的命令行中,运行 go test 来执行测试。
这一次,在没有-v 标志的情况下运行 go 测试。输出将只包括失败测试的结果,当您有很多测试时,这可能很有用。TestHelloName 测试应该失败——TestHelloEmpty 仍然通过。
$ go test
--- FAIL: TestHelloName (0.00s)
greetings_test.go:15: Hello("Gladys") = "Hail, %v! Well met!", <nil>, want match for `\bGladys\b`, nil
FAIL
exit status 1
FAIL example.com/greetings 0.182s
在下一个(也是最后一个)主题中,您将看到如何编译和安装代码以在本地运行。
# Go 应用程序的编译和安装
在最后一个主题中,您将学习几个新的 go 命令。虽然 go run 命令是在频繁更改时编译和运行程序的有用快捷方式,但它不会生成二进制可执行文件。
本主题介绍了用于生成代码的两个附加命令:
- go-build 命令编译包及其依赖项,但不安装结果。
- go install 命令编译并安装程序包。
注意:本主题是从创建 Go 模块开始的多部分教程的一部分。
- 在 hello 目录的命令行中,运行 go-build 命令将代码编译为可执行文件。
go build
- 在 hello 目录中的命令行中,运行新的 hello 可执行文件以确认代码是否有效。
请注意,您的结果可能会有所不同,这取决于您在测试后是否更改了 greetings.go 代码。
- Linux 或 Mac 系统下
$ ./hello
map[Darrin:Great to see you, Darrin! Gladys:Hail, Gladys! Well met! Samantha:Hail, Samantha! Well met!]
- Windows 系统下
$ hello.exe
map[Darrin:Great to see you, Darrin! Gladys:Hail, Gladys! Well met! Samantha:Hail, Samantha! Well met!]
您已将应用程序编译为可执行文件,以便运行它。但要当前运行它,您的提示需要位于可执行文件的目录中,或者指定可执行文件路径。
接下来,您将安装可执行文件,这样您就可以在不指定其路径的情况下运行它。
- 查找 Go 安装路径,Go 命令将在其中安装当前软件包。
您可以通过运行 go list 命令来发现安装路径,如以下示例所示:
$ go list -f '{{.Target}}'
例如,命令的输出可能会说/home/gopher/bin/hello,这意味着二进制文件被安装到/home/gopaher/bin。在下一步中,您将需要此安装目录。
- 将 Go 安装目录添加到系统的 shell 路径中。
这样,您就可以运行程序的可执行文件,而无需指定可执行文件的位置。
- Linux 或 Mac 系统
$ export PATH=$PATH:/path/to/your/install/directory
- Windows 系统
set PATH=%PATH%;C:\path\to\your\install\directory
另一种选择是,如果您的 shell 路径中已经有一个类似$HOME/bin 的目录,并且您想在那里安装 Go 程序,则可以使用 Go-env 命令设置 GOBIN 变量来更改安装目标:
go env -w GOBIN=/path/to/your/bin
或
$ go env -w GOBIN=C:\path\to\your\bin
- 更新完 shell 路径后,运行 go-install 命令编译并安装包
$ go install
- 只需键入应用程序的名称即可运行应用程序。为了让这变得有趣,打开一个新的命令提示符,并在其他目录中运行 hello 可执行文件名。
$ hello
map[Darrin:Hail, Darrin! Well met! Gladys:Great to see you, Gladys! Samantha:Hail, Samantha! Well met!]
Go 教程到此结束!