golang使用模板生成接口装饰器插件GoWrap的使用
GoWrap - Golang 接口装饰器生成工具
GoWrap 是一个命令行工具,它使用简单的模板为 Go 接口类型生成装饰器。通过 GoWrap,您可以轻松地在现有代码中添加指标、跟踪、回退、池等多种功能,只需几秒钟。
安装
CLI 安装
go install github.com/hexdigest/gowrap/cmd/gowrap@latest
作为模块安装
go get -u github.com/hexdigest/gowrap/cmd/gowrap
使用示例
基本使用
gowrap gen -p io -i Reader -t prometheus -o reader_with_metrics.go
这将为 io.Reader 接口生成一个包装了 Prometheus 指标的实现。
为本地包生成装饰器
gowrap gen -p ./connector -i Connector -t fallback -o ./connector/with_metrics.go
这将为 ./connector 子包中的 Connector 接口生成一个回退装饰器。
完整示例
下面是一个完整的示例,展示如何使用 GoWrap 为自定义接口生成装饰器:
- 首先定义一个接口:
// storage.go
package storage
type ItemStorage interface {
GetItem(id string) (*Item, error)
PutItem(item *Item) error
DeleteItem(id string) error
}
- 使用 GoWrap 生成带有日志记录的装饰器:
gowrap gen -p ./storage -i ItemStorage -t log -o storage_with_logging.go
- 生成的代码可以这样使用:
package main
import (
"log"
"os"
"./storage"
)
func main() {
// 原始实现
var baseStorage storage.ItemStorage = &storage.MyStorageImplementation{}
// 包装后的实现
loggedStorage := storage.NewItemStorageLogger(
baseStorage,
log.New(os.Stdout, "[storage] ", log.LstdFlags),
)
// 使用包装后的实现
item, err := loggedStorage.GetItem("123")
if err != nil {
log.Fatal(err)
}
// ...
}
内置模板
GoWrap 提供了多种内置模板:
circuitbreaker
: 在指定数量的连续错误后停止执行包装接口的方法,并在指定延迟后恢复执行fallback
: 接受源接口的多个实现,如果前一次尝试未在指定时间内返回结果,则并发运行每个实现log
: 使用标准日志包为源接口添加日志记录logrus
: 使用流行的 sirupsen/logrus 日志记录器为源接口添加日志记录prometheus
: 为源接口添加 Prometheus 指标retry
: 为源接口添加重试机制timeout
: 为每个接受上下文的方法添加可配置的超时
自定义模板
您可以编写自己的模板来为接口提供所需的功能。模板接收的结构信息由 TemplateInputs
结构体记录。
模板中可以使用以下自定义函数:
up
: 返回所有字母大写的输入down
: 返回所有字母小写的输入upFirst
: 返回首字母大写的输入downFirst
: 返回首字母小写的输入replace
: 返回用第二个参数替换第一个参数所有出现的输入snake
: 返回输入的下划线表示形式
本地化模板
默认情况下,GoWrap 会在生成的代码中包含 //go:generate
指令。如果您使用了远程模板,可以将模板复制到本地文件:
gowrap template copy fallback templates/fallback
然后使用本地模板生成装饰器:
gowrap gen -p io -i Reader -t templates/fallback reader_with_fallback.go
GoWrap 是一个强大的工具,可以显著减少为接口添加横切关注点所需的样板代码量。通过使用模板系统,它可以灵活地适应各种需求。
更多关于golang使用模板生成接口装饰器插件GoWrap的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang使用模板生成接口装饰器插件GoWrap的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GoWrap: 使用模板生成接口装饰器的Go工具
GoWrap是一个用于生成接口装饰器代码的Go工具,它通过模板驱动的方式自动为接口生成装饰器实现。下面我将详细介绍GoWrap的使用方法和示例代码。
安装GoWrap
首先安装GoWrap工具:
go install github.com/hexdigest/gowrap@latest
基本使用
1. 定义接口
假设我们有一个简单的接口:
// storage.go
package main
type Storage interface {
Get(key string) ([]byte, error)
Set(key string, value []byte) error
Delete(key string) error
}
2. 生成装饰器
使用GoWrap为这个接口生成装饰器:
gowrap gen -p . -i Storage -t log -o storage_decorator.go
参数说明:
-p
指定包路径-i
指定接口名-t
指定模板(这里是log)-o
输出文件名
3. 生成的装饰器代码
生成的storage_decorator.go
文件会包含一个实现了Storage
接口的结构体,并添加了日志功能:
// storage_decorator.go
package main
import (
"log"
)
type StorageWithLog struct {
base Storage
}
func NewStorageWithLog(base Storage) StorageWithLog {
return StorageWithLog{
base: base,
}
}
func (d StorageWithLog) Get(key string) ([]byte, error) {
log.Printf("Storage.Get called with key: %v", key)
defer log.Printf("Storage.Get returned with key: %v", key)
return d.base.Get(key)
}
func (d StorageWithLog) Set(key string, value []byte) error {
log.Printf("Storage.Set called with key: %v", key)
defer log.Printf("Storage.Set returned with key: %v", key)
return d.base.Set(key, value)
}
func (d StorageWithLog) Delete(key string) error {
log.Printf("Storage.Delete called with key: %v", key)
defer log.Printf("Storage.Delete returned with key: %v", key)
return d.base.Delete(key)
}
自定义模板
GoWrap的强大之处在于可以使用自定义模板。创建一个模板文件metrics.tmpl
:
// 自定义指标监控装饰器模板
package {{.Package}}
import (
"time"
"github.com/prometheus/client_golang/prometheus"
)
type {{.Interface}}WithMetrics struct {
base {{.Interface}}
requestCount *prometheus.CounterVec
requestDuration *prometheus.HistogramVec
}
func New{{.Interface}}WithMetrics(
base {{.Interface}},
requestCount *prometheus.CounterVec,
requestDuration *prometheus.HistogramVec,
) *{{.Interface}}WithMetrics {
return &{{.Interface}}WithMetrics{
base: base,
requestCount: requestCount,
requestDuration: requestDuration,
}
}
{{range .Methods}}
func (d *{{$.Interface}}WithMetrics) {{.Name}}({{.Params}}) {{.Results}} {
start := time.Now()
d.requestCount.WithLabelValues("{{.Name}}").Inc()
defer func() {
d.requestDuration.WithLabelValues("{{.Name}}").Observe(time.Since(start).Seconds())
}()
{{if .ReturnsError}}return {{end}}d.base.{{.Name}}({{.ArgNames}})
}
{{end}}
然后使用自定义模板生成装饰器:
gowrap gen -p . -i Storage -t metrics.tmpl -o storage_metrics_decorator.go
常用模板
GoWrap提供了一些内置模板:
log
- 添加日志记录sync
- 添加互斥锁retry
- 添加重试逻辑fallback
- 添加回退逻辑circuit
- 添加熔断器模式
实际应用示例
package main
import (
"log"
)
func main() {
// 原始实现
realStorage := &RealStorage{}
// 添加日志装饰器
loggedStorage := NewStorageWithLog(realStorage)
// 使用装饰后的接口
err := loggedStorage.Set("key", []byte("value"))
if err != nil {
log.Fatal(err)
}
data, err := loggedStorage.Get("key")
if err != nil {
log.Fatal(err)
}
log.Printf("Got data: %s", data)
}
// 实际存储实现
type RealStorage struct{}
func (s *RealStorage) Get(key string) ([]byte, error) {
return []byte("data for " + key), nil
}
func (s *RealStorage) Set(key string, value []byte) error {
return nil
}
func (s *RealStorage) Delete(key string) error {
return nil
}
总结
GoWrap是一个强大的工具,可以:
- 通过模板自动生成装饰器代码
- 减少重复的样板代码
- 保持代码整洁和可维护性
- 方便地添加横切关注点(日志、监控、重试等)
通过合理使用GoWrap,你可以更专注于业务逻辑的实现,而将通用的装饰逻辑交给工具自动生成。