零基础 go - 28(函数 - 包)

16 阅读4分钟

一、场景

  • 在实际开发中,我们往往需要在不同的文件中,去调用其他文件定义的函数、变量等内容。

  • 比如,我们在 main.go 文件中定义了一个函数 foo(),现在我们想在 utils.go 文件中调用这个函数,那么我们就需要在 utils.go 文件中导入 main.go 文件所在的包。

  • 这个时候,我们就需要使用到包(package)的概念。

  • 包可以理解为一个目录,里面包含了一系列的 Go 源文件,这些源文件共同组成了一个包。

  • 通过导入(import)包,我们就可以在当前文件中使用包中定义的函数、变量等内容。

二、包的本质和原理

  • 包的本质实际上就是创建不同的文件,来存放程序文件。
  • 包的原理就是通过将相关的 Go 源文件放在同一个目录下,并且在这些源文件中声明相同的包名来实现的。
  • go 的每个文件都属于一个包,也就是说go是以包的形式管理文件和项目目录结构的。

image.png

三、包的作用

  • 区分相同名字的函数、变量等标识符
  • 当程序文件很多时可以很好的管理文件
  • 控制函数、变量等访问范围,即作用域

四、包的使用

  • 打包基本语法:package 包名
  • 引入包的基本语法 import "包路径"

五、使用示例

  • 在 utils 文件夹下创建一个 utils.go 文件,定义一个 Cal 函数
  • 在 main.go 文件中创建一个 main 包,并在 main 函数中调用 utils 包中的 Cal 函数

image.png

image.png

image.png

image.png

六、包的使用细节和注意事项

  • package 必须在 Go 文件的第一行声明,且一个包内的所有 Go 文件必须声明相同的包名。

  • 包名和目录名不一定要相同,但通常我们会将包名命名为与目录名相同,以便于管理和识别。

  • 包名不能包含特殊字符,通常使用小写字母和下划线来命名。

  • 在同一个包中,所有的 Go 源文件都必须声明相同的包名,否则会导致编译错误。

  • 包的导入路径通常是相对于 GOPATH 或者 go.mod 文件所在目录的路径,使用斜杠(/)分隔。例如,如果我们有一个包位于 GOPATH/src/github.com/user/project/utils,那么我们可以通过 import "github.com/user/project/utils" 来导入这个包。

  • 在给一个文件打包时,该包对应一个文件夹,文件夹内的所有文件都属于这个包,包内的函数、变量等标识符可以被同一包内的其他文件直接访问,而不需要导入。

  • 包的访问控制:在 Go 中,包内的标识符(函数、变量等)如果以大写字母开头,则表示该标识符是可导出的,可以被其他包访问;如果以小写字母开头,则表示该标识符是不可导出的,只能在当前包内访问。

  • 包的初始化:当一个包被导入时,Go 会自动执行该包中的 init() 函数(如果存在)。init() 函数通常用于包的初始化工作,比如设置默认值、检查环境等。一个包中可以有多个 init() 函数,它们会按照在源文件中出现的顺序执行。

  • 包的循环依赖:Go 不允许包之间存在循环依赖关系,即包 A 导入包 B,同时包 B 又导入包 A。这会导致编译错误。为了避免这种情况,我们应该合理设计包的结构,尽量减少包之间的相互依赖。

  • 包的文档注释:在 Go 中,我们可以为包、函数、变量等标识符添加文档注释,这些注释以双斜杠(//)开头,并且紧接在标识符的前面。通过使用 go doc 命令,我们可以查看这些文档注释,帮助我们更好地理解和使用包中的内容。

  • 包的测试:Go 提供了内置的测试工具,我们可以在包中创建一个以 _test.go 结尾的文件,编写测试函数来测试包中的函数和变量。测试函数以 Test 开头,并且接受一个 *testing.T 类型的参数。通过运行 go test 命令,我们可以执行这些测试函数,确保我们的包的功能正确。

  • 使用其他包的变量或者函数的语法是:包名.标识符,例如 fmt.Println() 中的 fmt 就是包名,Println 是 fmt 包中导出的函数。

  • 如果包名很长,我们可以在导入时使用别名来简化代码,例如 import utils "github.com/user/project/utils",这样我们就可以通过 utils.Cal() 来调用 utils 包中的 Cal 函数。

  • 同一个包下,不能有相同的函数名或者变量名,否则会导致编译错误。

  • 如果你要编译成可执行文件,包名必须是 main,并且必须包含一个 main() 函数作为程序的入口点。

image.png