1 回答

TA貢獻1876條經驗 獲得超7個贊
技術說明:第一種方法向您保證(除了初始化結構時的錯誤)您可以調用methodAon Bar,第二種方法則不能,因為您必須使用與該接口相關的東西來初始化接口字段,以免出現 nil deference 錯誤。
請注意,使用第二種方法methodA不是在嵌入式對象上調用Bar ,而是在Foo嵌入對象上調用!
如果你有一個可以由許多對象共享并且是自包含的公共實現,則第二種方法很有用,即考慮你想知道一個對象是否實現了一個方法以確保你可以使用該對象記錄一些東西Log:在這種情況下你可以有一個返回 aLogger并用它設置接口字段的方法。示例如下:
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
恕我直言,方法一會強制您編寫更多代碼,但您在接口實現中更加自由,您可以通過嵌入 aLogger然后重寫結構Log中的方法來混合這兩種方法A1。
此外,您仍然可以傳遞一些東西來構建實現接口的東西:
package main
import "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")
}
- 1 回答
- 0 關注
- 122 瀏覽
添加回答
舉報