go語言介面
阿新 • • 發佈:2022-03-26
重點
介面在底層的實現有兩個部分:type 和 data。
在原始碼中,顯式地將 nil 賦值給介面時,介面的 type 和 data 都將為 nil。此時,介面與 nil 值判斷是相等的。但如果將一個帶有型別的 nil 賦值給介面時,只有 data 為 nil,而 type 為 nil,此時,介面與 nil 判斷將不相等。
nil 在 Go語言中只能被賦值給指標和介面。
因此,go 語言中的 nil,是不一定相等,因為介面的 nil 和型別的 nil 在資料結構上一樣,但是值不一樣.
介面與 nil 不相等
下面程式碼使用 MyImplement() 實現 fmt 包中的 Stringer 介面,這個介面的定義如下:
type Stringer interface {
String() string
}
在 GetStringer() 函式中將返回這個介面。通過 *MyImplement
指標變數置為 nil 提供 GetStringer 的返回值。在 main()
中,判斷 GetStringer 與 nil 是否相等,程式碼如下:
package main import "fmt" // 定義一個結構體 type MyImplement struct{} // 實現fmt.Stringer的String方法 func (m *MyImplement) String() string { return "hi" } // 在函式中返回fmt.Stringer介面 func GetStringer() fmt.Stringer { // 賦nil,這句話只是說明 data 為 nil,但是 type 帶有 *MyImplement 資訊 var s *MyImplement = nil // 返回變數 //s 變數此時被 fmt.Stringer 介面包裝後,實際型別為 *MyImplement,值為 nil 的介面 return s } func main() { // 判斷返回值是否為nil if GetStringer() == nil { fmt.Println("GetStringer() == nil") } else { //使用 GetStringer() 的返回值與 nil 判斷時,雖然接口裡的 value 為 nil,但 type 帶有 *MyImplement 資訊,使用 == 判斷相等時,依然不為 nil。 fmt.Println("GetStringer() != nil") } }
發現 nil 型別值返回時直接返回 nil
為了避免這類誤判的問題,可以在函式返回時,發現帶有 nil 的指標時直接返回 nil,程式碼如下:
func GetStringer() fmt.Stringer {
var s *MyImplement = nil
if s == nil {
return nil
}
return s
}