如何在Go中编写包

A package is made up of Go files that live in the same directory and have the same package statement at the beginning. You can include additional functionality from packages to make your programs more sophisticated. Some packages are available through the Go Standard Library and are therefore installed with your Go installation. Others can be installed with Go’s go get command. You can also build your own Go packages by creating Go files in the same directory across which you want to share code by using the necessary package statement.

程序包由Go文件组成,这些文件位于同一目录中,并且开头具有相同的package语句。 您可以从软件包中包含其他功能,以使您的程序更复杂。 有些软件包可通过Go标准库获得,因此随Go安装一起安装。 其他人可以使用Go's go get命令安装。 您还可以通过使用必要的package语句在要共享代码的同一目录中创建Go文件来构建自己的Go软件包。

This tutorial will guide you through writing Go packages for use within other programming files.

本教程将指导您编写用于其他编程文件的Go软件包。

先决条件 (Prerequisites)

编写和导入包 (Writing and Importing Packages)

Writing a package is just like writing any other Go file. Packages can contain definitions of functions, types, and variables that can then be used in other Go programs.

编写程序包就像编写其他任何Go文件一样。 包可以包含函数, 类型变量的定义,然后可以在其他Go程序中使用它们。

Before we create a new package, we need to be in our Go workspace. This is typically under our gopath. For the example, in this tutorial we will call the package greet. To do this, we’ve created a directory called greet in our gopath under our project space. If our organization were gopherguides, and we wanted to create the greet package under the organization while using Github as our code repository, then our directory would look like this:

在创建新包之前,我们需要先进入Go工作区。 这通常在我们的gopath 。 对于示例,在本教程中,我们将包称为greet 。 为此,我们在项目空间下的gopath创建了一个名为greet的目录。 如果我们的组织是gopherguides ,并且我们想在使用Github作为代码存储库的情况下在组织下创建greet包,那么我们的目录将如下所示:

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

The greet directory is within the gopherguides directory:

greet目录位于gopherguides目录中:

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

Finally, we can add the first file in our directory. It is considered common practice that the primary or entry point file in a package is named after the name of the directory. In this case, we would create a file called greet.go inside the greet directory:

最后,我们可以在目录中添加第一个文件。 通常的做法是,以目录名称命名包中的primary文件或entry point文件。 在这种情况下,我们将在greet目录中创建一个名为greet.go的文件:

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

With the file created, we can begin to write our code that we want to reuse or share across projects. In this case, we will create a function called Hello that prints out Hello World.

创建文件后,我们可以开始编写要在项目中重复使用或共享的代码。 在这种情况下,我们将创建一个名为Hello的函数,该函数会打印出Hello World

Open your greet.go file in your text editor and add the following code:

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

greet.go
greet.go
package greet

import "fmt"

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

Let’s break this first file down. The first line of each file needs the name of the package that you are working in. Since you’re in the greet package, you use the package keyword followed by the name of the package:

让我们分解第一个文件。 每个文件的第一行需要的名package ,你是在工作。由于你的是, greet包,您使用package ,然后包的名称关键字:

package greet

This will tell the compiler to treat everything in the file as being part of the greet package.

这将告诉编译器将文件中的所有内容都视为greet软件包的一部分。

Next you declare any other packages you need to use with the import statement. You’re only using one in this file—the fmt package:

接下来,声明需要与import语句一起使用的所有其他软件包。 您在此文件中仅使用一个文件fmt软件包:

import "fmt"

Lastly, you create the function Hello. It will use the fmt package to print out Hello, World!:

最后,创建函数Hello 。 它将使用fmt软件包打印出Hello, World!

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

Now that you’ve written the greet package, you can use it in any other package you create. Let’s create a new package in which you’ll use your greet package.

现在,您已经编写了greet包,您可以在创建的任何其他包中使用它。 让我们创建一个新的包,在其中使用greet包。

You’re going to create a package called example, which means you need a directory called example. Create this package in your gopherguides organization, so the directory structure looks like so:

您将创建一个名为example的包,这意味着您需要一个名为example的目录。 在您的gopherguides组织中创建此软件包,因此目录结构如下所示:

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

Now that you have your directory for your new package, you can create the entry point file. Because this is going to be an executable program, it is considered best practice to name the entry point file main.go:

现在您有了新软件包的目录,就可以创建入口点文件了。 因为这将是一个可执行程序,所以将入口点文件命名为main.go被视为最佳实践:

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

In your text editor, open main.go and add the following code to call the greet package:

在您的文本编辑器中,打开main.go并添加以下代码以调用greet包:

main.go
main.go
package main

import "github.com/gopherguides/greet"

func main() {
    greet.Hello()
}

Because you’re importing a package, you need to call the function by referencing the package name in dot notation. Dot notation is the practice of putting a period . between the name of the package you are using and the resource within that package that you want to use. For instance, in your greet package, you have the Hello function as a resource. If you want to call that resource, you use the dot notation of greet.Hello().

因为要导入软件包,所以需要通过以点表示法引用软件包名称来调用函数。 点表示法是放置句的做法. 在您正在使用的程序包的名称和您要使用的程序包中的资源之间。 例如,在greet包中,您具有Hello函数作为资源。 如果要调用该资源,请使用点表示法greet.Hello()

Now, you can open your terminal and run the program on the command line:

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

  • go run main.go

    去运行main.go

When you do, you’ll receive the following output:

完成后,您将收到以下输出:


   
   
Output
Hello, World!

To see how you can use variables in a package, let’s add a variable definition in your greet.go file:

要查看如何在包中使用变量,让我们在greet.go文件中添加变量定义:

greet.go
greet.go
package greet

import "fmt"

var Shark = "Sammy"

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

Next, open your main.go file and add the following highlighted line to call the variable from greet.go in a fmt.Println() function:

接下来,打开main.go文件,并添加以下突出显示的行以在fmt.Println()函数中从greet.go调用变量:

main.go
main.go
package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)
}

Once you run the program again:

再次运行该程序后:

  • go run main.go

    去运行main.go

You’ll receive the following output:

您将收到以下输出:


   
   
Output
Hello, World! Sammy

Finally, let’s also define a type in the greet.go file. You’ll create the type Octopus with name and color fields, and a function that will print out the fields when called:

最后,让我们在greet.go文件中定义一个类型。 您将使用namecolor字段创建一个类型为Octopus的类型,并创建一个在调用时将打印出这些字段的函数:

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 Hello() {
    fmt.Println("Hello, World!")
}

Open main.go to create an instance of that type at the end of the file:

打开main.go在文件末尾创建该类型的实例:

main.go
main.go
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())
}

Once you’ve created an instance of Octopus type with oct := greet.Octopus, you can access the functions and fields of the type within the main.go file’s namespace. This lets you write oct.String() on the last line without invoking greet. You could also, for example, call one of the types fields such as oct.Color without referencing the name of the greet package.

一旦使用oct := greet.Octopus创建了Octopus类型的实例,就可以在main.go文件的命名空间中访问该类型的函数和字段。 这使您可以在最后一行写oct.String()而不调用greet 。 例如,您也可以调用类型字段之一,例如oct.Color而不必引用greet包的名称。

The String method on the Octopus type uses the fmt.Sprintf function to create a sentence, and returns the result, a string, to the caller (in this case, your main program).

Octopus类型的String方法使用fmt.Sprintf函数创建一个句子, returns结果(字符串) returns给调用者(在本例中为您的主程序)。

When you run the program, you’ll receive the following output:

运行该程序时,您将收到以下输出:

  • go run main.go

    去运行main.go

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

By creating the String method on Octopus, you now have a reusable way to print out information about your custom type. If you want to change the behavior of this method in the future, you only have to edit this one method.

通过在Octopus上创建String方法,您现在可以使用一种可重用的方式来打印有关您的自定义类型的信息。 如果将来要更改此方法的行为,则只需编辑此方法。

导出代码 (Exported Code)

You may have noticed that all of the declarations in the greet.go file you called were capitalized. Go does not have the concept of public, private, or protected modifiers like other languages do. External visibility is controlled by capitalization. Types, variables, functions, and so on, that start with a capital letter are available, publicly, outside the current package. A symbol that is visible outside its package is considered to be exported.

您可能已经注意到,您调用的greet.go文件中的所有声明都大写了。 Go不像其他语言那样具有publicprivateprotected修饰符的概念。 外部可见性由大小写控制。 以大写字母开头的类型,变量,函数等在当前程序包外部可以公开获得。 在其包装之外可见的符号被视为已exported

If you add a new method to Octopus called reset, you can call it from within the greet package, but not from your main.go file, which is outside the greet package:

如果在Octopus添加一个名为reset的新方法,则可以从greet包中调用它,但不能从greet包之外的main.go文件中调用它:

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!")
}

If you try to call reset from the main.go file:

如果您尝试从main.go文件调用reset

main.go
main.go
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()
}

You’ll receive the following compilation error:

您将收到以下编译错误:


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

To export the reset functionality from Octopus, capitalize the R in reset:

要从Octopus export reset功能,请在reset大写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!")
}

As a result you can call Reset from your other package without getting an error:

结果,您可以从其他程序包中调用Reset ,而不会出现错误:

main.go
main.go
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())
}

Now if you run the program:

现在,如果您运行该程序:

  • go run main.go

    去运行main.go

You will receive the following output:

您将收到以下输出:


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

By calling Reset, you cleared out all the information in the Name and Color fields. When you call the String method, it will print nothing where Name and Color normally appear because the fields are now empty.

通过调用Reset ,可以清除“ Name和“ Color字段中的所有信息。 当您调用String方法时,由于字段现在为空,因此在“ Name和“ Color通常出现的地方将不打印任何内容。

结论 (Conclusion)

Writing a Go package is the same as writing any other Go file, but placing it in another directory allows you to isolate the code to be reused elsewhere. This tutorial covered how to write definitions within a package, demonstrated how to make use of those definitions within another Go programming file, and explained the options for where to keep the package in order to access it.

编写Go程序包与编写任何其他Go文件相同,但是将其放在另一个目录中使您可以隔离要在其他地方重用的代码。 本教程介绍了如何在程序包中编写定义,演示了如何在另一个Go编程文件中使用这些定义,并说明了将程序包保留在何处以便对其进行访问的选项。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-write-packages-in-go

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值