英文:
Go: Optional methods in an interface
问题
我正在进行一个严重依赖于基础代码库的项目。在基础代码中,定义了一个接口(这里进行了简化),名为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
}
对于我们的项目,现在有一个第三种事件类型(例如eventTypeC),它是我们项目独有的。一种方法是在基础类中添加第三个接口定义(eventHookTypeC),并在我们自己的项目代码中相应地实现。然而,我们的CI环境也会使用这个新版本的Baselibrary.go构建所有其他项目,但它们将缺乏eventHookTypeC的实现而导致构建失败。
除了更改我们的构建环境或存储库之外,是否有一种Go的解决方法,可以在不更改其他项目的代码的情况下解决这个问题?
英文:
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?
答案1
得分: 12
你可以使用与http.Pusher
或io.Closer
类似的方式来实现。你需要创建一个新的接口,其中包含“可选”的方法,并传递原始接口。当你想要执行可选方法时,你可以使用类型断言来检查你拥有的值是否实现了其他接口,如果实现了,则调用该方法。
type eventHandle interface {
eventHookTypeA
eventHookTypeB
// 不要添加 TypeC 接口。
someOtherMethod() results
}
type eventHookTypeA interface {
// 方法定义
HandleEventA() results
}
type eventHookTypeB interface {
// 方法定义
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("发生了一些问题")
}
}
return nil
}
希望对你有帮助!
英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论