在Go中创建包的工作流程

时间:2017-06-08 05:49:56

标签: go packages

我知道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()
}

有更好的方法可以做到这一点,还是标准的工作流程?感谢。

1 个答案:

答案 0 :(得分:8)

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

首先,阅读"How to Write Go Code",它将解释Go的软件包布局和测试工具。最好跟他们一起去,因为很多Go工具都期望这种布局。

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

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

将功能放在newpackage.go下的package 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

请注意,测试与其测试的包装不同。这使它成为黑盒测试,它只能看到导出的(即UpperCase)函数。您可以通过将测试放在同一个包中来进行玻璃箱测试,最好在单独的文件中执行此操作,例如newpackage_internal_test.go

不幸的是Go并没有使用断言函数,上面的ift.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())
}

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