Go:接口中的可选方法

huangapple go评论86阅读模式
英文:

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.Pusherio.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
 }

huangapple
  • 本文由 发表于 2017年6月16日 05:45:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/44577539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定