Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > golang创建Module

详解如何在golang项目开发中创建自己的Module

作者:demo007x

既然我们使用了很多开源的 module为我们的日常开发提供了很多的便捷性,那我们该如何实现自己的 module 来提供给团队中使用,接下小编就给大家介绍一下在golang项目开发如何创建自己的Module,需要的朋友可以参考下

为什么要创建一个 Module?

我们日常开发程序的时候都会引入第三方的 package,使用第三方的 package 的好处是我们可以快速的开发我们的程序的功能,只需要专注我们自己项目的功能,而且第三方的 package 提供了强大的,丰富的功能模块。比如 web 开发框架 ginecho,微服务开发框架 go-microgo-zero;权限控制:casbin,jwt: jwt-gogorm:gorm, 存储:minio 编写命令:cobra, 配置文件解析:viper,数据库:mysql 等等。这些包都是以 module 的形式提供的服务。

在自己的团队内部同样可以构建自己的私有化的 module,工公司内部的其他团队使用。比如我们公司有三个项目组,都有一些共同的项目。所以我们有公共的 module 放到 gitlab 上面提供不同团队的公共使用。同样这样也遵循了软件设计的高内聚低耦合的设计总则。将独立的功能封转为 module

这样做的好处是我们可以只实现一次共享使用,并不需要每个团队中都各自实现,同样也会带啦有好多弊端。

如何实现我们自己的 Module?

既然我们使用了很多开源的 module为我们的日常开发提供了很多的便捷性,那我们该如何实现自己的 module 来提供给团队中使用,甚至可以开放到 gitlab 上面提供给所有人使用(取之于开源,馈与开源)。

通过一下步骤来实现一个其他人可以使用的 module

创建一个 module 目录

首先创建一个 Go 模块。在模块中,我们可以将一组有用的功能在一个或多个相关包中实现。

Go 代码被分组为 packagepackage 又被分组为modulemodule 中需要指定运行代码所需的依赖项,包括 Go 版本及其所需的其他模块。

1、打开控制台并cd转到工作目录中,并创建目录module/greetings

 mkdir module
 cd module/greetings/

2、go mod init命令初始化模块 。

运行go mod init命令,为其提供模块路径 - 此处使用example.com/greetings. 如果发布模块,则这必须是 Go 工具可以下载您的模块的路径。那将是我们的代码的存储库。

 $ go mod init example.com/greetings

go mod init命令创建一个 go.mod 文件来跟踪代码的依赖项。当我们添加依赖项时,go.mod 文件将列出项目的代码所依赖的版本。这可以保持构建的可重复性,并让我们可以直接控制要使用的模块版本。

3、打开编辑器在greetings创建目录下创建 文件greetings.go并编写代码:

 package greetings
 ​
 import (
   "fmt"
   "math/rand"
 )
 func Hello(name string) string {
   return fmt.Sprintf("嗨,%v。欢迎!", name)
 }

该函数Hello 接受一个name类型为的参数 string。该函数还返回一个string。在Go中,名称以大写字母开头的函数可以被不在同一包中的函数调用。这在 Go 中称为导出名称。

从另一个模块调用您的代码

1、我们在 greeting 的同级目录创建 hello 目录,作为调用者。

 ~/Developer/module
 tree -d
 .
 ├── greetings
 └── hello

2、打开编辑器并创建文件 hello.go 文件。在 hello.go 文件中编写代码:

 import (
   "example.com/greetings"
   "log"
 )
 ​
 func main() {
   message := greetings.Hello("demo007")
   fmt.Println(message)
 }

在文件中声明一个main包。在 Go 中,作为应用程序执行的代码必须位于包中main

导入两个包:example.com/greetingsfmt。 导入 example.com/greetings可以访问该Hello 函数。还可以导入fmt, 以及处理输入和输出文本的函数(例如将文本打印到控制台)。greetings通过调用包的 函数 来获取输出信息。

3、编辑example.com/hello模块以使用本地 example.com/greetings模块。

example.com/greetings 对于生产使用, 可以从其存储库发布模块,Go 工具可以在其中找到它并下载它。但是由于我们尚未发布该模块,因此我们需要调整该模块,以便它可以在本地文件系统上 example.com/hello找到代码example.com/greetings

所以我们使用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.20
 ​
 replace example.com/greetings => ../greetings
 ​
 require example.com/greetings v0.0.0-00010101000000-000000000000
 ​

然后我们在命令中 cd hello 的目录中,并执行命令 go mod tidy, 执行完成后我们发现新增加一行 require example.com/greetings v0.0.0-00010101000000-000000000000 并制定了一个版本号.

我们在 hello 中执行运行命令查看:

 go run hello.go
 嗨,demo007。欢迎!

返回并处理错误

处理错误是可靠代码的一个基本特征。下面我们将添加一些代码以从 greetings 模块返回错误,然后在调用者中处理它。

在 greetings/greetings.go 中,修改代码:

 package greetings
 ​
 import (
   "errors"
   "fmt"
   "math/rand"
 )
 ​
 func Hello(name string) (string, error) {
   // 如果没有提供名称,则返回带有错误消息的错误。
   if name == "" {
     return name, errors.New("empty name")
   }
 ​
   // 使用随机格式创建一条消息。
   message := fmt.Sprintf("嗨,%v。欢迎!", name)
   return message, nil
 }

我们修改了 Hello 函数添加了返回值 errorif 语句来检测输入的 name 是否是一个有效的值。如果为空则返回name 和 一个 错误 errors.New("empty name")

hello/hello.go 文件中,处理函数现在返回的错误 Hello以及非错误值。

 package main
 ​
 import (
   "example.com/greetings"
   "fmt"
   "log"
 )
 ​
 func main() {
   message, err := greetings.Hello("demo007")
   if err != nil {
     log.Fatal(err)
   }
   fmt.Println(message)

使用标准库中的函数log package输出错误信息。如果出现错误,可以使用 log包的Fatal来打印错误并停止程序。

在目录中的命令行中hello,运行 hello.go 以确认代码有效

 go run hello.go
 Great to see you, demo007!

处理切片中的数据

我们将使用 Go 切片。切片类似于数组,只不过它的大小会随着添加和删除项目而动态变化。切片是 Go 最有用的类型之一。

我们将添加一个小切片来包含三条问候消息,然后让代码随机返回其中一条消息。

greetings/greetings.go 中,我们修改代码,如下所示。

 package greetings
 ​
 import (
   "errors"
   "fmt"
   "math/rand"
 )
 ​
 func Hello(name string) (string, error) {
   // 如果没有提供名称,则返回带有错误消息的错误。
   if name == "" {
     return name, errors.New("empty name")
   }
 ​
   // 使用随机格式创建一条消息。
   message := fmt.Sprintf(randomFormat(), name)
   return message, nil
 }
 ​
 func randomFormat() string {
   formats := []string{
     "Hi, %v. Welcome!",
     "Great to see you, %v!",
     "Hail, %v! Well met!",
   }
   return formats[rand.Intn(len(formats))]
 }

1、添加一个randomFormat函数,返回随机选择的问候消息格式。 randomFormat以小写字母开头,使其只能被其自己的包中的代码访问(换句话说,它不会被导出)。

2、在 中randomFormat,声明formats具有三种消息格式的切片。声明切片时,您可以在括号中省略其大小,如下所示:[]string。这告诉 Go 切片底层数组的大小可以动态更改。

3、使用该 math/rand 包生成一个随机数,用于从切片中选择一个项目。

4、在 中Hello,调用该randomFormat函数来获取您将返回的消息的格式,然后 name一起使用该格式和值来创建消息。

5、像以前一样返回消息以及错误

hello/hello.go 中,我们修改代码,如下所示:

 package main
 ​
 import (
   "example.com/greetings"
   "fmt"
   "log"
 )
 ​
 func main() {
   message, err := greetings.Hello("demo007x")
   // 如果返回了错误,请将其打印到控制台并退出程序。
   if err != nil {
     log.Fatal(err)
   }
   //如果没有返回错误,请将返回的消息打印到控制台。
   fmt.Println(message)
 }
 ​

我们运行代码看看输出的内容:

 go run hello.go
 Hail, demo007x! Well met!
 ​
 go run hello.go
 Great to see you, demo007x!
 ​
 go run hello.go
 Hi, demo007x. Welcome!

测试 module

以上我们编写了基本的或者说是最简单的 golang module 的程序项目,如何确保我们的程序是无错误的或者是没有 bug 的?最好的办法就是添加 测试程序

在开发过程中测试代码可能会暴露出在您进行更改时出现的错误。

Go 对单元测试的内置支持使我们可以更轻松地进行测试。具体来说,使用命名约定、Go 的testing包和go test命令,可以快速编写和执行测试。

 package greetings
 ​
 import (
   "regexp"
   "testing"
 )
 ​
 // TestHelloName 调用 greetings.Hello 并传入一个名称,检查返回值是否有效。
 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 调用 greetings.Hello 并传入空字符串, 检查是否出现错误。
 func TestHelloEmpty(t *testing.T) {
   msg, err := Hello("")
   if msg != "" || err == nil {
     t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
   }
 }
 go test -v
 === RUN   TestHelloName
 --- PASS: TestHelloName (0.00s)
 === RUN   TestHelloEmpty
 --- PASS: TestHelloEmpty (0.00s)
 PASS
 ok    example.com/greetings 0.007s

发布module

以上我们编写了我们的第一个 go module, 并且编写了对应函数的测试程序,然后我们可以将我们的 module 程序提交到 github等系统。其他人就可以通过执行命令 go get example.com/greetingsgreeting 包安装到自己的项目中。

总结:

golang module 给我们提供了灵活的本地开发并测试 module 的机制。我们通过修改 go.mod 文件,通过指令 replace example.com/greetings => ../greetings 来实现本地 module 的开发和测试的全部过程。

以上就是详解golang项目开发如何创建自己的Module的详细内容,更多关于golang创建Module的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文