The Application interface has been enhanced with three new methods to support the enhanced service registry functionality:
// New methods added in v1.11.1
GetServicesByModule(moduleName string) []string
GetServiceEntry(serviceName string) (*ServiceRegistryEntry, bool)
GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntryIf you have custom implementations of the Application interface (e.g., for testing), you'll need to add these methods:
import "reflect"
type MockApplication struct {
// ... existing fields
}
// Add these new methods to satisfy the updated Application interface
func (m *MockApplication) GetServicesByModule(moduleName string) []string {
return []string{} // Return empty slice for mock
}
func (m *MockApplication) GetServiceEntry(serviceName string) (*ServiceRegistryEntry, bool) {
return nil, false // Return not found for mock
}
func (m *MockApplication) GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntry {
return nil // Return empty for mock
}If you have decorator patterns around the Application interface, ensure they delegate to the underlying implementation:
type ApplicationDecorator struct {
app Application
}
func (d *ApplicationDecorator) GetServicesByModule(moduleName string) []string {
return d.app.GetServicesByModule(moduleName)
}
func (d *ApplicationDecorator) GetServiceEntry(serviceName string) (*ServiceRegistryEntry, bool) {
return d.app.GetServiceEntry(serviceName)
}
func (d *ApplicationDecorator) GetServicesByInterface(interfaceType reflect.Type) []*ServiceRegistryEntry {
return d.app.GetServicesByInterface(interfaceType)
}Version v1.11.1 also fixes panics that could occur when modules provide services with nil instances during interface-based dependency resolution. The framework now gracefully handles these cases:
- Services with
nilinstances are skipped during interface matching - Nil type checking is performed before reflection operations
- Logger calls are protected against nil loggers
To avoid issues with nil service instances:
-
Validate service instances before registration:
func (m *MyModule) ProvidesServices() []ServiceProvider { if m.serviceInstance == nil { return []ServiceProvider{} // Don't provide nil services } return []ServiceProvider{{ Name: "myService", Instance: m.serviceInstance, }} }
-
Use proper error handling in module initialization:
func (m *MyModule) Init(app Application) error { if m.requiredDependency == nil { return fmt.Errorf("required dependency not available") } return nil }
-
Test your modules with the new interface methods:
func TestModuleWithEnhancedRegistry(t *testing.T) { app := modular.NewStdApplication(nil, logger) module := &MyModule{} app.RegisterModule(module) err := app.Init() require.NoError(t, err) // Test the new interface methods services := app.GetServicesByModule("myModule") // ... verify services }