diff --git a/module/example_test.go b/module/example_test.go index 43ae5f0..a8246ab 100644 --- a/module/example_test.go +++ b/module/example_test.go @@ -7,20 +7,28 @@ import ( "github.com/googollee/go-espresso/module" ) -type DB struct { +type DB interface { + Target() string +} + +type db struct { target string } -func NewDB(ctx context.Context) (*DB, error) { - return &DB{ +func NewDB(ctx context.Context) (DB, error) { + return &db{ target: "localhost.db", }, nil } +func (db *db) Target() string { + return db.target +} + var ModuleDB = module.New(NewDB) type Cache struct { - fallback *DB + fallback DB } func NewCache(ctx context.Context) (*Cache, error) { @@ -51,8 +59,8 @@ func ExampleModule() { db := ModuleDB.Value(ctx) cache := ModuleCache.Value(ctx) - fmt.Println("db target:", db.target) - fmt.Println("cache fallback target:", cache.fallback.target) + fmt.Println("db target:", db.Target()) + fmt.Println("cache fallback target:", cache.fallback.Target()) // Output: // db target: localhost.db @@ -63,9 +71,9 @@ func ExampleModule_withOtherValue() { targetKey := "target" ctx := context.WithValue(context.Background(), targetKey, "target.db") - newDB := func(ctx context.Context) (*DB, error) { + newDB := func(ctx context.Context) (DB, error) { target := ctx.Value(targetKey).(string) - return &DB{ + return &db{ target: target, }, nil } @@ -94,8 +102,8 @@ func ExampleModule_withOtherValue() { _ = db _ = cache - fmt.Println("db target:", db.target) - fmt.Println("cache fallback target:", cache.fallback.target) + fmt.Println("db target:", db.Target()) + fmt.Println("cache fallback target:", cache.fallback.Target()) // Output: // db target: target.db @@ -105,8 +113,8 @@ func ExampleModule_withOtherValue() { func ExampleModule_createWithError() { ctx := context.Background() - newDB := func(ctx context.Context) (*DB, error) { - return &DB{ + newDB := func(ctx context.Context) (DB, error) { + return &db{ target: "localhost.db", }, nil } @@ -135,8 +143,8 @@ func ExampleModule_createWithError() { func ExampleModule_createWithPanic() { ctx := context.Background() - newDB := func(ctx context.Context) (*DB, error) { - return &DB{ + newDB := func(ctx context.Context) (DB, error) { + return &db{ target: "localhost.db", }, nil } @@ -183,3 +191,44 @@ func ExampleModule_notExistingProvider() { // Output: // inject error: module *module_test.Cache creates an instance error: no db as fallback } + +type FileSystem interface { + Read() + Write() +} + +type realFileSystem struct{} + +func NewRealFileSystem(context.Context) (FileSystem, error) { + return &realFileSystem{}, nil +} + +var RealFileSystem = module.New(NewRealFileSystem) + +func (f *realFileSystem) Read() {} +func (f *realFileSystem) Write() {} + +type mockFileSystem struct{} + +func NewMockFileSystem(context.Context) (FileSystem, error) { + return &mockFileSystem{}, nil +} + +var MockFileSystem = module.New(NewMockFileSystem) + +func (f *mockFileSystem) Read() {} +func (f *mockFileSystem) Write() {} + +func ExampleModule_duplicatingProviders() { + defer func() { + p := recover() + fmt.Println("panic:", p) + }() + + repo := module.NewRepo() + repo.AddModule(RealFileSystem) + repo.AddModule(MockFileSystem) + + // Output: + // panic: already exist a provider with type module_test.FileSystem +} diff --git a/module/module.go b/module/module.go index 210b34f..b42e765 100644 --- a/module/module.go +++ b/module/module.go @@ -4,7 +4,7 @@ package module import ( "context" - "fmt" + "reflect" ) // BuildFunc is the constructor of an Instance. @@ -30,7 +30,7 @@ type Module[T any] struct { func New[T any](builder BuildFunc[T]) Module[T] { var t T return Module[T]{ - moduleKey: moduleKey(fmt.Sprintf("%T", t)), + moduleKey: moduleKey(reflect.TypeOf(&t).Elem().String()), builder: builder, } } diff --git a/module/repo.go b/module/repo.go index 524cf2c..4049d2e 100644 --- a/module/repo.go +++ b/module/repo.go @@ -21,6 +21,9 @@ func NewRepo() *Repo { // AddModule adds a module to the repo. // Module always implements Provider, so a module can be added directly. func (r *Repo) AddModule(provider Provider) { + if _, ok := r.providers[provider.key()]; ok { + panic("already exist a provider with type " + provider.key()) + } r.providers[provider.key()] = provider }