go語言可以開發介面。go語言中介面是一組方法的簽名,它是go語言中重要的組成部分,介面做的事情就好像是定義一個規範或者協定,各個實現方只要按照協定實現即可。go語言中使用interface關鍵字來定義介面,語法「type 介面型別名 interface{方法名1( 參數列1 ) 返回值列表1 方法名2( 參數列2 ) 返回值列表2…}」。
php入門到就業線上直播課:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
介面對於我們來說應該是一個比較熟悉的概念,在各種開發語言中運用都非常的廣泛,對於像我們比較熟悉java的程式設計師來說對於介面就更加的親切,下面我們來看下在go語言中介面是怎麼用,以及介面在日常開發中發揮的作用。
go語言中介面是一組方法的簽名,它是go語言中重要的組成部分,介面做的事情就好像是定義一個規範或者協定,各個實現方只要按照協定實現即可。
介面是一種型別
介面型別是對其他型別行為的抽象和概括,不關心具體的實現細節,這種抽象的方式可以讓我們的函數變的更加靈活。
type 介面型別名 interface{
方法名1( 參數列1 ) 返回值列表1
方法名2( 參數列2 ) 返回值列表2
…
}
登入後複製
在go語言中我們使用interface關鍵字來定義介面。
如果一個任意型別T的方法集為一個介面型別的方法集的超集,則我們說型別T實現了該介面。
介面的實現在go語言中是隱式的,也就說兩個型別之間的實現關係不需要在程式碼中體現出來,G哦語言中也沒有類似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()
}
登入後複製
空介面:interface{},不包含任何方法,正因為如此,任何型別都實現了空介面,所以空介面可以儲存任意型別的資料。
fmt
包下的 Print
系列函數,其引數大多是空介面型別,也可以說支援任意型別
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的值
// 空介面作為map值
var studentInfo = make(map[string]interface{})
studentInfo["name"] = "李白"
studentInfo["age"] = 18
studentInfo["married"] = false
fmt.Println(studentInfo)
登入後複製
空介面可以儲存任意型別的值,那我們如何獲取其儲存的具體資料呢?
介面值
一個介面的值(簡稱介面值)是由一個具體型別和具體型別的值兩部分組成的。
這兩部分分別稱為介面的動態型別和動態值。
想要判斷空介面中的值這個時候就可以使用型別斷言,其語法格式:
x.(T)
登入後複製
其中:
x:表示型別為interface{}的變數
T:表示斷言x可能是的型別。
該語法返回兩個引數,第一個引數是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視訊教學、】
以上就是go語言可以開發介面嗎的詳細內容,更多請關注TW511.COM其它相關文章!