GoLang之接口interface
文章目錄
- 接口interface
- 1.接口介紹
- 2.接口定義
- 2.1定義要求
- 2.2接口可以嵌入到其他接口里但必須得匿名
- 2.2.1接口里可以含一個接口時
- 2.2.2接口里可以含多個接口時
 
- 2.3接口沒有數(shù)據(jù)字段
- 2.4接口可以嵌入到結(jié)構(gòu)體struct里
- 2.5空接口可以作為任何類型數(shù)據(jù)的容器
- 2.6接口命名習(xí)慣以 er 結(jié)尾
- 2.7實現(xiàn)接口的所有方法即可實現(xiàn)接口
- 2.7.1沒有嵌套其他接口時
- 2.7.1嵌套其他接口時正確實現(xiàn)
- 2.7.1嵌套其他接口時錯誤實現(xiàn)
 
- 2.8接口是一個或多個方法簽名的集合
- 2.9一個類型可以實現(xiàn)多個接口
- 2.9.1接口內(nèi)方法不一樣時
- 2.9.2接口內(nèi)方法一樣時
 
- 2.10接口同樣支持匿名方法
- 2.11只有當(dāng)接口存儲的類型和對象都為nil時接口才等于nil
- 2.12接口類型的變量可使用其實例的方法
- 2.13接口類型的變量不可以使用其實例的字段
- 2.14值接收者實現(xiàn)接口
- 2.15指針接收者實現(xiàn)接口
- 2.16多個類型實同一接口
- 2.17結(jié)構(gòu)體中方法+結(jié)構(gòu)體中所嵌套的結(jié)構(gòu)體的方法來實現(xiàn)接口
 
- 3.使用接口的原因
- 4.接口的方法錯誤定義
- 5.空接口
- 5.1空結(jié)構(gòu)體占用16字節(jié)
- 5.2類型斷言
- 5.1定義
- 5.2v,ok=x.(Y)應(yīng)用
- 5.3type switch 語句介紹
- 5.4結(jié)合switch語句
 
 
 
接口interface
1.接口介紹
在Go語言中接口(interface)是一種類型,一種抽象的類型;
 interface是一組method的集合,是duck-type programming的一種體現(xiàn)。接口做的事情就像是定義一個協(xié)議(規(guī)則),只要一臺機器有洗衣服和甩干的功能,我就稱它為洗衣機。不關(guān)心屬性(數(shù)據(jù)),只關(guān)心行為(方法);
 為了保護你的Go語言職業(yè)生涯,請牢記接口(interface)是一種類型;
 
2.接口定義
2.1定義要求
2.2接口可以嵌入到其他接口里但必須得匿名
2.2.1接口里可以含一個接口時
type Phone interface {demo//不會報錯 } type demo interface {} type Phone interface {aa demo//會編譯報錯 } type demo interface {}2.2.2接口里可以含多個接口時
// Sayer 接口 type Sayer interface {say() }// Mover 接口 type Mover interface {move() }// 接口嵌套 type animal interface {SayerMover }type cat struct {name string }func (c cat) say() {fmt.Println("喵喵喵") }func (c cat) move() {fmt.Println("貓會動") }func main() {var x animalx = cat{name: "花花"}x.move()x.say() }2.3接口沒有數(shù)據(jù)字段
接口只有方法聲明,沒有實現(xiàn),沒有數(shù)據(jù)字段
2.4接口可以嵌入到結(jié)構(gòu)體struct里
2.5空接口可以作為任何類型數(shù)據(jù)的容器
2.6接口命名習(xí)慣以 er 結(jié)尾
2.7實現(xiàn)接口的所有方法即可實現(xiàn)接口
實現(xiàn)接口條件:
 接口被實現(xiàn)的條件一:接口的方法與實現(xiàn)接口的類型方法格式一致
 接口被實現(xiàn)的條件二:接口中所有方法均被實現(xiàn)
 任何類型的方法集中只要擁有該接口’對應(yīng)的全部方法’簽名就表示它 “實現(xiàn)” 了該接口,無須在該類型上顯式聲明實現(xiàn)了哪個接口,這稱為Structural Typing;
 所謂對應(yīng)方法,是指有相同名稱、參數(shù)列表 (不包括參數(shù)名) 以及返回值;
 當(dāng)然該類型還可以有其他方法
2.7.1沒有嵌套其他接口時
// Sayer 接口 type Sayer interface {say() } type dog struct{}type cat struct{} // dog實現(xiàn)了Sayer接口 func (d dog) say() {fmt.Println("汪汪汪") }// cat實現(xiàn)了Sayer接口 func (c cat) say() {fmt.Println("喵喵喵") }2.7.1嵌套其他接口時正確實現(xiàn)
type Sayer interface {Listersay() } type Lister interface {lis() }type cat struct{}// dog實現(xiàn)了Sayer接口 func (d cat) say() {fmt.Println("汪汪汪") }// cat實現(xiàn)了Sayer接口 func (c cat) lis() {fmt.Println("喵喵喵") }func main() {var x Sayer // 聲明一個Sayer類型的變量xa := cat{} // 實例化一個catx = a // 會報錯,原因缺少say方法x.say() // 汪汪汪x.lis() }2.7.1嵌套其他接口時錯誤實現(xiàn)
type Sayer interface {Listersay() } type Lister interface {lis() } type dog struct{}type cat struct{}// dog實現(xiàn)了Sayer接口 func (d dog) say() {fmt.Println("汪汪汪") }// cat實現(xiàn)了Sayer接口 func (c cat) lis() {fmt.Println("喵喵喵") }func main() {var x Sayer // 聲明一個Sayer類型的變量xa := cat{} // 實例化一個catb := dog{} // 實例化一個dogx = a // 會報錯,原因缺少say方法x = b // 會報錯,原因缺少lis方法x.say() // 汪汪汪}2.8接口是一個或多個方法簽名的集合
2.9一個類型可以實現(xiàn)多個接口
2.9.1接口內(nèi)方法不一樣時
// Sayer 接口 type Sayer interface {say() }// Mover 接口 type Mover interface {move() }type dog struct {name string }// 實現(xiàn)Sayer接口 func (d dog) say() {fmt.Printf("%s會叫汪汪汪\n", d.name) }// 實現(xiàn)Mover接口 func (d dog) move() {fmt.Printf("%s會動\n", d.name) }func main() {var x Sayervar y Movervar a = dog{name: "旺財"}x = ay = ax.say() //輸出:旺財會叫汪汪汪y.move() //輸出:旺財會動 }2.9.2接口內(nèi)方法一樣時
// Sayer 接口 type Sayer interface {say() }// Mover 接口 type Mover interface {say() }type dog struct {name string }// 實現(xiàn)Sayer接口 func (d dog) say() {fmt.Printf("%s會叫汪汪汪\n", d.name) }func main() {var x Sayervar y Movervar a = dog{name: "旺財"}x = ay = ax.say() //輸出:旺財會叫汪汪汪y.say()//輸出:旺財會叫汪汪汪 }2.10接口同樣支持匿名方法
type Phone interface {func() string //匿名時候需要加funcsay() string //不匿名時候不用加func }2.11只有當(dāng)接口存儲的類型和對象都為nil時接口才等于nil
2.12接口類型的變量可使用其實例的方法
接口類型的變量可使用其實例的方法 ,但是不可以使用其實例的字段
// Sayer 接口 type Sayer interface {say() } type dog struct {a int }type cat struct{}// dog實現(xiàn)了Sayer接口 func (d dog) say() {fmt.Println("汪汪汪") }// cat實現(xiàn)了Sayer接口 func (c cat) say() {fmt.Println("喵喵喵") }func main() {var x Sayer // 聲明一個Sayer類型的變量xa := cat{} // 實例化一個catb := dog{} // 實例化一個dogx = a // 可以把cat實例直接賦值給xx.say() // 喵喵喵x = b // 可以把dog實例直接賦值給xx.say() // 汪汪汪}2.13接口類型的變量不可以使用其實例的字段
// Sayer 接口 type Sayer interface {say() } type dog struct {a int }// dog實現(xiàn)了Sayer接口 func (d dog) say() {fmt.Println("汪汪汪") }func main() {var x Sayer b := dog{a :4,}x = b x.say() fmt.Println(x.a) //會編譯出錯 }2.14值接收者實現(xiàn)接口
從下面的代碼中我們可以發(fā)現(xiàn),使用值接收者實現(xiàn)接口之后,不管是dog結(jié)構(gòu)體還是結(jié)構(gòu)體指針dog類型的變量都可以賦值給該接口變量。因為Go語言中有對指針類型變量求值的語法糖,dog指針fugui內(nèi)部會自動求值fugui
type Mover interface {move() }type dog struct{}func (d dog) move() {fmt.Println("狗會動") }func main() {var x Movervar wangcai = dog{} // 旺財是dog類型x = wangcai // x可以接收dog類型var fugui = &dog{} // 富貴是*dog類型x = fugui // x可以接收*dog類型x.move() }2.15指針接收者實現(xiàn)接口
此時實現(xiàn)Mover接口的是dog類型,所以不能給x傳入dog類型的wangcai,此時x只能存儲dog類型的值
type Mover interface {move() }type dog struct{}func (d *dog) move() {fmt.Println("狗會動") }func main() {var x Movervar wangcai = dog{} // 旺財是dog類型x = wangcai // 這一行會會議報錯var fugui = &dog{} // 富貴是*dog類型x = fugui // x可以接收*dog類型x.move() }2.16多個類型實同一接口
// Mover 接口 type Mover interface {move() } type dog struct {name string }type car struct {brand string }// dog類型實現(xiàn)Mover接口 func (d dog) move() {fmt.Printf("%s會跑\n", d.name) }// car類型實現(xiàn)Mover接口 func (c car) move() {fmt.Printf("%s速度70邁\n", c.brand) } func main() {var x Movervar a = dog{name: "旺財"}var b = car{brand: "保時捷"}x = ax.move() //輸出:旺財會跑x = bx.move() //輸出:保時捷速度70邁 }2.17結(jié)構(gòu)體中方法+結(jié)構(gòu)體中所嵌套的結(jié)構(gòu)體的方法來實現(xiàn)接口
接口的方法可以通過在類型中嵌入其他類型或者結(jié)構(gòu)體來實現(xiàn)
// WashingMachine 洗衣機 type WashingMachine interface {wash()dry() }// 甩干器 type dryer struct{}// 實現(xiàn)WashingMachine接口的dry()方法 func (d dryer) dry() {fmt.Println("甩一甩") }// 海爾洗衣機 type haier struct {dryer //嵌入甩干器 }// 實現(xiàn)WashingMachine接口的wash()方法 func (h haier) wash() {fmt.Println("洗刷刷") } func main() {var x WashingMachinevar a haierx = ax.dry() //輸出:甩一甩}3.使用接口的原因
上面的代碼中定義了貓和狗,然后它們都會叫,你會發(fā)現(xiàn)main函數(shù)中明顯有重復(fù)的代碼,如果我們后續(xù)再加上豬、青蛙等動物的話,我們的代碼還會一直重復(fù)下去。那我們能不能把它們當(dāng)成“能叫的動物”來處理呢?
 像類似的例子在我們編程過程中會經(jīng)常遇到:
 比如一個網(wǎng)上商城可能使用支付寶、微信、銀聯(lián)等方式去在線支付,我們能不能把它們當(dāng)成“支付方式”來處理呢?
 比如三角形,四邊形,圓形都能計算周長和面積,我們能不能把它們當(dāng)成“圖形”來處理呢?
 比如銷售、行政、程序員都能計算月薪,我們能不能把他們當(dāng)成“員工”來處理呢?
 Go語言中為了解決類似上面的問題,就設(shè)計了接口這個概念。接口區(qū)別于我們之前所有的具體類型,接口是一種抽象的類型。當(dāng)你看到一個接口類型的值時,你不知道它是什么,唯一知道的是通過它的方法能做什么
4.接口的方法錯誤定義
package mainimport ("fmt" )type Phone interface {call() } //會編譯報錯 func (i Phone) call() {fmt.Println("q23erg") } func main() {}5.空接口
5.1空結(jié)構(gòu)體占用16字節(jié)
type demo interface { }func main() {var a demofmt.Println(unsafe.Sizeof(a)) //輸出16var b interface{}fmt.Println(unsafe.Sizeof(b)) //輸出16var c complex64fmt.Println(unsafe.Sizeof(c)) //輸出8 }5.2類型斷言
5.1定義
5.2v,ok=x.(Y)應(yīng)用
func main() {var x interface{}x = "pprof.cn"v, ok := x.(string)if ok {fmt.Println(v)} else {fmt.Println("類型斷言失敗")}//輸出:pprof.cn } func main() {var x interface{}x = "pprof.cn"v, ok := x.(bool)if ok {fmt.Println(v)} else {fmt.Println("類型斷言失敗")}//輸出:類型斷言失敗 }5.3type switch 語句介紹
 
5.4結(jié)合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!")} } func main() {var x interface{}x = "pprof.cn"justifyType(x) //輸出:x is a string,value is pprof.cn }總結(jié)
以上是生活随笔為你收集整理的GoLang之接口interface的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 常用项目文档目录示例
- 下一篇: ADB Interface 找不到驱动程
