Go新手封装dig服务容器接口出现Invoke方法不兼容,该如何正确声明?
问题原因
- Go语言的接口实现是隐式匹配,要求方法的签名完全一致,包括可变参数的类型。
- 你定义的
Container接口中,Invoke方法的可变参数是...interface{}类型,而dig.Container的Invoke方法可变参数是...dig.InvokeOption类型,二者类型不匹配,因此会报实现不兼容的错误,Provide方法同理也存在相同问题。
解决方案
提供两种适配方案,可根据你的使用场景选择:
方案1:接口直接匹配dig的方法签名(适合不打算替换容器实现的场景)
直接调整接口定义,把可变参数的类型和dig官方定义对齐:
import "go.uber.org/dig" type Container interface { Provide(constructor interface{}, opts ...dig.ProvideOption) error Invoke(function interface{}, opts ...dig.InvokeOption) error }
该方案无需额外封装,直接可以用*dig.Container实例赋值给你的Container接口变量。
方案2:通用抽象适配(适合需要兼容多种容器实现、不想绑定dig依赖的场景)
定义适配器结构体,封装底层的dig容器,手动实现你定义的Container接口,在方法内部做参数类型转换:
import ( "fmt" "go.uber.org/dig" ) // DigAdapter 适配dig容器到自定义Container接口 type DigAdapter struct { container *dig.Container } func NewDigAdapter() *DigAdapter { return &DigAdapter{ container: dig.New(), } } func (d *DigAdapter) Provide(constructor interface{}, opts ...interface{}) error { var digOpts []dig.ProvideOption for _, opt := range opts { digOpt, ok := opt.(dig.ProvideOption) if !ok { return fmt.Errorf("invalid provide option type: %T", opt) } digOpts = append(digOpts, digOpt) } return d.container.Provide(constructor, digOpts...) } func (d *DigAdapter) Invoke(function interface{}, opts ...interface{}) error { var digOpts []dig.InvokeOption for _, opt := range opts { digOpt, ok := opt.(dig.InvokeOption) if !ok { return fmt.Errorf("invalid invoke option type: %T", opt) } digOpts = append(digOpts, digOpt) } return d.container.Invoke(function, digOpts...) }
使用的时候直接把*DigAdapter实例传给需要application.Container的位置即可。
内容的提问来源于stack exchange,提问作者maxgu
相关产品推荐
相关产品推荐

