我正在为我正在编写的玩具包编写规范,虽然大部分规范都保证包中的各种结构满足主要的公共接口,但我也有兴趣指定接口必须要求的方法;我知道这有点迂腐,但我认为这将是一个巧妙的实验,并且会施加压力以保持公共界面的稳定。
这是我的第一次尝试:
type Roller interface {
Min() int
}
type minS struct {}
func (m minS) Min() int {return 0}
func (m minS) Max() int {return 0}
func RollerSpec(c gospec.Context) {
var r Roller = minS{}
c.Specify("has a minimum value.", func() {
_, ok := r.(interface{Min() int})
c.Expect(ok, Equals, true)
})
c.Specify("has a maximum value.", func() {
_, ok := r.(interface{Max() int})
c.Expect(ok, Equals, true)
})
c.Specify("has an expected value.", func() {
_, ok := r.(interface{Exp() int})
c.Expect(ok, Equals, true)
})
c.Specify("can be rolled.", func() {
_, ok := r.(interface{Roll() int})
c.Expect(ok, Equals, true)
})
}
如您所见,我的Roller
界面只需要Min()
但同时minS
实现了Min()
和Max()
。我通过了前两个规范,即使Runner
不满足interface{Max() int}
因为我用来测试它的虚拟类型。同样,在没有基类型的情况下声明 r 会导致它无法满足所有规范。
很明显,为什么 Go 会在接口之间对实际存储的类型进行类型断言,但这不是我在这里寻找的。我还检查了反射包,但它似乎也只检查结构。有没有办法以编程方式检查接口是否需要给定的方法,而无需自己拉入解析包并爬取解析树以获取方法名称?