1. 程式人生 > 其它 >go語言介面

go語言介面

重點

介面在底層的實現有兩個部分: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
}