猿问

如何在使用 golang 中现有接口的同时添加更多功能?

假设我有一个接口 Foo,我正在添加一个结构,它需要 Foo 的方法和一些额外的方法。在那种情况下,以下两个被认为是最佳实践?或者如果有其他更合适的第三种方式,那么请提出建议。


方法一


type Foo interface {

   methodA()

}


type Bar struct {

}


func (b Bar) methodA () {

   ...

}


func (b Bar) methodB () {

   ...

}

方法二


type Foo interface {

   methodA()

}


type Bar struct {

   Foo    // this can be initialized with any concrete implementation of Foo

}


func (b Bar) methodB () {

   ...

}

另外,如果能指出上述方法更适合哪些场景,那就太好了?谢谢!


慕丝7291255
浏览 75回答 1
1回答

幕布斯6054654

技术说明:第一种方法向您保证(除了初始化结构时的错误)您可以调用methodAon Bar,第二种方法则不能,因为您必须使用与该接口相关的东西来初始化接口字段,以免出现 nil deference 错误。请注意,使用第二种方法methodA不是在嵌入式对象上调用Bar ,而是在Foo嵌入对象上调用!如果你有一个可以由许多对象共享并且是自包含的公共实现,则第二种方法很有用,即考虑你想知道一个对象是否实现了一个方法以确保你可以使用该对象记录一些东西Log:在这种情况下你可以有一个返回 aLogger并用它设置接口字段的方法。示例如下:package mainimport "fmt"type Logger interface {    Log(string)}type ConsoleLogger struct {} // See? No external dependenciesfunc (Cl ConsoleLogger) Log(msg string) {    fmt.Println(msg)}type A1 struct {    Logger}type A2 struct {    Logger}func main() {    a := A1{ConsoleLogger{}}    b := A2{ConsoleLogger{}}    a.Log("Test")    b.Log("Test")}嵌入对象对于调度方法调用很有用,请记住它最终只是语法糖,所以除了传递包含对象之外,您没有任何方法可以使用它的字段。如果接口必须以某种方式使用外部对象 ( 和 ) 数据,那么此方法会很尴尬,因为您必须初始化接口对象,然后在某些情况下会浪费内存来存储对所需数据的一些Logger引用A1。A2恕我直言,方法一会强制您编写更多代码,但您在接口实现中更加自由,您可以通过嵌入 aLogger然后重写结构Log中的方法来混合这两种方法A1。此外,您仍然可以传递一些东西来构建实现接口的东西:package mainimport "fmt"type Logger interface {    Log(string)}type ConsoleLogger struct {    Prepend string // string to prepend to log message}func (Cl ConsoleLogger) Log(msg string) {    fmt.Println(Cl.Prepend + "-" + msg)}type A1 struct {    Logger}type A2 struct {    Logger}func (a A2) Log(msg string) { // Overriding implementation    fmt.Println("In A2")    a.Logger.Log(msg) // Call the original interface value!}func main() {    a := A1{ConsoleLogger{"A1"}}    b := A2{ConsoleLogger{"A2"}}    a.Log("Test")    b.Log("Test")}
随时随地看视频慕课网APP

相关分类

Go
我要回答