理解golang的interface主要在於如下兩點:golang
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 main() { animals := []Animal{Cat{}, Dog{}} for _, animal := range animals { fmt.Println(animal.Speak()) } }
以上代碼中,定義了Animal爲接口,而Cat和Dog兩個結構體分別實現了接口中定義的方法。當interface{}做爲函數形參時,能夠接受不一樣類型的參數。數組
若是將上述代碼的:函數
func (c Cat) Speak() string { return "cat" }
修改成:指針
func (c *Cat) Speak() string { return "cat" }
再次運行源代碼,就會出現如下錯誤:code
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並未實現Speak()方法, 而是由 *Cat 實現的。這說明結構體在實現接口方法時並不會隱式轉換類型。接口
可是:string
可是,把 animals := []Animal{Cat{}, Dog{}} 修改爲 animals := []Animal{&Cat{}, &Dog{}} 卻能夠執行,由於把指針做爲參數,會隱式轉換。
interface{} 做爲函數形參和 []interface{} 做爲形參有很大區別,示例以下:it
interface{} 能夠賦值任何類型的值class
package main import "fmt" func Test(params interface{}) { fmt.Println(params) } func main() { Test("string") Test(123) Test(true) }
package main import ( "fmt" ) func PrintAll(vals []interface{}) { for _, val := range vals { fmt.Println(val) } } func main() { names := []string{"stanley", "david", "oscar"} PrintAll(names) }
以上代碼是沒法正常運行的,錯誤提示爲:import
cannot use names (type []string) as type []interface {} in argument to PrintAll
這說明對接口數組賦值前,必須多一個類型轉換操做,正確代碼以下:
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) }