Golang 中的指標接收器和介面實作
在 Go 中,接收器函數允許方法對特定類型進行操作。當方法具有指標接收器時,它可以修改結構體的實際實例。
理解問題
考慮以下程式碼片段:
type IFace interface { SetSomeField(newValue string) GetSomeField() string } type Implementation struct { someField string } // Method with non-pointer receiver func (i Implementation) GetSomeField() string { return i.someField } // Method with non-pointer receiver func (i Implementation) SetSomeField(newValue string) { i.someField = newValue }
在此程式碼中,兩種方法都有非指標接收器。這意味著當呼叫 SetSomeField 時,它會建立該結構的副本並修改該副本。原始實例保持不變。
使用指標接收器
要更改實際實例,SetSomeField 方法應該有一個指標接收器:
// Method with pointer receiver func (i *Implementation) SetSomeField(newValue string) { i.someField = newValue }
現在,SetSomeField 可以修改原始實例了。然而,這在實作 IFace 介面時會引發一個問題:
package main import ( "fmt" ) type IFace interface { SetSomeField(newValue string) GetSomeField() string } type Implementation struct { someField string } // Method with pointer receiver func (i *Implementation) GetSomeField() string { return i.someField } // Method with pointer receiver func (i *Implementation) SetSomeField(newValue string) { i.someField = newValue } func Create() IFace { obj := Implementation{someField: "Hello"} return obj // Offending line } func main() { a := Create() // Assigning an Implementation value to an IFace variable a.SetSomeField("World") // Will panic because a is an Implementation value, not a pointer fmt.Println(a.GetSomeField()) }
編譯此程式碼會導致恐慌,因為 Create 傳回一個 Implement 值,而不是指向它的指標。若要使用指標接收器實作接口,必須將方法宣告為指標接收器,且 Create 函數必須傳回指向 Implements 的指標。
type IFace interface { SetSomeField(newValue string) GetSomeField() string } type Implementation struct { someField string } // Method with pointer receiver func (i *Implementation) GetSomeField() string { return i.someField } // Method with pointer receiver func (i *Implementation) SetSomeField(newValue string) { i.someField = newValue } func Create() *Implementation { obj := Implementation{someField: "Hello"} return &obj } func main() { var a IFace a = Create() // Now assigning a pointer to Implementation to an IFace variable a.SetSomeField("World") fmt.Println(a.GetSomeField()) }
現在,a 是指向 Implements 值的指針,它使用指針接收器實作 IFace。透過 SetSomeField 所做的變更將影響原始實例。
以上是為什麼在 Go 介面實作中使用指標接收器需要返回指標?的詳細內容。更多資訊請關注PHP中文網其他相關文章!