Skip to content

Instantly share code, notes, and snippets.

@IronSavior
Created April 21, 2022 23:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IronSavior/f956b3f11b2a8961bc103f45e2186ca2 to your computer and use it in GitHub Desktop.
Save IronSavior/f956b3f11b2a8961bc103f45e2186ca2 to your computer and use it in GitHub Desktop.
It is possible for an interface to be un-satisfied by a superset interface value (and this is dumb)
package main
///
/// Genderated code:
///
type GeneratedQueries interface {
A() error
B() error
}
// Low-level DB client
type impl struct{}
func (impl) A() error { return nil }
func (impl) B() error { return nil }
func (impl) BeginTx() txImpl { return txImpl{} }
// Low-level DB transaction
type txImpl struct{}
func (txImpl) A() error { return nil }
func (txImpl) B() error { return nil }
func (txImpl) Commit() error { return nil }
func (txImpl) Rollback() error { return nil }
func NewImpl() impl {
return impl{}
}
///
/// End generated code
///
// Methods manually added to generated types
func (impl) AcquireLock() error { return nil }
func (txImpl) AcquireLock() error { return nil }
func (impl) ReleaseLock() {}
func (txImpl) ReleaseLock() {}
// An interface for the added methods
type Locker interface {
AcquireLock() error
ReleaseLock()
}
// Combining both generated and manually defined methods in one interface
type Operations interface {
GeneratedQueries
Locker
}
// A client has operations and can also initiate a transaction
type Client interface {
Operations
BeginTx() TxClient
}
// A transaction client has operations and can terminate its transaction
type TxClient interface {
Operations
Commit() error
Rollback() error
}
// Implements Client
type dbClient struct{ impl }
func (dbClient) BeginTx() TxClient { return txImpl{} }
func NewClient() Client {
return dbClient{NewImpl()}
}
///// The application only needs a subset of the DB operations:
// AppQueries is a sub-set of Operations
type AppQueries interface {
Locker
A() error
}
// Store is a subset of Client
type Store interface {
AppQueries
BeginTx() TxStore
}
// TxStore is a subset of TxClient
type TxStore interface {
AppQueries
Commit() error
Rollback() error
}
// App depends on a Store
type App struct {
Store
}
func main() {
c := App{
// Compiler complains that a Client can't be used here because Client.BeginTx() returns TxClient
// and Store.BeginTx() returns TxStore despite the fact TxClient implements TxStore. This is stupid.
Store: NewClient(),
}
if c.AcquireLock() != nil {
panic("hell to naw naw")
}
defer c.ReleaseLock()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment