簡單的介面
在 Go 中,介面只是一組方法。我們使用介面來指定給定物件的行為。
type Painter interface {
Paint()
}
實現型別不需要宣告它正在實現介面。定義相同簽名的方法就足夠了。
type Rembrandt struct{}
func (r Rembrandt) Paint() {
// use a lot of canvas here
}
現在我們可以將結構用作介面。
var p Painter
p = Rembrandt{}
可以通過任意數量的型別來滿足(或實現)介面。型別也可以實現任意數量的介面。
type Singer interface {
Sing()
}
type Writer interface {
Write()
}
type Human struct{}
func (h *Human) Sing() {
fmt.Println("singing")
}
func (h *Human) Write() {
fmt.Println("writing")
}
type OnlySinger struct{}
func (o *OnlySinger) Sing() {
fmt.Println("singing")
}
這裡,Human
結構同時滿足 Singer
和 Writer
介面,但 OnlySinger
結構只滿足 Singer
介面。
空介面
有一個空的介面型別,它不包含任何方法。我們宣告它為 interface{}
。這不包含任何方法,因此每個 type
都滿足它。因此,空介面可以包含任何型別值。
var a interface{}
var i int = 5
s := "Hello world"
type StructType struct {
i, j int
k string
}
// all are valid statements
a = i
a = s
a = &StructType{1, 2, "hello"}
介面最常見的用例是確保變數支援一個或多個行為。相比之下,空介面的主要用例是定義一個可以儲存任何值的變數,而不管其具體型別如何。
要將這些值恢復為原始型別,我們只需要這樣做
i = a.(int)
s = a.(string)
m := a.(*StructType)
要麼
i, ok := a.(int)
s, ok := a.(string)
m, ok := a.(*StructType)
ok
表示 interface a
是否可轉換為給定型別。如果不可能施展 ok
將是 false
。
介面值
如果宣告介面的變數,它可以儲存實現介面宣告的方法的任何值型別!
如果我們宣告 interface Singer
的 h
,它可以儲存 Human
或 OnlySinger.
型別的值。這是因為它們都實現了 Singer
介面指定的方法。
var h Singer
h = &human{}
h.Sing()