一文帶你了解Go語言中接口的使用
接口
在 Go
語言中,接口是一種抽象的類型,是一組方法的集合。接口存在的目的是定義規(guī)范,而規(guī)范的細(xì)節(jié)由其他對(duì)象去實(shí)現(xiàn)。我們來看一個(gè)例子:
import "fmt" type Person struct { Name string } func main() { person := Person{Name: "cmy"} fmt.Println(person) // {cmy} }
上述代碼定義了結(jié)構(gòu)體 Person
,main
函數(shù)創(chuàng)建了此結(jié)構(gòu)體的變量 person
,然后通過 fmt
包里的 Println
函數(shù)打印這個(gè)結(jié)構(gòu)體,打印結(jié)果為 {cmy}
。在此基礎(chǔ)上,我們改造一下代碼:
import "fmt" type Person struct { Name string } func (p Person) String() string { return fmt.Sprintf("name: %s", p.Name) } func main() { person := Person{Name: "cmy"} fmt.Println(person) // name: cmy }
新改造的代碼里為結(jié)構(gòu)體 Person
添加一個(gè)結(jié)構(gòu)體方法 String() string
,方法的返回結(jié)果是對(duì) name
進(jìn)行格式化,我們?cè)俅蛴∫幌陆Y(jié)構(gòu)體,觀察結(jié)果發(fā)現(xiàn)是 String()
方法返回的值,而不是 {cmy}
。 為什么是這樣呢?這是因?yàn)?fmt.Println(T)
函數(shù)的實(shí)現(xiàn)細(xì)節(jié)里,會(huì)對(duì)結(jié)構(gòu)體進(jìn)行判斷,如果結(jié)構(gòu)體實(shí)現(xiàn)了 Stringer
接口,則會(huì)直接打印 String()
方法的返回值。以下是 Stringer 接口的代碼:
type Stringer interface { String() string }
結(jié)構(gòu)體實(shí)現(xiàn)了這個(gè)接口,也就意味著遵守這個(gè)接口所定義的規(guī)范,fmt.Println(T)
函數(shù)發(fā)現(xiàn)結(jié)構(gòu)體有這個(gè)規(guī)范,因此就會(huì)根據(jù)規(guī)范來打印信息。基于 Stringer
接口,我們來看看接口的語法格式:
type XXX interface { // methods }
1、type
接口的聲明,必須以 type
關(guān)鍵字開頭。
2、接口名
推薦駝峰式命名法,首字母大寫的方法名可以在包外訪問,小寫的只能在包內(nèi)訪問。
3、interface
接口的標(biāo)識(shí)。
4、接口體
大括號(hào)里面聲明規(guī)范,也就是聲明方法,方法必須具有名字。
接口的實(shí)現(xiàn)
在 Go
語言里,接口的實(shí)現(xiàn)不是基于接口,而是基于方法。如果一個(gè)自定義類型擁有了某個(gè)接口的所有方法,那么這個(gè)自定義類型就實(shí)現(xiàn)這個(gè)接口。接口的實(shí)現(xiàn)在上述的例子中有所體現(xiàn),Person
結(jié)構(gòu)體定義了 String() string
方法,擁有了 Stringer
接口的所有方法,因此實(shí)現(xiàn)了 Stringer
接口。
一個(gè)自定義類型可以實(shí)現(xiàn)多個(gè)接口
type A interface { a() } type B interface { b() } type Person struct { Name string } func (p Person) a() { } func (p Person) b() { }
A
接口聲明了 a
方法, B
接口聲明了 b
方法,Person
結(jié)構(gòu)體定義了 a
和 b
兩個(gè)方法,因此 Person
結(jié)構(gòu)體實(shí)現(xiàn)了 A
和 B
兩個(gè)接口。
接口類型變量
一旦接口被定義,它就可以用于聲明變量。
import "fmt" type A interface { } func main() { var a A fmt.Println(a) // <nil> }
如果只聲明接口變量,不初始化,變量的值默認(rèn)為 nil
,因?yàn)榻涌陬愋蛯?shí)際上是一個(gè)指針。若為接口賦初值,需要選擇一個(gè)合法的值,即被賦值的基類必須實(shí)現(xiàn)這個(gè)接口。
空接口
在 Go
語言里面可以認(rèn)為所有類型實(shí)現(xiàn)了空接口,因?yàn)榭战涌跊]有任何的方法。
import "fmt" type EmptyInterface interface { } func main() { var a EmptyInterface = 1 var b EmptyInterface = true var c EmptyInterface = "hello" var d EmptyInterface = 3.14 var e EmptyInterface = 'c' fmt.Println(a, b, c, d, e) // 1 true hello 3.14 99 }
所有類型都實(shí)現(xiàn)空接口,因此空接口變量可以被賦初值為任意類型的值或變量。
類型斷言
Go
語言支持類型斷言操作,通過這個(gè)操作,可以還原接口變量的右值(被賦的初值)。類型斷言的語法形式通常為:
v, ok := a.(T)
如果斷言成功,那么 v
的值為接口變量的值,ok
的值為 true
;如果斷言失敗,v
的值為 T
類型的零值,ok
的值為 false
。
類型斷言變種 type switch
通過 type switch
的方式,可以判斷接口變量屬于哪種動(dòng)態(tài)類型。
import "fmt" type EmptyInterface interface { } func main() { var a EmptyInterface = 1 switch a.(type) { case string: fmt.Println("a 的右值類型為 string") case int: fmt.Println("a 的右值類型為 int") case bool: fmt.Println("a 的右值類型為 bool") case float64: fmt.Println("a 的右值類型為 float64") } }
小結(jié)
本文先是對(duì)接口的定義進(jìn)行介紹,然后通過一個(gè)例子,了解了接口其中的一個(gè)應(yīng)用場(chǎng)景和引出接口的語法格式以及實(shí)現(xiàn)的方法,然后介紹了空接口的特點(diǎn)和類型斷言,最后介紹了變種的類型斷言 type switch
的應(yīng)用例子。
到此這篇關(guān)于一文帶你了解Go語言中接口的使用的文章就介紹到這了,更多相關(guān)Go語言接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Golang中for-loop與goroutine的問題詳解
這篇文章主要給大家介紹了關(guān)于Golang中for-loop與goroutine問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09小學(xué)生也能看懂的Golang異常處理recover panic
在其他語言里,宕機(jī)往往以異常的形式存在,底層拋出異常,上層邏輯通過 try/catch 機(jī)制捕獲異常,沒有被捕獲的嚴(yán)重異常會(huì)導(dǎo)致宕機(jī),go語言追求簡潔,優(yōu)雅,Go語言不支持傳統(tǒng)的 try…catch…finally 這種異常2021-09-09Go語言Web編程實(shí)現(xiàn)Get和Post請(qǐng)求發(fā)送與解析的方法詳解
這篇文章主要介紹了Go語言Web編程實(shí)現(xiàn)Get和Post請(qǐng)求發(fā)送與解析的方法,結(jié)合實(shí)例形式分析了Go語言客戶端、服務(wù)器端結(jié)合實(shí)現(xiàn)web數(shù)據(jù)get、post發(fā)送與接收數(shù)據(jù)的相關(guān)操作技巧,需要的朋友可以參考下2017-06-06Go語言中切片(slice)和數(shù)組(array)的區(qū)別詳解
Go語言中切片(slice)和數(shù)組(array)是兩種不同的數(shù)據(jù)結(jié)構(gòu),它們?cè)谟梅ê托袨樯嫌幸恍┲匾獏^(qū)別,所以本文就通過一些代碼示例給大家詳細(xì)的介紹一下Go語言中切片(slice)和數(shù)組(array)的區(qū)別,需要的朋友可以參考下2023-09-09Golang使用JWT進(jìn)行認(rèn)證和加密的示例詳解
JWT是一個(gè)簽名的JSON對(duì)象,通常用作Oauth2的Bearer?token,JWT包括三個(gè)用.分割的部分。本文將利用JWT進(jìn)行認(rèn)證和加密,感興趣的可以了解一下2023-02-02Go語言中常量和變量的定義、使用規(guī)范及常見應(yīng)用場(chǎng)景
每一門語言都會(huì)有常量的定義,變量的定義,以及基于這些定義的運(yùn)算,下面這篇文章主要給大家介紹了關(guān)于Go語言中常量和變量的定義、使用規(guī)范及常見應(yīng)用場(chǎng)景的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06詳解golang channel有無緩沖區(qū)的區(qū)別
這篇文章主要給大家介紹了golang channel有無緩沖區(qū)的區(qū)別,無緩沖是同步的,有緩沖是異步的,文中通過代碼示例給大家講解的非常詳細(xì),需要的朋友可以參考下2024-01-01