GO转移工具: ifacecodegen的实例

89 阅读2分钟

类似于 counterfeiter我们使用另一个工具,叫做 ifacecodegen的工具,它允许我们使用Go模板从接口定义中自动生成代码。

ifacecodegen 是用来生成满足接口类型的代码,并包装实现所述接口的现有类型,想想看,中间件代码将用于记录目的(使用logurs)或收集指标(使用NewRelic)。

例如,假设你有遵循DDD范式的代码(其中有一个存储库/数据存储和某种服务/用例)。

// User ...
type User struct {
	Role string
}

// UserFinder finds an existing User from a remote data store.
type UserFinder interface {
	Find(id int64) (User, error)
}

// UserValidator determines if the requested user has specific roles.
type UserValidator struct {
	f UserFinder
}

// NewUserValidator ...
func NewUserValidator(f UserFinder) UserValidator {
	return UserValidator{f}
}

// IsAdmin determines if the user with the specified id is an admin.
func (v *UserValidator) IsAdmin(id int64) (bool, error) {
	u, _ := v.f.Find(id) // XXX error validation omitted
	if u.Role == "admin" {
		return true, nil
	}
	return false, nil
}

// IsGuest determines if the user with the specified id is a guest.
func (v *UserValidator) IsGuest(id int64) (bool, error) {
	u, _ := v.f.Find(id) // XXX error validation omitted
	if u.Role == "guest" {
		return true, nil
	}
	return false, nil
}

而且你打算添加日志支持,以确定在调用远程数据存储方法时每个方法需要多长时间,你需要做两件事。

  1. 实现一个模板,做你想实现的事情,和
  2. 添加一个 generate指令来生成该文件。

对于第一件事,即模板,那个的内容将看起来像。

type logger{{ .Name }} struct {
  s {{ .Name }}
}

func NewLogger{{ .Name }}(s {{ .Name }}) {{ .Name }} {
  return &logger{{ .Name }}{
    s: s,
  }
}

{{ $ifaceRef := . }}
{{ range .Methods }}
  func (m *logger{{ $ifaceRef.Name }}) {{ .Name }}({{ input_parameters . }}) {{ $methodRef := . }}{{ output_parameters . }} {
    now := time.Now()
    defer func() {
      log.Printf("%s took %s", "{{ .Name }}", time.Since(now))
    }()

    {{ return . }} m.s.{{ .Name }}({{ input_calls . }})
  }
{{ end }}

最后,添加以下指令。

//go:generate ifacecodegen -source main.go -template logger.tmpl -destination logger.gen.go -package main

通过生成的代码,我们应该仍然能够满足UserFinder 所定义的契约,并增加对日志的支持!

$ ./ifacecodegen-example
2019/07/17 23:28:09 Find took 100.109011ms
2019/07/17 23:28:10 Find took 200.418756ms

显然,这个例子是非常简单的,但是想象一下,当你有数百个数据存储方法,并且需要为所有这些方法收集指标时,你将节省的真正的人力时间!

请随意浏览完整的程序并玩一玩!

ifacecodegen 是一个简单而强大的工具,强烈推荐。