「每周译Go」如何在 Go 中编写包

admin 2022年11月7日14:38:59评论25 views字数 5401阅读18分0秒阅读模式

各位Gopher们,今天将是《How To Code In Go》上半部分的最后一篇啦!在这里小G先给 Gopher 们一直以来的坚持点个大大的赞「每周译Go」如何在 Go 中编写包!行百里者半九十,要继续坚持哦!

Gopher们在学习过程中若是有任何与Go相关的问题,欢迎留言区告诉我们,小G看到后一定第一时间回复大家!

那么话不多说,一起来看下今天的内容叭~

目录
  1. 如何在 Ubuntu 18.04 上安装 Go 和设置本地编程环境

  2. 如何在 macOS 上安装 Go 和设置本地编程环境

  3. 如何在 Windows 10 上安装 Go 和设置本地编程环境

  4. 如何用 Go 编写你的第一个程序

  5. 理解 GOPATH

  6. 如何在 Go 中写注释

  7. 理解 Go 的数据类型

  8. Go 中处理字符串的介绍

  9. 如何在 Go 中格式化字符串

  10. 介绍 Go 中的 Strings 包

  11. 如何在 Go 中使用变量和常量

  12. 如何在 Go 中转换数据类型

  13. 如何用运算符在 Go 中做数学计算

  14. 了解 Go 中的布尔逻辑

  15. 理解 Go 中的 Map

  16. 理解 Go 中的数组和切片

  17. 在 Go 中处理错误

  18. 在 Go 中创建自定义错误

  19. 在 Go 中处理恐慌

  20. 在 Go 中导入包


如何在 Go 中编写包

一个包由同一目录下的 Go 文件组成的,并且在文件开头有相同的包声明。你可以从包中加入额外的功能,使你的程序更加复杂。有些包可以通过 Go 标准库获得,因此在安装 Go 时就已经安装了。其他的可以用 Go 的go get命令来安装。你也可以通过在同一目录下创建 Go 文件来建立你自己的 Go 包,你可以通过使用必要的包声明来分享代码。

本教程将指导你如何编写 Go 包,以便在其他编程文件中使用。

前提条件

  • 按照《如何安装和设置 Go 的本地编程环境》系列教程中的一个教程设置 Go 编程环境。按照本地编程环境教程中的步骤5创建你的 Go 工作区。要遵循本文的例子和命名规则,请阅读第一节「编写和导入软件包」。
  • 为了加深你对 GOPATH 的了解,请阅读往期文章《理解 GOPATH》

编写和导入软件包

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

在我们创建一个新的包之前,我们需要进入我们的 Go 工作区。这通常是在我们的gopath下。对于这个例子,本教程中我们将把包称为greet。为了做到这一点,在我们的项目空间下的gopath中创建了一个名为greet的目录。当使用 Github 作为代码库,组织名称为gopherguides,想在此组织下创建greet包,那么我们的目录会是这样的:

└── $GOPATH
└── src
└── github.com
└── gopherguides
greet目录在gopherguides目录中:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── greet
最后,我们可以添加我们目录中的第一个文件。通常的做法是,包中的 主要入口 文件是以目录名来命名的。在这种情况下,将在greet目录下创建一个名为greet.go的文件:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── greet
└── greet.go
创建了文件后,我们就可以开始编写我们想要重复使用或在不同项目中共享的代码。在本例中,我们将创建一个打印出 Hello WorldHello 的函数。
在文本编辑器中打开 greet.go 文件,增加如下代码:
package greet

import "fmt"

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

让我们把这个文件分解一下,每个文件中第一行需要是所处的名称。因为你在greet包里,所以通过使用package关键字,后面加包的名称:

package greet
这将告诉编译器把文件中的所有内容作为greet包的一部分。
接下来,你用 import 语句声明你需要使用的任何其他包。在这个文件中你只使用一个包,fmt包:
import "fmt"
最后,你创建函数Hello,它将使用fmt包来打印出Hello, World!
func Hello() {
 fmt.Println("Hello, World!")
}
现在已经编写了greet包,可以在你创建的任何其他包中使用它。让我们创建一个新的包,在其中使用greet包。
接下来创建一个名为example的包,这意味着需要一个名为example的目录。在gopherguides中创建这个包,所以目录结构看起来像这样:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── example
现在你有了新包的目录,可以创建入口文件。因为这将是一个可执行的程序,最好的做法是将入口文件命名为main.go
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── example
└── main.go
在文本编辑器中,打开main.go,添加以下代码来调用greet包:
package main

import "github.com/gopherguides/greet"

func main() {
 greet.Hello()
}

因为正在导入一个包,通过用点符号来调用指定包的函数。点符号是指在使用的包的名称和想使用的包中资源之间加一个句号.。例如,在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中的变量:
package main

import (
 "fmt"

 "github.com/gopherguides/greet"
)

func main() {
 greet.Hello()

 fmt.Println(greet.Shark)
}
再次运行此程序:
go run main.go
你会收到以下输出:
Hello, World!
Sammy

最后,让我们也在greet.go文件中定义一个类型。创建一个带有 namecolor字段的 Octopus 类型,以及一个在调用时将打印出字段的函数:

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,在文件的末尾创建一个该类型的实例:
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文件的命名空间中访问该类型的函数和字段。这使得在最后一行直接写oct.String(),而不用调用greet。同样的,也可以在不引用greet包的名字的情况下调用oct.Color等类型字段。

Octopus类型上的String方法使用fmt.Sprintf函数来输出一段文本,并将结果即一个字符串,返回给调用者(在这里是指主程序)。

当你运行该程序时,你会收到以下输出:
go run main.go
Hello, World!
Sammy
The octopus's name is "Jesse" and is the color orange.
通过在Octopus上创建String方法,你现在有一个可重复使用的方法来打印出自定义类型的信息。如果想在将来改变这个方法的行为,只需要编辑这一个方法。

可导出代码

你可能已经注意到,调用的greet.go文件中所有的声明都是大写的。Go 没有像其他语言那样有publicprivateprotected修饰符的概念。外部可见性是由大写字母控制的。以大写字母开头的类型、变量、函数等等,在当前包之外是可以公开使用的。一个在其包外可见的符号被认为是 可导出 的。
如果你给Octopus添加了一个名为reset的新方法,可以在greet包内调用它,但是不能在main.go文件中调用,因为调用者在greet包之外:
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 功能,请将reset 中的R 大写:
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,清除了NameColor字段中的所有信息。当调用String方法时,NameColor打印为空,因为这些字段现在是空的。

总结

编写 Go 包与编写其他 Go 文件是一样的,但把它放在另一个目录中可以隔离代码,以便在其他地方重复使用。本教程介绍了如何在包中编写定义,演示了如何在另一个 Go 文件中使用这些定义,并解释了控制包是否可访问的选项。

2022 GopherChina大会报名火热进行中!

扫描下方二维码即可报名参与哦~
「每周译Go」如何在 Go 中编写包

大会合作、现场招聘及企业购票等事宜请联系微信:18516100522

「每周译Go」如何在 Go 中编写包

戳这里 Go !

原文始发于微信公众号(GoCN):「每周译Go」如何在 Go 中编写包

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年11月7日14:38:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   「每周译Go」如何在 Go 中编写包http://cn-sec.com/archives/1394749.html

发表评论

匿名网友 填写信息