I am working on a project that heavily depends on a base code-base. In the base code, there is an interface defined (simplified here) called eventWatcher
//Baselibrary.go:
package base
type eventHandle interface {
eventHookTypeA
eventHookTypeB
someOtherMethod() results
}
type eventHookTypeA interface {
// method definitions
HandleEventA() results
}
type eventHookTypeB interface {
// method definitions
HandleEventB() results
}
func handleEvents(eventType string, handle eventHandle) results {
if eventType == "eventA" {
return handle.HandleEventA()
} else if eventType == "eventB" {
return handle.HandleEventB()
}
return nil
}
For our project, we now havee a third event type (ex. eventTypeC) that is exclusive to our project. One way is to just add a third interface definition (eventHookTypeC) in the base class and implement accordingly in our own project code. However our CI environment will also take this new version of Baselibrary.go and build all other projects with it, which will fail because of they will lack impl of eventHookTypeC.
Aside from changing our build environments or repo, is there a Go workaround to this without having to change code for the other projects?
You can do it the same way it's done with e.g. http.Pusher
or io.Closer
. You create a new interface with the "optional" method, and pass around the original interface. When you want to execute the optional method, you use a type assertion to check if the value you have implements the other interface, and if it does, call the method.
type eventHandle interface {
eventHookTypeA
eventHookTypeB
// DON'T add TypeC interface.
someOtherMethod() results
}
type eventHookTypeA interface {
// method definitions
HandleEventA() results
}
type eventHookTypeB interface {
// method definitions
HandleEventB() results
}
type eventHookTypeC interface {
HandleEventC() results
}
func handleEvents(eventType string, handle eventHandle) results {
if eventType == "eventA" {
return handle.HandleEventA()
} else if eventType == "eventB" {
return handle.HandleEventB()
} else if eventType == "eventC" {
if c,ok := handle.(eventHookTypeC); ok {
return c.HandleEventC()
} else {
log.Println("somewhat bad happen")
}
}
return nil
}