在 Go 中创建包的工作流程

Posted

技术标签:

【中文标题】在 Go 中创建包的工作流程【英文标题】:Workflow for creating packages in Go 【发布时间】:2017-11-09 16:31:42 【问题描述】:

我了解 Go 中的程序是以 main 函数为起点运行的。但我想知道为新包创建函数的工作流程是什么。

例如,在 python 中,当直接调用模块时,我在模块中使用__main__。当模块从另一个文件中导入时,__main__ 将被忽略。这在您开发新模块时很有用。

if __name__ == "__main__":
    # Run module code here if module called directly

对于 Go,我使用带有 package main 的 test.go 文件以及我的 main.go 文件来测试我正在创建的包中的函数。

// test.go
package main

import (
    "newpackage"
)

func main() 
    newpackage.MyNewFunc()

有没有更好的方法来做到这一点,或者这是标准的工作流程?谢谢。

【问题讨论】:

是的,有:请阅读golang.org/cmd/go/#hdr-Test_packages和golang.org/pkg/testing 从其他包导入主包看起来很奇怪。您能否提供一些细节来告诉我们您为什么会出现这种情况? 我不确定你的意思。我不是要导入主包。我只是想知道是否有与 python 的if __name__ == "__main__": 等效的方法,它可以让我尝试模块中的各个函数,而无需编写测试文件。见***.com/a/4041260/5319281 但正如其他人指出的那样,Go 的测试工具似乎是最好的方法。 【参考方案1】:

您没有在 Go 中使用 main 进行测试。 Go 有自己的测试框架。

首先,阅读"How to Write Go Code",它将解释 Go 的包布局和测试工具。最好使用它们,因为很多 Go 工具都需要这种布局。

创建包时,将其放在~/go/src 的某个位置。我建议使用您喜欢使用的存储库遵循约定,即使对于您不一定要上传的内容。它有助于更​​好地组织; go get 也会将其他外部包放入~/go/src/

例如,我会使用~/go/src/github.com/schwern/newpackage/,即使我不打算将其上传到 Github。 github.com/schwern 在 Go 源代码树中充当我的“组织”。

把函数放到newpackage.gopackage newpackage下。

$ cat ~/go/src/github.com/schwern/newpackage/newpackage.go 
package newpackage

func MyNewFunc() string 
    return "Hello!"

然后测试进入newpackage_test.go,紧邻newpackage.go。这些应该是Python熟悉的,写一堆Test*函数。与 Python 不同,它不使用断言。

$ cat ~/go/src/github.com/schwern/newpackage/newpackage_test.go 
package newpackage_test

import(
    "testing"
    "github.com/schwern/newpackage"
)

func TestMyNewFunc( t *testing.T ) 
    want := "Hello!"
    have := newpackage.MyNewFunc()

    if have != want 
        t.Errorf("MyNewFunc(): have: '%v', want: '%v'", have, want )
    

如果你在包目录中运行go test,它将编译当前包及其依赖项,在包目录中查找并编译所有*_test.go文件,并执行它们的Test*函数。

$ pwd
/Users/schwern/go/src/github.com/schwern/newpackage
$ go test -v
=== RUN   TestMyNewFunc
--- PASS: TestMyNewFunc (0.00s)
PASS
ok      github.com/schwern/newpackage   0.013s

请注意,该测试与它的测试位于不同的包中。这使它成为一个黑盒测试,它只能看到导出的(即大写)函数。您可以通过将测试放在同一个包中来进行 glassbox 测试,最好将其放在单独的文件中,例如 newpackage_internal_test.go

不幸的是 Go 没有断言函数,上面的 if 和对 t.Errorf 的调用是等价的。与其不断地手动滚动它们,不如有一些库提供断言函数,如stvp/assert。运行go get github.com/stvp/assert 后,您可以编写...

package newpackage_test

import(
    "testing"
    "github.com/schwern/newpackage"
    "github.com/stvp/assert"
)

func TestMyNewFunc( t *testing.T ) 
    assert.Equal( t, newpackage.MyNewFunc(), "Hello!" )


如果你想要一个使用newpackage 的可执行文件,它可能应该放在自己的包中。除非它是newpackage 的组成部分。

$ cat ~/go/src/github.com/schwern/newexec/main.go 
package main

import (
    "fmt"
    "github.com/schwern/newpackage"
)

func main() 
    fmt.Println(newpackage.MyNewFunc())

如果你想测试main,the testing package provides a special TestMain function...虽然我承认我并不完全理解它。与任何其他语言一样,最好将尽可能多的功能放入库调用中,并让 main 成为一个瘦包装器。

【讨论】:

以上是关于在 Go 中创建包的工作流程的主要内容,如果未能解决你的问题,请参考以下文章

在测试中创建和导入辅助函数,而不使用 py.test 在测试目录中创建包

我在 setup.py 中需要啥选项才能在正确的目录中创建包?

警告:在 plsql 中创建包体时出现编译错误...

在 Xamarin UWP 中创建包后,视频只能用语音播放,我看不到视频

使用 GoLand 启动 运行 Go 项目

go.sum工作机制