接口類型是對其它類型行爲的抽象和歸納;由於接口類型不會和特定的實現細節綁定在一塊兒,經過這種抽象的方式咱們可讓咱們的函數更加靈活和更具備適應能力。函數
不少面向對象的語言都有類似的接口概念,但Go語言中接口類型的獨特之處在於它是知足隱式實現的。也就是說,咱們沒有必要對於給定的具體類型定義全部知足的接口類型;簡單地擁有一些必需的方法就足夠了。這種設計可讓你建立一個新的接口類型知足已經存在的具體類型卻不會去改變這些類型的定義;當咱們使用的類型來自於不受咱們控制的包時這種設計尤爲有用。設計
接口(interface)定義了一個對象的行爲規範,只定義規範不實現,由具體的對象來實現規範的細節。接口類型是一種抽象的類型。它不會暴露出它所表明的對象的內部值的結構和這個對象支持的基礎操做的集合;它們只會展現出它們本身的方法。也就是說當你有看到一個接口類型的值時,你不知道它是什麼,惟一知道的就是能夠經過它的方法來作什麼。指針
package main import "fmt" type canSay interface{ Say() } type dog struct { name string } type cat struct { name string } func (d dog) Say() { fmt.Println(d.name,"say") } func main() { var tom2 canSay tom := dog{name: "湯姆"} tom2 = tom tom2.Say() // 湯姆 say mi := cat{name: "貓咪"} tom2 = mi // 報錯 由於cat沒有實現接口規定的say方法 }
接口值,由兩個部分組成,一個具體的類型和那個類型的值。它們被稱爲接口的動態類型和動態值。在咱們的概念模型中,一些提供每一個類型信息的值被稱爲類型描述符,好比類型的名稱和方法。在一個接口值中,類型部分表明與之相關類型的描述符。code
package main import ( "bytes" "fmt" "io" "os" ) func main() { var w io.Writer fmt.Printf("類型:%T,值:%v\n",w,w) // 類型:<nil>,值:<nil> w = os.Stdout fmt.Printf("類型:%T,值:%v\n",w,w) // 類型:*os.File,值:&{0xc00007e280} w = new(bytes.Buffer) fmt.Printf("類型:%T,值:%v\n",w,w) // 類型:*bytes.Buffer,值: w = nil fmt.Printf("類型:%T,值:%v\n",w,w) // 類型:<nil> 類型:<nil> }
一個包含nil指針的接口不是nil接口對象
類型斷言是一個使用在接口值上的操做。語法上它看起來像x.(T)被稱爲斷言類型,這裏x表示一個接口的類型和T表示一個類型。一個類型斷言檢查它操做對象的動態類型是否和斷言的類型匹配。接口
x.(T)
T表示類型string
package main import ( "bytes" "fmt" "io" "os" ) func main() { var w io.Writer w = os.Stdout f := w.(*os.File) fmt.Printf("類型%T,值:%v\n",f,f) // 類型*os.File,值:&{0xc00014a280} c := w.(*bytes.Buffer) fmt.Printf("類型%T,值:%v\n",c,c) // panic }
判斷是什麼類型:it
package main import ( "fmt" ) func judgeType(x interface{}) { switch v := x.(type) { case string: fmt.Printf("is string:%v\n", v) case int: fmt.Printf("is int:%v\n", v) case bool: fmt.Printf("is bool:%v\n", v) default: fmt.Println("donot know ") } } func main() { judgeType(1) // is int:1 judgeType(true) // is bool:true judgeType("true") // is string:true judgeType(1.22) // donot know }
空接口是沒有定義任何方法的接口。所以任何類型都實現了空接口。空接口類型的變量能夠存儲任意類型的變量。io
package main import "fmt" func main() { var test interface{} t1 := 1 test = t1 fmt.Printf("類型:%T 值:%v\n",test,test) // 類型:int 值:1 t2 := "zhaohaiyu" test = t2 fmt.Printf("類型:%T 值:%v\n",test,test) // 類型:string 值:zhaohaiyu t3 := false test = t3 fmt.Printf("類型:%T 值:%v\n",test,test) // 類型:bool 值:false t4 := 3.14 test = t4 fmt.Printf("類型:%T 值:%v\n",test,test) // 類型:float64 值:3.14 }
func show(test interface{}) { fmt.Printf("類型:%T 值:%v\n",test,test) }
var studentInfo = make(map[string]interface{}) studentInfo["name"] = "趙海宇" studentInfo["age"] = 18 fmt.Println(studentInfo) // map[age:18 name:趙海宇]