Go语言包与模块区别

前面的代码均通过 package main 指定了包名为 main。
在 Go 中,若一个程序是 main 包的一部分,则会生成二进制的可运行文件,并调用其中的 main 函数。

对于非 main 包,则会生成 .a 文件,供其他包调用。

创建包
若存在以下的目录结构:

$ tree myMath
myMath
└── myMath.go

myMath.go 为:

package myMath

func Add(a, b int) int {
  res := a + b
  return res
}

需要注意的是,在 Go 中,对于内容是否对外可见是通过其首字母的大小写来确定的,若首字母为大写则对外可见,如 myMath.Add() 方法,若首字母为小写,则对外不可见。
现在我们就有了一个名为 myMath 的包。在 Go 1.11 以前,需要将该包放在 $GOPATH 目录下,其他程序才能引用该包。

创建模块
Go 1.11 中引入了 Go Module,以模块的方式对包进行管理。对于上述包使用 go mod init <moduleName> 创建一个模块。
如:

go mod init github.com/username/myMath
go: creating new go.mod: module github.com/username/myMath
go: to add module requirements and sums:
go mod tidy

通过该命令,可以创建一个名为 github.com/username/myMath 的模块。由于很多包都是在 github 上发布的,因此可以将模块命名为 github.com + 用户名 + 包名的形式。go mod tidy 命令会将该包中引用的其他包下载到本地,由于 myMath 包没有引用其他包,因此无需执行该命令。

创建模块后目录结构为:

$ tree myMath
myMath
├── go.mod
└── myMath.go

新增了 go.mod 文件,其中记录了 模块名,go 版本,以及依赖等:

module github.com/username/myMath

go 1.17

GO111MODULE
Go 1.11 后存在两种包管理方式,一种是 GOPATH 的方式,一种是 Go module 的方式,为了解决包管理方式选择的问题,Go 提供了 GO111MODULE 环境变量,该变量有三种取值:

on 表示使用模块管理,不会去 GOPATH 目录查找包;
off 表示不适用模块管理,只在 GOPATH 下查找包;
auto 为默认值,则会根据当前目录下是否包含 go.mod 文件来决定使用何种方式。
引用包
这里只介绍通过模块的方式来引用包。

对于外部包,直接使用 import 语句引用即可,对于本地的自定义包,同样是通过 import 语句引用的,但需要对 go.mod 文件做一些修改。

若存在本地目录:

$ tree hello
hello
└── hello.go

其中 hello.go 为:

package main

import (
  "fmt",
  "github.com/username/myMath"
)

func main() {
  a, b := 1, 2
  sum := myMath.Add(a, b)
  fmt.Printf("sum = %d\n", sum)
}
 
若要引用其他的模块,也需要为该包创建一个模块:

go mod init main
创建模块后,需要在 go.mod 中添加下面内容:

require github.com/liumh/myMath v0.0.0

replace github.com/liumh/myMath => ../myMath
 
通过 replace 命令,将 github.com/liumh/myMath 包的路径改为本地路径,而无需访问远程仓库。

至此,就可以运行 hello.go了:

go run hello.go
sum = 3
 
发布包
可以将包发布到远程仓库,如 github。若发布上述的 myMath 包,则需要修改该包的包名为 github.com + 实际的github用户名 + "myMath",并在 github 上创建名为 myMath 的仓库。可以通过 git tag 命令标记该模块的版本。
 

posted @ 2022-06-02 00:28  jinzi  阅读(5)  评论(0编辑  收藏  举报