假设我有一个接口Foo,并且我要添加一个结构,该结构需要Foo的方法以及一些其他方法。在以下两种情况下,哪种才是最佳实践?或者,如果还有其他更合适的第三种方法,那就建议。
方法1
vagrant ssh
方法2
type Foo interface {
methodA()
}
type Bar struct {
}
func (b Bar) methodA () {
...
}
func (b Bar) methodB () {
...
}
此外,如果可以指出上述方法在哪种情况下更适合,那将是很好的?谢谢!
答案 0 :(得分:1)
技术说明:第一种方法向您保证(除了初始化结构中的错误),您可以在methodA
上调用Bar
,而第二种方法则不必,因为您必须在初始化接口字段时考虑到这一点界面没有nil引用错误。
请注意,不是在methodA
上调用第二种方法Bar
,而是在Foo
嵌入式对象上调用!
第二种方法很有用,如果您有一个可以被许多对象共享并且可以自我包含的通用实现,即认为您想知道某个对象是否实现了Log
方法,以确保您可以使用该方法记录某些内容对象:在这种情况下,您可以有一个返回Logger
的方法,并使用该方法设置接口字段。示例如下:
package main
import "fmt"
type Logger interface {
Log(string)
}
type ConsoleLogger struct {} // See? No external dependencies
func (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
)数据,则此方法将很尴尬,因为您必须初始化接口对象然后在某些情况下会存储一些对所需数据的引用,而这会浪费内存。
IMHO方法之一会迫使您编写更多代码,但是您在界面实现中会更加自由,可以通过嵌入Logger
并在{{1 }}结构。
此外,您可以传递一些东西来构建实现接口的东西:
Log