Go語言接口


接口介紹

在Go語言中接口(interface)是一種類型,一種抽象的類型。

接口的定義

定義格式:

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

Go語言的接口在命名時,一般會在單詞后面添加er,接口名最好要能突出該接口的類型含義。

接口實現

一個對象只要全部實現了接口中的方法,那么就實現了這個接口。
Go語言中不同的類型可以實現同一個接口。(示例中dog和cat都實現了Animal接口)

//定義一個Animal接口
// Animal 是一個動物接口,實現move()和say()方法
type Animal interface {
    move()
    say()
}

//定義dog結構體
type dog struct {
    name string
}
//定義cat結構體
type cat struct {
    name string
}
//dog實現move方法
func (d dog) move() {
    fmt.Printf("%s會跑\n",d.name)
}
//dog實現say方法
func (d dog) say() {
    fmt.Printf("%s會叫汪汪汪\n",d.name)
}
//cat實現move方法
func (c *cat) move() {
    fmt.Printf("%s會跑\n",c.name)
}
//cat實現say方法
func (c cat) say() {
    fmt.Printf("%s會叫喵喵喵\n",c.name)
}
func main()  {
    var a Animal    //聲明一個Animal類型的a
    //實例化一個dog結構體
    d := dog{name:"旺財"}
    fmt.Printf("%T\n", d)       //main.dog
    d.move()    //旺財會跑
    d.say()     //旺財會叫汪汪汪
    a = d // 接口是一種類型,一種抽象的類型。
    fmt.Println(a)  //{旺財}
    //實例化一個cat結構體
    c := cat{name:"藍貓"}
    c.move()    //藍貓會跑
    c.say()     //藍貓會叫喵喵喵
}

多態

GO語言通過接口模擬多態。

類型與接口關系

一個類型可以同時實現多個接口,而接口間彼此獨立,不知道對方的實現。
Go語言中不同的類型可以實現同一個接口。

接口嵌套

接口與接口間可以通過嵌套創造出新的接口。

//定義speaker接口
type speaker interface {
    speak()
}
//定義mover接口
type mover interface {
    move()
}
// 接口嵌套
type animal interface {
    speaker
    mover
}
//定義cat結構體
type cat struct {
    name string
}
//cat是值類型接收者
func (c cat) speak() {
    fmt.Println("喵喵喵")
}

func (c cat) move() {
    fmt.Println("貓會動")
}
func main()  {
    var x animal
    x = cat{name: "花花"}
    x.move()    //貓會動
    x.speak()   //喵喵喵
}

空接口

空接口定義

空接口是指沒有定義任何方法的接口。空接口類型的變量可以存儲任意類型的變量。

//空接口
func main()  {
    var x interface{}
    x = 100     //int類型
    fmt.Println(x)  //100
    x = "ares"  //string類型
    fmt.Println(x)  //ares
    x = struct {    //結構體類型
        name string
    }{name:"ares"}  
    fmt.Println(x)  //ares
}

空接口應用

空接口可以作為函數的參數或map的值。

//空接口
func showType(a interface{}) {
    fmt.Printf("type:%T\n", a)
}

func main()  {
    //空接口作為函數的參數
    showType(100)       //type:int
    showType("ares")    //type:string
    //定義一個值為空接口的map
    var stu = make(map[string]interface{},100)
    stu["ares"] = 100
    stu["ares1"] = "男"
    fmt.Println(stu)    //map[ares:100 ares1:男]
    //map,key是字符串,value是任意類型
    map1 := make(map[string]interface{})
    map1["name"] = "ares"
    map1["age"] = 18
    map1["id"] = 1
    map1["friend"] = struct {
        name string
        age  int
    }{"jay", 33}
    fmt.Println(map1) //map[age:18 friend:{jay 33} id:1 name:ares]
    }

接口嵌套

類似於繼承。

type A interface {
    test1()
}
type B interface {
    test2()
}
type C interface {
    A
    B
    test3()
}
type Cat struct { //如果要實現接口c,需要將接口a和接口b中的方法一起實現
}

func (c Cat) test1() {
    fmt.Println("test1...")
}
func (c Cat) test2() {
    fmt.Println("test2...")
}
func (c Cat) test3() {
    fmt.Println("test3...")
}
func main() {
    var cat = Cat{}
    cat.test1() //test1...
    cat.test2() //test2...
    cat.test3() //test3...
    //將cat賦值接口A類型,則只能使用test1方法
    var cat1 A = Cat{}
    cat1.test1() //test1...
    //將cat賦值接口B類型,則只能使用test2方法
    var cat2 B = Cat{}
    cat2.test2() //test2...
}

類型斷言

語法:

x.(T)

x:表示類型為interface{}的變量
T:表示斷言x可能是的類型
若為true則表示斷言成功,為false則表示斷言失敗。

//類型斷言
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)
    case *string:
        fmt.Printf("x is a point指針 is %v\n", v)
    case struct{}:
        fmt.Printf("x is a struct is %v\n", v)
    default:
        fmt.Println("unsupport type!")
    }
}
func main()  {
    justifyType(100)        //x is a int is 100
    justifyType("ares") //x is a string,value is ares
    justifyType(false)  //x is a bool is false
    x := "ares"
    justifyType(&x) //x is a point指針 is 0xc000094010
    justifyType(struct {}{})    //x is a struct is {}
    justifyType([]int{123}) //unsupport type!
}

值接收者和指針接收者實現接口的區別

如果接收者為指針類型的話,不能把值傳進去。

//定義animal接口
type animal interface {
    speak()
    move()
}
//定義cat結構體
type cat struct{
    name string
}
//定義dog結構體
type dog struct{
    name string
}
//值接收者
 func (c cat) speak() {
    fmt.Printf("%s會叫喵喵喵\n",c.name)
 }
 func (c cat) move() {
    fmt.Printf("%s會動\n",c.name)
 }
 //指針接收者
func (d *dog) speak() {
    fmt.Printf("%s會叫汪汪汪\n",d.name)
}
func (d *dog) move() {
    fmt.Printf("%s會動\n",d.name)
}
func main()  {
    var c1 animal
    lm := cat{name:"藍貓"}
    c1 = lm     //因為實現animal接口的是cat值類型,所以可以直接賦值
    c1.move()   //藍貓會動
    c1.speak()  //藍貓會叫喵喵喵
    var c2 animal
    jm := &dog{name:"金毛"}   //現animal接口的是*dog類型,所以必須要通過&來取值
    c2 = jm
    c2.move()   //金毛會動
    c2.speak()  //金毛會叫汪汪汪
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM