go語言可以開發介面。 go語言中介面是一組方法的簽名,它是go語言中重要的組成部分,介面做的事情就好像是定義一個規範或協議,各個實作方只要按照協議實作即可。 go語言中使用interface關鍵字來定義接口,語法“type 接口類型名 interface{方法名1( 參數列表1 ) 返回值列表1 方法名2( 參數列表2 ) 返回值列表2…}”。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
介面對我們來說應該是一個比較熟悉的概念,在各種開發語言中運用都非常的廣泛,對於像我們比較熟悉java的程式設計師來說對於介面就更加的親切,下面我們來看下在go語言中介面是怎麼用,以及介面在日常開發中所扮演的角色。
go語言中介面是一組方法的簽名,它是go語言中重要的組成部分,介面做的事情就好像是定義一個規範或協議,各個實現方只要依照協議實現即可。
介面是一種類型
介面類型是對其他類型行為的抽象和概括,不關心具體的實作細節,這種抽象的方式可以讓我們的函數變的更加靈活。
type 接口类型名 interface{ 方法名1( 参数列表1 ) 返回值列表1 方法名2( 参数列表2 ) 返回值列表2 … }
在go語言中我們使用interface關鍵字來定義介面。
如果一個任意型別T的方法集為一個介面類型的方法集的超集,則我們說類型T實作了該介面。
介面的實作在go語言中是隱式的,也就說兩個類型之間的實作關係不需要在程式碼中體現出來,GO語言中沒有類似java中implements的關鍵字,Go編譯器將自動在需要的時候檢查兩個類型之間的實作關係。接口定義後,需要實作接口,呼叫方才能正確編譯通過並使用接口。
介面的實作需要遵循兩個規則才能讓介面可用:
1、介面的方法與實作介面的類型方法格式一致在類型中加入與介面簽章一致的方法就可以實作該方法。簽名包括方法中的名稱、參數清單、傳回參數清單。也就是說,只要實作介面類型中的方法的名稱、參數清單、傳回參數清單中的任一項與介面要實作的方法不一致,那麼介面的這個方法就不會被實作。
package main import "fmt" type Phone interface { Call() SendMessage() } type HuaWei struct { Name string Price float64 } func (h *HuaWei) Call() { fmt.Printf("%s:可以打电话",h.Name) } func (h *HuaWei) SendMessage() { fmt.Printf("%s:可以发送短信",h.Name) } func main() { h := new(HuaWei) h.Name="华为" var phone Phone phone = h phone.SendMessage() }
當型別無法實作介面時,編譯器會報錯:
## a.函數名稱不一致所造成的報錯## b.實作函數的方法簽章不一致所導致的報錯
2、介面中所有方法都實作當一個介面中有多個方法時,只有這些方法都實作了,介面才能被正確編譯並使用
func (h *Xiaomi) Call() { fmt.Printf("%s:可以打电话",h.Name) } func main() { h := new(Xiaomi) h.Name="小米" var phone Phone phone = h phone.SendMessage() }
當小米類型只是實作介面中的一個方法的時候,我們在使用的時候,編譯錯誤。
類型與介面的關係
一個型別可以實作多個接口,而介面之間彼此獨立,不知道對方的實作。
例如,狗既可以動,可以叫
package main import "fmt" type Move interface { move() } type Say interface { say() } type Dog struct { Name string } func (d *Dog) move() { fmt.Printf("%s会动\n", d.Name) } func (d *Dog) say() { fmt.Printf("%s会叫汪汪汪\n", d.Name) } func main() { var m Move var s Say d:=&Dog{ Name: "旺财", } m = d s=d m.move() s.say() }
多個類型實作同一個介面Go語言中不同的類型還可以實現同一接口首先我們定義一個Mover接口,它要求必須有一個move方法。
type Mover interface { move() }
例如狗可以動,汽車也可以動,可以使用以下程式碼實現這個關係:
type dog struct { name string } type car struct { brand string } // dog类型实现Mover接口 func (d dog) move() { fmt.Printf("%s会跑\n", d.name) } // car类型实现Mover接口 func (c car) move() { fmt.Printf("%s速度70迈\n", c.brand) }
這時候我們在程式碼中就可以把狗和汽車當成一個會動的物體來處理了,不再需要關注它們具體是什麼,只需要呼叫它們的move方法就可以了。
func main() { var x Mover var a = dog{name: "旺财"} var b = car{brand: "保时捷"} x = a x.move() x = b x.move() }
套件下的Print
系列函數,其參數大多是空介面類型,也可以說支援任意型別
空介面作為map的值func Print(a ...interface{}) (n int, err error) func Println(format string, a ...interface{}) (n int, err error) func Println(a ...interface{}) (n int, err error)
// 空接口作为map值 var studentInfo = make(map[string]interface{}) studentInfo["name"] = "李白" studentInfo["age"] = 18 studentInfo["married"] = false fmt.Println(studentInfo)
介面值
一個介面的值(簡稱介面值)是由一個特定類型和具體類型的值兩部分組成的。
這兩部分分別稱為介面的動態類型和動態值。
想要判斷空介面中的值這個時候就可以使用型別斷言,其語法格式:
x.(T)
其中:
该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。
func main() { var x interface{} x = "ms的go教程" v, ok := x.(string) if ok { fmt.Println(v) } else { fmt.Println("类型断言失败") } }
上面的示例中如果要断言多次就需要写多个if判断,这个时候我们可以使用switch语句来实现:
func justifyType(x interface{}) { switch v := x.(type) { case string: fmt.Printf("x is a string,value is %v\n", v) case int: fmt.Printf("x is a int is %v\n", v) case bool: fmt.Printf("x is a bool is %v\n", v) default: fmt.Println("unsupport type!") } }
因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。
关于接口需要注意的是,只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,那样只会增加不必要的抽象,导致不必要的运行时损耗。
以上是go語言可以開發介面嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!