溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

go語(yǔ)言可不可以開發(fā)接口

發(fā)布時(shí)間:2022-12-16 09:43:39 來(lái)源:億速云 閱讀:95 作者:iii 欄目:編程語(yǔ)言

本篇內(nèi)容主要講解“go語(yǔ)言可不可以開發(fā)接口”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“go語(yǔ)言可不可以開發(fā)接口”吧!

go語(yǔ)言可以開發(fā)接口。go語(yǔ)言中接口是一組方法的簽名,它是go語(yǔ)言中重要的組成部分,接口做的事情就好像是定義一個(gè)規(guī)范或者協(xié)議,各個(gè)實(shí)現(xiàn)方只要按照協(xié)議實(shí)現(xiàn)即可。go語(yǔ)言中使用interface關(guān)鍵字來(lái)定義接口,語(yǔ)法“type 接口類型名 interface{方法名1( 參數(shù)列表1 ) 返回值列表1 方法名2( 參數(shù)列表2 ) 返回值列表2…}”。

接口對(duì)于我們來(lái)說(shuō)應(yīng)該是一個(gè)比較熟悉的概念,在各種開發(fā)語(yǔ)言中運(yùn)用都非常的廣泛,對(duì)于像我們比較熟悉java的程序員來(lái)說(shuō)對(duì)于接口就更加的親切,下面我們來(lái)看下在go語(yǔ)言中接口是怎么用,以及接口在日常開發(fā)中發(fā)揮的作用。

概念

go語(yǔ)言中接口是一組方法的簽名,它是go語(yǔ)言中重要的組成部分,接口做的事情就好像是定義一個(gè)規(guī)范或者協(xié)議,各個(gè)實(shí)現(xiàn)方只要按照協(xié)議實(shí)現(xiàn)即可。

接口是一種類型

接口類型是對(duì)其他類型行為的抽象和概括,不關(guān)心具體的實(shí)現(xiàn)細(xì)節(jié),這種抽象的方式可以讓我們的函數(shù)變的更加靈活。

接口定義

type 接口類型名 interface{
    方法名1( 參數(shù)列表1 ) 返回值列表1
    方法名2( 參數(shù)列表2 ) 返回值列表2
    …
}

在go語(yǔ)言中我們使用interface關(guān)鍵字來(lái)定義接口。

接口實(shí)現(xiàn)條件

如果一個(gè)任意類型T的方法集為一個(gè)接口類型的方法集的超集,則我們說(shuō)類型T實(shí)現(xiàn)了該接口。

接口的實(shí)現(xiàn)在go語(yǔ)言中是隱式的,也就說(shuō)兩個(gè)類型之間的實(shí)現(xiàn)關(guān)系不需要在代碼中體現(xiàn)出來(lái),G哦語(yǔ)言中也沒有類似java中implements的關(guān)鍵字,Go編譯器將自動(dòng)在需要的時(shí)候檢查兩個(gè)類型之間的實(shí)現(xiàn)關(guān)系。接口定義后,需要實(shí)現(xiàn)接口,調(diào)用方才能正確編譯通過(guò)并使用接口。

接口的實(shí)現(xiàn)需要遵循兩條規(guī)則才能讓接口可用:

1、接口的方法與實(shí)現(xiàn)接口的類型方法格式一致在類型中添加與接口簽名一致的方法就可以實(shí)現(xiàn)該方法。簽名包括方法中的名稱、參數(shù)列表、返回參數(shù)列表。也就是說(shuō),只要實(shí)現(xiàn)接口類型中的方法的名稱、參數(shù)列表、返回參數(shù)列表中的任意一項(xiàng)與接口要實(shí)現(xiàn)的方法不一致,那么接口的這個(gè)方法就不會(huì)被實(shí)現(xiàn)。

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:可以發(fā)送短信",h.Name)
}

func main() {

	h := new(HuaWei)
	h.Name="華為"
	var phone Phone
	phone = h
	phone.SendMessage()
}

當(dāng)類型無(wú)法實(shí)現(xiàn)接口時(shí),編譯器會(huì)報(bào)錯(cuò):

a.函數(shù)名稱不一致導(dǎo)致的報(bào)錯(cuò)

b.實(shí)現(xiàn)函數(shù)的方法簽名不一致導(dǎo)致的報(bào)錯(cuò)

2、接口中所有方法均被實(shí)現(xiàn)當(dāng)一個(gè)接口中有多個(gè)方法時(shí),只有這些方法都被實(shí)現(xiàn)了,接口才能被正確編譯并使用

func (h *Xiaomi) Call() {
	fmt.Printf("%s:可以打電話",h.Name)
}

func main() {
	h := new(Xiaomi)
	h.Name="小米"
	var phone Phone
	phone = h
	phone.SendMessage()
}

go語(yǔ)言可不可以開發(fā)接口

當(dāng) 小米 類型僅僅實(shí)現(xiàn)接口中的一個(gè)方法的時(shí)候,我們?cè)谑褂玫臅r(shí)候,編譯報(bào)錯(cuò)。

類型與接口的關(guān)系

一個(gè)類型實(shí)現(xiàn)多個(gè)接口

一個(gè)類型可以實(shí)現(xiàn)多個(gè)接口,而接口之間彼此獨(dú)立,不知道對(duì)方的實(shí)現(xiàn)。

例如,狗既可以動(dòng),可以叫

package main

import "fmt"

type Move interface {
	move()
}
type Say interface {
	say()
}
type Dog struct {
	Name string
}

func (d *Dog) move()  {
	fmt.Printf("%s會(huì)動(dòng)\n", d.Name)
}
func (d *Dog) say()  {
	fmt.Printf("%s會(huì)叫汪汪汪\n", d.Name)
}

func main() {
	var m Move
	var s  Say
	d:=&Dog{
		Name: "旺財(cái)",
	}
	m = d
	s=d
	m.move()
	s.say()
}

多個(gè)類型實(shí)現(xiàn)同一個(gè)接口

Go語(yǔ)言中不同的類型還可以實(shí)現(xiàn)同一接口 首先我們定義一個(gè)Mover接口,它要求必須有一個(gè)move方法。

type Mover interface {
    move()
}

例如狗可以動(dòng),汽車也可以動(dòng),可以使用如下代碼實(shí)現(xiàn)這個(gè)關(guān)系:

type dog struct {
    name string
}

type car struct {
    brand string
}

// dog類型實(shí)現(xiàn)Mover接口
func (d dog) move() {
    fmt.Printf("%s會(huì)跑\n", d.name)
}

// car類型實(shí)現(xiàn)Mover接口
func (c car) move() {
    fmt.Printf("%s速度70邁\n", c.brand)
}

這個(gè)時(shí)候我們?cè)诖a中就可以把狗和汽車當(dāng)成一個(gè)會(huì)動(dòng)的物體來(lái)處理了,不再需要關(guān)注它們具體是什么,只需要調(diào)用它們的move方法就可以了。

func main() {
        var x Mover
        var a = dog{name: "旺財(cái)"}
        var b = car{brand: "保時(shí)捷"}
        x = a
        x.move()
        x = b
        x.move()
    }

空接口

空接口:interface{},不包含任何方法,正因?yàn)槿绱?,任何類型都?shí)現(xiàn)了空接口,所以空接口可以存儲(chǔ)任意類型的數(shù)據(jù)。

fmt 包下的 Print 系列函數(shù),其參數(shù)大多是空接口類型,也可以說(shuō)支持任意類型

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)

類型推斷

空接口可以存儲(chǔ)任意類型的值,那我們?nèi)绾潍@取其存儲(chǔ)的具體數(shù)據(jù)呢?

接口值

一個(gè)接口的值(簡(jiǎn)稱接口值)是由一個(gè)具體類型和具體類型的值兩部分組成的。

這兩部分分別稱為接口的動(dòng)態(tài)類型和動(dòng)態(tài)值。

想要判斷空接口中的值這個(gè)時(shí)候就可以使用類型斷言,其語(yǔ)法格式:

x.(T)

其中:

  • x:表示類型為interface{}的變量

  • T:表示斷言x可能是的類型。

該語(yǔ)法返回兩個(gè)參數(shù),第一個(gè)參數(shù)是x轉(zhuǎn)化為T類型后的變量,第二個(gè)值是一個(gè)布爾值,若為true則表示斷言成功,為false則表示斷言失敗。

func main() {
    var x interface{}
    x = "ms的go教程"
    v, ok := x.(string)
    if ok {
        fmt.Println(v)
    } else {
        fmt.Println("類型斷言失敗")
    }
}

上面的示例中如果要斷言多次就需要寫多個(gè)if判斷,這個(gè)時(shí)候我們可以使用switch語(yǔ)句來(lái)實(shí)現(xiàn):

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!")
    }
}

因?yàn)榭战涌诳梢源鎯?chǔ)任意類型值的特點(diǎn),所以空接口在Go語(yǔ)言中的使用十分廣泛。

到此,相信大家對(duì)“go語(yǔ)言可不可以開發(fā)接口”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI