开发者

Go Generate 代替 Makefile使用方法详解

目录
  • 介绍
  • Mockery
  • Go Generate
    • 用法
  • 总结

    介绍

    图灵完备性(Turing completeness)是通用计算机的一个属性,它表示一个程序可以写另一个程序。比如 go test 命令:它会扫描被测试的包,写一个包含测试内容的程序,然后编译运行。

    可能你听得比较多的是元编程(meta-program)。这里不细究他们的区别。我们重点是,用程序生成另一个程序的场景,越来越广泛了。比如:

    • protobufandroids: 根据 pb 文件(.proto)生成 go 代码文件(.pb.go)
    • yacc: 根据 yacc 文件(.y)生成 go 代码文件
    • bindata: 二进制文件(如 JPEG)转成 go 的 bytes 数组
    • mockery: 根据 go 的 interface 生成 Mock 对象(依赖 stretchr/testify/mock 包)。

    自动生成代码的命令,该如何集成进项目里面?一般来说,我们可以借助外部的工具,如 Make。使用 Go 1.4 新增的 g编程客栈o generate 命令,就可以避免外部工具了。

    Mockery

    我们以 mockery 为例,关于 mockery 生成的 Mock 对象,我之前的文章有介绍过:Go 库:单元测试利器 testify。

    比如我们定义了 Greeter 接口,作为 Hello 的参数(代码本身无意义,仅做示例):

    // greet.go 文件
    package greet
    type Greeter interface {
    	Greet() string
    }
    // 加上"hello"前缀
    func Hello(g Greeter) string {
    	return "hello " + g.Greet()
    }
    

    我们要给 Hello 函数写单元测试的话,就需要为 Greeter 写一个 Mock 对象。我们可以使用 mockery 来生成。

    安装 mockery:

    go install github.com/vektra/mockery/v2@latest
    

    为当前包下的所有 interface 生成 mock 对象,输出到 mocks 目录。

    mockery --output mocks/ --dir . --all
    

    我们查看目录文件:

    ➜ tree
    .
    ├── greet.go
    └── mocks             // mockery 生成的 mock 对象
        └── Greeter.go
    1 directory, 2 files
    

    关于 mockery 的说明,我们可以查看仓库:github.com/vektra/mock…。现在,我们可以为 Hello 写单元测试了:

    // greet_test.go 文件
    package greet
    import (
    	"example/greet/mocks"
    	"testing"
    	"github.com/stretchr/testify/assert"
    )
    func TestHello(t *testing.T) {
      // 实例化 mock 对象
    	greeter := new(mocks.Greeter)
      // 设置预期,当请求 greeter.Greet() 时,返回 "world"
    	greeter.On("Greet").Return("world")
    	want := "hello world"
    	got := Hello(greeter)
      // 断言相等
    	assert.Equal(t, want, got)
    }
    

    Go Generate

    我们接下来的问题是,Mockery 命令需要集成到项目里,我们可以写 shell 脚本、或者 Make 文件,但这些都不是 go tool 的工具。

    用法

    go generate 非常方便使用,只要当前目录的 .go 文件(如 greet.go 文件),加上备注:

    //go:generate mockery --output mocks/ --dir . --all
    

    我们先把刚刚生成的 mocks 目录删除,当前目录结构是:

    ➜   tree
    .
    ├js── greet.go
    └── greet_test编程客栈.go
    0 directories, 2 files
    

    然后进入 greet 包,执行 go generate:

    ➜  go generate  
    01 Dec 22 20:06 CST INF Starting mockery dry-run=false version=v2.10.0
    01 Dec 22 20:06 CST INF Walking dry-run=false version=v2.10.0
    01 Dec 22 20:06 CST INF Generating mock dry-run=false interface=Greeter qualified-name=example/greet version=v2.10.0
    

    打印目录结构,会发现 mocks 对象又生成了:

    ➜ tree
    .
    ├── greet.go
    ├── greet_test.go
    └── mocks
        └── Greeter.go
    1 directory, 3 files
    

    总结

    Rob Pike 大神在 go generate 的提案有说过,希望 go generate 能替换 go 仓库中的 Makefil编程客栈e。本人没有明显的偏向,但是 go generate 确实不失为一个优秀的工具。

    引用

    以上就是Go Generate 代替 Makefile使用方法详解的详细内容,更多关于Go Generate代替Makefile的资料请关注我们其它相关文章!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜