3 ms·
The thing is, implicit interfaces give you so much freedom and make it so easy to keep your code decoupled, that the very rare times that you hit something like
by NateDad 11y ago
The thing is, implicit interfaces give you so much freedom and make it so easy to keep your code decoupled, that the very rare times that you hit something like this Next() problem, you just work around it and accept it as a cost for all the other benefits it brings.
For the record, in Juju we have hundreds of interfaces and hundreds of thousands of lines of code, and AFAIK have never had this be a problem.
For the given Next problem, you can easily make a wrapper type that simply masks the underlying Next() method with its own implementation.
type MyType struct {}
func (m *MyType) Next(i int) {
// do base next stuff
}
type ForSql struct {
*MyType
}
func (f ForSql) Next() bool {
// do sql-next stuff
}
and then using this type is trivial in-code:
mt := &MyType{}
doSomeSqlThing(ForSql{mt})
Note that this new type retains all the methods of the original type, so it still implements all the interfaces it used to (unless they rely on the old Next signature).
Compare this to the benefits of implicit interfaces (decoupled code, easy composition, using third party code as your own interface type without needing a wrapper type)... hopefully it's pretty obvious this is a large net positive.