2 回答

TA貢獻1895條經驗 獲得超3個贊
不要使用指向接口類型的指針,只使用接口類型。
Queuable是一種接口類型,因此在您使用 的代碼中的任何地方*Queuable,都將其更改為Queuable. 例如:
type Queuable interface {
Next() Queuable
}
type Node struct {
value interface{}
next Queuable
}
// Next gets the next object
func (n *Node) Next() Queuable {
return n.next
}
...
在 Go 中,接口類型的值存儲一對:分配給變量的具體值,以及該值的類型描述符。
更多關于接口的內部結構:反射定律#接口的表示
所以你幾乎不需要一個指向接口的指針。一個接口包含一個鍵值對,其中鍵可以是一個指針。接口指針有意義的罕見情況是,如果您想修改傳遞給另一個函數的接口類型變量的值。
在您的示例中,該類型*Job實現了Queuable因為它有一個帶有接收器類型的方法*Job,因此在需要值的任何地方Queuable,*Job都可以使用值(并且Queuable將創建和使用類型的隱式接口值)。
回到你的例子:
您Queuable只定義了一種方法來獲取隊列中的下一個元素,但沒有定義一種方法來將它排入隊列,這將使該解決方案失去靈活性。單個Next()方法僅描述它是“排隊的”,但它不是(必然)“可排隊的”。
為了排隊,我還要添加另一種方法:SetNext(Queuable)
type Queuable interface {
Next() Queuable
SetNext(Queuable)
}
它的實現Node可以是例如:
func (n *Node) SetNext(q Queuable) { n.next = q }
在Go Playground上試試。
另請注意,Nodeand中有一些代碼重復Job,即next字段Next()和SetNext()方法。我們可以創建一個基本節點實現,例如:
type Base struct {
next Queuable
}
func (b *Base) Next() Queuable { return b.next }
func (b *Base) SetNext(q Queuable) { b.next = q }
現在您可以將這種Base類型嵌入到將“繼承”字段和方法的具體Node和Job實現中,因此您不必在和類型上定義任何這些。nextNext()SetNext()NodeJob
這是Nodeand的完整實現,Job不需要其他任何東西:
type Node struct {
*Base
value interface{}
}
type Job struct {
*Base
instruction string
}
在Go Playground上試試這個。

TA貢獻1817條經驗 獲得超6個贊
永遠不要使用指向接口類型的指針,這已經是一個指針了!
因此,要使代碼正常工作,請更改*Queuableas Queuable。
type Node struct {
value interface{}
next Queuable
}
// Next gets the next object
func (n *Node) Next() Queuable {
return n.next
}
// Job - A job for the queue
type Job struct {
instruction string
next Queuable
}
但是,您可以使用方法接收器作為指針,具體取決于結構的復雜性。雖然如果使用的 struct 類型很簡單,您可以定義使用 struct 值的方法,這種方式在內存中分配一個新地址。如果您使用方法接收器作為指針,它將引用該結構已在內存中占用的地址。
關于接收者的指針與值的規則是值方法可以在指針和值上調用,但指針方法只能在指針上調用。
出現這個規則是因為指針方法可以修改接收者;在一個值上調用它們將導致該方法接收該值的副本,因此任何修改都將被丟棄。因此,該語言不允許這種錯誤。
經驗法則是,為了一致性,最好堅持將方法定義作為指針或方法定義作為整個接口實現中的值。
- 2 回答
- 0 關注
- 168 瀏覽
添加回答
舉報