Created
April 21, 2022 23:42
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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