如何编写Go软件包

Go程序包由位于同一目录中的Go文件组成,该文件的开头有相同的package表达式。 连接到程序的程序包使您可以扩展其功能。 一些软件包是标准Go库的一部分。 这意味着,如果您使用Go,则它们已经安装。 其他软件包使用go get命令安装。 您还可以编写自己的Go-packages,在特殊目录中创建文件,并遵守包设计规则。



我们今天发布的翻译材料是Go-package的开发指南,可以将Go-packages连接到其他文件。

先决条件


  • 设置您的Go软件环境( 在此处了解如何执行此操作)。 创建一个Go工作区(以上材料的第五点专门讨论这一点)。 在本材料的下一部分中,您可以找到建议在家中复制的示例。 因此,您可以更好地处理它们。
  • 为了加深您对GOPATH -请阅读材料。

编写和导入包


编写程序包代码与编写常规Go代码相同。 包可以包含函数,类型和变量的声明,然后可以在其他Go程序中使用它们。

在开始创建新程序包之前,我们需要转到Go工作区。 它位于GOPATH变量指定的路径上。 例如,将我们的组织称为gopherguides 。 同时,我们使用GitHub作为存储库。 这导致以下事实:沿着GOPATH指定的路径,我们具有以下文件夹结构:

 └── $GOPATH    └── src        └── github.com            └── gopherguides 

我们将命名我们将在本指南中开发的软件包。 为此,请在gopherguides目录中创建greet目录。 因此,现有的文件夹结构将采用以下形式:

 └── $GOPATH    └── src        └── github.com            └── gopherguides                └── greet 

现在我们准备将第一个文件添加到greet目录。 通常,作为包的入口点的文件称为与包目录相同的文件。 在这种情况下,这意味着我们在greet目录中创建greet.go文件:

 └── $GOPATH    └── src        └── github.com            └── gopherguides                └── greet                    └── greet.go 

在此文件中,我们可以编写要在项目中重用的代码。 在这种情况下,我们将创建Hello函数,该函数显示文本Hello, World!

在文本编辑器中打开greet.go文件,并向其中添加以下代码:

 package greet import "fmt" func Hello() {    fmt.Println("Hello, World!") } 

让我们分析该文件的内容。 每个文件的第一行应包含我们在其中工作的软件包的名称。 由于我们位于greet package ,因此在此处使用package关键字,后跟包名称:

 package greet 

这告诉编译器接受文件中的所有内容作为greet软件包的一部分。

接下来,使用import语句导入必要的软件包。 在这种情况下,我们只需要一个软件包fmt

 import "fmt" 

最后,我们创建Hello函数。 她将使用fmt软件包的功能来显示字符串Hello, World!

 func Hello() {    fmt.Println("Hello, World!") } 

现在,在创建greet包之后,您可以在其他任何包中使用它。 让我们创建一个新的包,在其中我们将使用greet包。

即,我们将创建一个example包。 为此,我们将从进行相同的假设开始,创建greet包。 首先,在gopherguides文件夹中创建example文件夹:

 └── $GOPATH    └── src        └── github.com            └── gopherguides                    └── example 

现在创建一个文件,作为包的入口点。 我们将此软件包视为可执行程序,而不是其代码计划在其他软件包中使用的软件包。 程序输入点的文件通常称为main.go

 └── $GOPATH    └── src        └── github.com            └── gopherguides                └── example                    └── main.go 

在编辑器中打开main.go文件, main.go以下代码main.go到其中,这使您可以使用greet包的功能:

 package main import "github.com/gopherguides/greet" func main() {    greet.Hello() } 

我们将greet包导入了main.go文件中,这意味着要调用此包中声明的函数,我们需要使用点表示法。 点表示法是一种结构,其中在包名称和要使用的此包的资源名称之间放置一个点。 例如,在greet包中, Hello函数扮演资源的角色。 如果需要调用此函数,则使用点表示法: greet.Hello()

现在,您可以打开终端并运行程序:

 go run main.go 

完成此操作后,终端将显示以下内容:

 Hello, World! 

现在让我们谈谈如何使用包中声明的变量。 为此,请将变量声明添加到greet.go文件中:

 package greet import "fmt" var Shark = "Sammy" func Hello() {    fmt.Println("Hello, World!") } 

打开main.go文件,并在其中添加一行,其中fmt.Println()函数用于显示在greet.go程序包中声明的Shark变量的值。 即,将main.go转换为以下格式:

 package main import (    "fmt"    "github.com/gopherguides/greet" ) func main() {    greet.Hello()    fmt.Println(greet.Shark) } 

再次运行程序:

 go run main.go 

现在,她将输出以下内容:

 Hello, World! Sammy 

现在让我们谈谈如何在包中声明类型。 使用“ Name和“ Color字段创建一个Octopus类型,并创建一个类型方法。 调用此方法时,将返回经过特殊处理的Octopus字段的内容。 让我们greet.go转换为以下格式:

 package greet import "fmt" var Shark = "Sammy" type Octopus struct {    Name string    Color string } func (o Octopus) String() string {    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color) } func Hello() {    fmt.Println("Hello, World!") } 

现在打开main.go ,在其中创建新类型结构的实例,并引用其String()方法:

 package main import (    "fmt"    "github.com/gopherguides/greet" ) func main() {    greet.Hello()    fmt.Println(greet.Shark)    oct := greet.Octopus{        Name: "Jesse",        Color: "orange",    }    fmt.Println(oct.String()) } 

在使用类似于oct := greet.Octopus的构造创建Octopus实例之后,可以从main.go文件的命名空间访问该类型的方法和属性。 特别是,这使您可以使用位于main.go文件末尾的oct.String()命令,而main.go greet 。 另外,例如,我们可以使用oct.Color构造来oct.Color Color结构的字段。 同时,当我们调用该方法时,我们不访问greet

Octopus类型的String方法使用fmt.Sprintf函数构成句子,并使用return ,结果字符串return给方法调用(在这种情况下,此位置位于main.go )。

再次运行程序:

 go run main.go 

它将输出以下内容到控制台:

 Hello, World! Sammy The octopus's name is "Jesse" and is the color orange. 

现在,我们为Octopus配备了String方法,我们有了适合重用的类型信息输出机制。 如果将来您需要更改此方法的行为(可在许多项目中使用),则只需在greet.go编辑其代码greet.go

实体出口


您可能已经注意到,在访问greet软件包时,我们使用的所有内容都以大写字母开头的名称。 Go没有其他语言的访问修饰符,例如publicprivateprotected 。 实体对外部机制的可见性受字母(大小)开头的事实控制。 结果,名称,名称和名称以大写字母开头的类型,变量,函数在当前程序包外部可用。 包外部可见的代码称为导出。

如果为Octopus类型配备了称为reset的新方法,则可以从greet包中调用此方法,但不能从greet包中的main.go文件中main.go 。 这是greet.go的更新版本:

 package greet import "fmt" var Shark = "Sammy" type Octopus struct {    Name string    Color string } func (o Octopus) String() string {    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color) } func (o Octopus) reset() {    o.Name = ""    o.Color = "" } func Hello() {    fmt.Println("Hello, World!") } 

让我们尝试从main.go文件中调用reset

 package main import (    "fmt"    "github.com/gopherguides/greet" ) func main() {    greet.Hello()    fmt.Println(greet.Shark)    oct := greet.Octopus{        Name: "Jesse",        Color: "orange",    }    fmt.Println(oct.String())    oct.reset() } 

这将导致以下编译错误:

 oct.reset undefined (cannot refer to unexported field or method greet.Octopus.reset) 

为了导出Octopus类型reset方法,您需要对其进行重命名,将首字母小写r替换为大写R 我们通过编辑greet.go做到这greet.go

 package greet import "fmt" var Shark = "Sammy" type Octopus struct {    Name string    Color string } func (o Octopus) String() string {    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color) } func (o Octopus) Reset() {    o.Name = ""    o.Color = "" } func Hello() {    fmt.Println("Hello, World!") } 

这将导致以下事实:我们将能够从其他程序包调用Reset ,而不会遇到错误消息:

 package main import (    "fmt"    "github.com/gopherguides/greet" ) func main() {    greet.Hello()    fmt.Println(greet.Shark)    oct := greet.Octopus{        Name: "Jesse",        Color: "orange",    }    fmt.Println(oct.String())    oct.Reset()    fmt.Println(oct.String()) } 

运行程序:

 go run main.go 

这是控制台的内容:

 Hello, World! Sammy The octopus's name is "Jesse" and is the color orange The octopus's name is "" and is the color . 

通过调用Reset方法,我们清除了Octopus实例的“ Name和“ Color字段。 结果,在调用String ,以前显示了NameColor字段的内容,现在什么也不显示。

总结


编写Go软件包与编写常规Go代码没什么不同。 但是,将程序包代码放在其自己的目录中可以隔离该代码,该代码可在任何其他Go项目中使用。 在这里,我们讨论了如何在程序包中声明函数,变量和类型,研究了如何在程序包外部使用这些实体,并弄清楚了存储在何处以供重用的程序包。

亲爱的读者们! 您通常在Go上编写哪些程序? 您是否在其中使用专有软件包?

Source: https://habr.com/ru/post/zh-CN464289/


All Articles