将单个程序包/模块拆分为多个(许多)文件会在进行构建时产生未定义的错误。

时间:2019-07-29 20:36:57

标签: go

我喜欢将模块/软件包分成许多文件(例如,较大的功能文件和耦合的帮助程序文件)。现在,模块可以随着扩展而具有许多更大的功能。假设我的模块/软件包每个都包含大约30个文件。

几天前我开始使用Go时,我对模块模式有些困惑。我有JavaScript(ES6 +)背景。经过研究,我发现您可以通过运行以下命令go build ./...来构建由多个文件组成的软件包。效果很好,直到我的程序包包含大约10个文件。突然我看到关于函数未定义的错误。同时,在模块/软件包的src中明确定义了这些功能(并适当大写)。

我的直觉是这是由于构建顺序所致。假设我们有2个文件“ a.go”和“ b.go”。文件“ a.go”引用了文件“ b.go”中的函数。当在“ b.go”之前构建文件“ a.go”时,出现未定义的错误。我的第二感觉是文件“ a.go”包含对文件“ b.go”内部函数的引用,反之亦然。因此,文件“ b.go”也引用了文件“ a.go”中的函数。

  1. 我的第二个肠道感觉正确吗?
  2. 人们通常如何解决这个问题,或者更好的是,什么是最佳实践?
  3. 创建由许多文件组成的单个模块的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

您可以根据需要在一个目录中包含多达.go个文件。

Go软件包由一个目录中的所有.go文件组成。单个目录中的每个.go文件应与同一目录中的其他package foo文件具有相同的.go声明。

您的源代码通过导入语句(例如import "github.com/my/repo/pkg1"中提供的导入路径从另一个包(另一个目录)中导入代码。

要构建软件包,您可以cd到目录并发布go build .(其中.意味着构建当前目录中的所有文件,或者也可以发布{{ 1}}中没有任何参数,因为默认值为go build)。

同一包(同一目录)中的代码可以引用同一包(同一目录)中其他文件中的代码,而无需导入其他文件,也不需要导出符号(大写的第一个字符)。 / p>

非常值得花时间阅读"How to Write Go Code",其中包括这些概念的概述,包括:

  

Go程序员通常将所有Go代码保存在单个工作区中。

     
      
  • 工作区包含许多版本控制存储库(例如,由Git管理)。
  •   
  • 每个存储库包含一个或多个
  •   
  • 每个软件包都在一个目录中包含一个或多个Go源文件。
  •   
  • 软件包目录的路径确定其导入路径
  •   

稍后介绍了“工作区”和GOPATH之间的关系:

  

GOPATH环境变量指定工作空间的位置。默认情况下,它的目录位于您的主目录内,因此在Unix上为$ HOME / go,在Plan 9上为$ home / go,在Windows上为%USERPROFILE%\ go(通常为C:\ Users \ YourName \ go)。

关于您更具体的问题:

将单个程序包拆分为多个(许多)文件会在进行构建时产生未定义的错误。/

在同一个目录中的多个单独.文件中拆分软件包(相同的软件包)本身不会引起问题,但是当然需要正确进行(例如,所有{{1} }同一目录(同一包)中的文件需要在顶部附近具有相同的.go声明;同一目录中的文件不应尝试使用.go语句来导入同一目录中的其他文件;等)。

我的直觉是因为构建顺序。

构建顺序在这里无关紧要。

第二个感觉是文件“ a.go”包含对文件“ b.go”内部函数的引用,反之亦然。因此,文件“ b.go”也引用了文件“ a.go”中的函数。

如果package fooimport位于同一程序包(同一目录)中,这很好。

另一方面,如果a.gob.go位于不同的程序包(不同的目录)中,则不允许这样做。这是因为Go不允许在包级别使用循环依赖项。如果这是问题所在,那么最简单的解决方案是将a.gob.go移到同一目录中,或者重构以引入第三个包来中断周期,从而使a.go和{{1 }}都可以依赖于第三个程序包,也可以使用接口或其他可能的解决方案,但是鉴于您说您不熟悉Go,最简单的解决方案可能是学习时最好的解决方案。