理解golang的interface主要在于以下兩點:
- interface是方法的集合
- interface是一種類型
簡單示例
package main
import "fmt"
type Animal interface {
Speak() string
}
type Cat struct{}
func (c Cat) Speak() string {
return "cat"
}
type Dog struct{}
func (d Dog) Speak() string {
return "dog"
}
func Test(params interface{}) {
fmt.Println(params)
}
func main() {
animals := []Animal{Cat{}, Dog{}}
for _, animal := range animals {
fmt.Println(animal.Speak())
}
Test("string")
Test(123)
Test(true)
}
以上代碼中,定義了Animal為接口,而Cat和Dog兩個結(jié)構(gòu)體分別實現(xiàn)了接口中定義的方法。當interface{}作為函數(shù)形參時,可以接受不同類型的參數(shù)。
指針與interface
如果將上述代碼的:
func (c Cat) Speak() string {
return "cat"
}
修改為:
func (c *Cat) Speak() string {
return "cat"
}
再次運行源代碼,就會出現(xiàn)以下錯誤:
cannot use Cat literal (type Cat) as type Animal in array or slice literal:
Cat does not implement Animal (Speak method has pointer receiver)
這是因為程序認為Cat并未實現(xiàn)Speak()方法, 而是由 *Cat 實現(xiàn)的。這說明結(jié)構(gòu)體在實現(xiàn)接口方法時并不會隱式轉(zhuǎn)換類型。
interface 數(shù)組
interface{} 作為函數(shù)形參和 []interface{} 作為形參有很大區(qū)別,示例如下:
package main
import (
"fmt"
)
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}
}
func main() {
names := []string{"stanley", "david", "oscar"}
PrintAll(names)
}
以上代碼是無法正常運行的,錯誤提示為:
cannot use names (type []string) as type []interface {} in argument to PrintAll
這說明對接口數(shù)組賦值前,必須多一個類型轉(zhuǎn)換操作,正確代碼如下:
package main
import (
"fmt"
)
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}
}
func main() {
names := []string{"stanley", "david", "oscar"}
vals := make([]interface{}, len(names))
for i, v := range names {
vals[i] = v
}
PrintAll(vals)
}
以上是關(guān)于interface使用的基礎(chǔ)內(nèi)容。