Go語言接口不同于其他語言。在Go語言中,該接口是一種自定義類型,用于指定一組一個或多個方法簽名,并且該接口是抽象的,因此不允許您創(chuàng)建該接口的實(shí)例。但是您可以創(chuàng)建接口類型的變量,并且可以為該變量分配具有接口所需方法的具體類型值。換句話說,接口既是方法的集合,也是自定義類型。
在Go語言中,您可以使用以下語法創(chuàng)建接口:
type interface_name interface{ //方法簽名 }
例如:
//創(chuàng)建一個接口 type myinterface interface{ // 方法 fun1() int fun2() float64 }
此處,接口名稱包含在type和interface關(guān)鍵字之間,方法簽名包含在花括號之間。
在Go語言中,為了實(shí)現(xiàn)接口,必須實(shí)現(xiàn)接口中聲明的所有方法。go語言接口是隱式實(shí)現(xiàn)的。與其他語言一樣,它不包含實(shí)現(xiàn)接口的任何特定關(guān)鍵字。如下例所示:
// Golang程序說明如何 //實(shí)現(xiàn)接口 package main import "fmt" //創(chuàng)建一個接口 type tank interface { // 方法 Tarea() float64 Volume() float64 } type myvalue struct { radius float64 height float64 } //實(shí)現(xiàn)方法 //桶的(Tank)接口 func (m myvalue) Tarea() float64 { return 2*m.radius*m.height + 2*3.14*m.radius*m.radius } func (m myvalue) Volume() float64 { return 3.14 * m.radius * m.radius * m.height } func main() { // 訪問使用桶的接口 var t tank t = myvalue{10, 14} fmt.Println("桶的面積 :", t.Tarea()) fmt.Println("桶的容量:", t.Volume()) }
輸出:
桶的面積 : 908 桶的容量: 4396
接口的零值為nil。
當(dāng)接口包含零個方法時,此類接口稱為空接口。因此,所有類型都實(shí)現(xiàn)空接口。
語法:
interface{}
接口類型:該接口有兩種類型,一種是靜態(tài)的,另一種是動態(tài)的。靜態(tài)類型是接口本身,例如下面示例中的tank。但是接口沒有靜態(tài)值,所以它總是指向動態(tài)值。
接口類型的變量,其中包含實(shí)現(xiàn)接口的類型的值,因此該類型的值稱為動態(tài)值,而該類型是動態(tài)類型。又稱具體值和具體類型。
//說明Go程序的概念 //動態(tài)值和類型 package main import "fmt" //創(chuàng)建接口 type tank interface { // 方法 Tarea() float64 Volume() float64 } func main() { var t tank fmt.Println("tank interface值為: ", t) fmt.Printf("tank 的類型是: %T ", t) }
輸出:
tank interface值為: <nil> tank 的類型是: <nil>
在上面的示例中,有一個名為tank的接口。在此示例中,fmt.Println("tank interface值為: ", t) 語句返回該接口的動態(tài)值,而 fmt.Printf("tank 的類型是: %T ", t) 語句返回該接口的動態(tài)類型,即nil,因?yàn)檫@里的接口不知道誰在實(shí)現(xiàn)它。
類型斷言:在Go語言中,類型斷言是應(yīng)用于接口值的操作。換句話說,類型斷言是提取接口值的過程。
語法:
a.(T)
在這里,a是接口的值或表達(dá)式,T是也稱為類型斷言的類型。類型斷言用于檢查其操作數(shù)的動態(tài)類型是否匹配已斷言的類型。如果T是具體類型,則類型斷言檢查a的給定動態(tài)類型是否等于T,這里,如果檢查成功進(jìn)行,則類型斷言返回a的動態(tài)值。否則,如果檢查失敗,則操作將出現(xiàn)panic異常。如果T是接口類型,則類型斷言檢查滿足T的給定動態(tài)類型,這里,如果檢查成功進(jìn)行,則不提取動態(tài)值。
//類型斷言 package main import "fmt" func myfun(a interface{}) { //提取a的值 val := a.(string) fmt.Println("值為: ", val) } func main() { var val interface { } = "nhooo" myfun(val) }
輸出:
值為: nhooo
在上面的示例中,如果將val:= a。(string)語句更改為val:= a。(int),則程序會拋出panic異常。因此,為了避免此問題,我們使用以下語法:
value, ok := a.(T)
在這里,如果a的類型等于T,則該值包含a的動態(tài)值,并且ok將設(shè)置為true。并且如果a的類型不等于T,則ok設(shè)置為false并且value包含零值,并且程序不會拋出panic異常。如下面的程序所示:
package main import "fmt" func myfun(a interface{}) { value, ok := a.(float64) fmt.Println(value, ok) } func main() { var a1 interface { } = 98.09 myfun(a1) var a2 interface { } = "nhooo" myfun(a2) }
輸出:
98.09 true 0 false
類型判斷:在Go接口中,類型判斷用于將接口的具體類型與case語句中提供的多種類型進(jìn)行比較。它與類型聲明類似,只是有一個區(qū)別,即大小寫指定類型,而不是值。您還可以將類型與接口類型進(jìn)行比較。如下例所示:
package main import "fmt" func myfun(a interface{}) { //使用類型判斷 switch a.(type) { case int: fmt.Println("類型: int,值:", a.(int)) case string: fmt.Println("\n類型: string,值: ", a.(string)) case float64: fmt.Println("\n類型: float64,值: ", a.(float64)) default: fmt.Println("\n類型未找到") } }
輸出:
類型: string,值: nhooo 類型: float64,值: 67.9 類型未找到
接口的使用:當(dāng)您想要在其中傳遞不同類型的參數(shù)的方法或函數(shù)中時,可以使用接口,就像Println()函數(shù)一樣?;蛘?,當(dāng)多種類型實(shí)現(xiàn)同一接口時,也可以使用接口。