I'm writing a specification for a toy package I'm writing, and while most of the spec is guaranteeing that various structs in the package satisfy the primary public interface, I am also interested in specifying the methods that the interface must require; I know this is more than a little pedantic, but I figured it would be a neat experiment, and would apply pressure to keep the public interface stable.
This is my first try:
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)
})
}
As you can see, my Roller
interface only requires Min()
but minS
implements both Min()
and Max()
. I pass the first two specs, even though Runner
doesn't satisfy interface{Max() int}
because the dummy type I use to test it does. Likewise, declaring r without a base type causes it to fail all specs.
It is obvious why Go would have type assertion between interfaces work on the actual stored type, but it's not what I'm looking for here. I've also checked the reflect package, but it seems like it only inspects structs as well. Is there a way to programmatically check whether an interface requires a given method without pulling in the parse package myself and crawling the parse tree for the method name?