常德網(wǎng)站seo百度收錄官網(wǎng)
文章目錄
- duck typing
- nil不一定是空接口
- 組合代替繼承
- 接口轉(zhuǎn)換回具體的類型
- 使用switch匹配接口的原始類型
duck typing
golang中實現(xiàn)某個接口不需要像其它語言使用 implemet 去繼承實現(xiàn),而是只要你的結(jié)構(gòu)體包含接口所需的方法即可
package mainimport "fmt"type Person interface {talk()
}type XM struct {
}func (receiver XM) talk() {fmt.Println("I am XM")
}func main() {var p Personp = XM{}p.talk() // I am XM
}
nil不一定是空接口
初始化的接口是等于 nil的,接口底層其實有一個type來記錄原始的struct,當某個struct賦值給接口時,接口會在type中記錄該類型(就算是nil也會記錄),此時接口打印出來是nil,但和nil并不相等
}type XM struct {
}func (X XM) talk() {fmt.Println("I am XM")
}func main() {var p Personif p == nil {fmt.Println("var p Person is nil") //var p Person is nil}var a *XMif a == nil {fmt.Println("var a *XM is nil") //var a *XM is nil}p = aif p != nil {fmt.Println("var p != nil") //var p != nil}fmt.Println(p) // <nil>
}
組合代替繼承
通過內(nèi)嵌組合來繼承功能,XM匿名內(nèi)嵌了Person,就具有了Person的能力
package mainimport "fmt"type Person struct {Name string
}func (receiver Person) Talk() {fmt.Printf("I am %s \n", receiver.Name)
}type XM struct {Person
}func main() {var xm XMp := Person{Name: "Person"}xm.Name = "XM"xm.Talk() // I am XMp.Talk() // I am Person
}
重寫方法只需要聲明一個同名方法即可
package mainimport "fmt"type Person struct {Name string
}func (receiver Person) Talk() {fmt.Printf("I am %s \n", receiver.Name)
}type XM struct {Person
}func (receiver XM) Talk() {fmt.Printf("hello,I am %s", receiver.Name)
}func main() {var xm XMxm.Name = "XM"xm.Talk() // hello,I am XM
}
接口轉(zhuǎn)換回具體的類型
struct 轉(zhuǎn)為接口,只要struct 擁有 接口的方法,即可將struct 賦值給接口,如果想將接口轉(zhuǎn)回struct,可以使用 result,ok := interface.(struct), ok 代表是否能夠成功轉(zhuǎn)換
package mainimport "fmt"type IAnimal interface {Eat()
}type Bridge struct {
}func (b Bridge) Eat() {fmt.Println("I can eat")
}func (b Bridge) Fly() {fmt.Println("I can fly")
}type Fish struct {
}func (f Fish) Eat() {fmt.Println("I can eat")
}func ShowTime(animal IAnimal) {animal.Eat()if b, ok := animal.(Bridge); ok {b.Fly()}
}func main() {var (f Fishb Bridge)ShowTime(f) // I can eatfmt.Println("--------------")ShowTime(b) // I can eat \n I can fly
}
ok 判斷的是完全轉(zhuǎn)換,就算不ok,轉(zhuǎn)換后的結(jié)果也可以調(diào)用struct的方法,但是不建議這么做
package mainimport "fmt"type IAnimal interface {Eat()
}type Bridge struct {Name string
}func (b Bridge) Eat() {fmt.Println(b.Name + "I can eat")
}func (b Bridge) Fly() {fmt.Println(b.Name + "I can fly")
}type Fish struct {Name string
}func (f Fish) Eat() {fmt.Println(f.Name + "I can eat")
}func ShowTime(animal IAnimal) {animal.Eat()b, ok := animal.(Bridge)fmt.Println(ok)b.Fly()
}func main() {f := Fish{Name: "fish"}b := Bridge{Name: "bridge"}ShowTime(f)// fishI can eat// false// I can flyfmt.Println("--------------")ShowTime(b)//bridgeI can eat// true//bridgeI can fly
}
使用switch匹配接口的原始類型
struct.(type) 可以獲取接口的原始類型,但是只能在switch中使用
package mainimport "fmt"type IAnimal interface {Eat()
}type Bridge struct {Name string
}func (b Bridge) Eat() {fmt.Println(b.Name + "I can eat")
}func (b Bridge) Fly() {fmt.Println(b.Name + "I can fly")
}type Fish struct {Name string
}func (f Fish) Eat() {fmt.Println(f.Name + "I can eat")
}func ShowTime(animal IAnimal) {switch animal.(type) {case Fish:fmt.Println("原先是Fish")case Bridge:fmt.Println("原先是Bridge")}
}func main() {var (f Fishb Bridge)ShowTime(f) // 原先是FishShowTime(b) // 原先是Bridge
}