11. Go接口

接口

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

Go 语言的接口设计是非侵入式的,接口编写者无须知道接口被哪些类型实现。而接口实现者只需知道实现的是什么样子的接口,但无须指明实现哪一个接口。编译器知道最终编译时使用哪个类型实现哪个接口,或者接口应该由谁来实现。

Go语言中使用接口来体现多态,是duck-type(鸭子类型)的一种体现。当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

接口的定义与实现

package main

import (
    "fmt"
)

// 定义一个接口
type Phone interface {
    call()
}

// 定义一个结构体
type NokiaPhone struct {
}


// 实现
func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    //定义接口类型的变量
    var phone Phone

    //只要实现了此接口方法的类型,那么这个类型的变量(接收者类型)就可以给i赋值
    phone = new(NokiaPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()

}
package main

import "fmt"

// 声明一个接口
type reg interface {
	get(str string) string
}

// 声明结构体
type str1 struct {
	str string
}

// 定义结构体方法
func (s str1) get(str string) string {
	return str + "str1"
}

type str2 struct {
	str string
}

func (s str2) get(str string) string {
	return str + "str2"
}

func getStr(r reg) {
	fmt.Println(r.get("你是猪!"))
}

func main() {
	// 实现了方法  就是实现了接口
	testStr := str2{"11111111111"}
	getStr(testStr)
}

接口被实现的条件

接口的方法与实现接口的类型方法格式一致,在类型中添加与接口签名一致的方法就可以实现该方法。签名包括方法中的名称、参数列表、返回参数列表。也就是说,只要实现接口类型中的方法的名称、参数列表、返回参数列表中的任意一项与接口要实现的方法不一致,那么接口的这个方法就不会被实现。

接口中所有方法均被实现,当一个接口中有多个方法时,只有这些方法都被实现了,接口才能被正确编译并使用。

空接口与类型断言

具有0个方法的接口称为空接口。它表示为interface {}。由于空接口有0个方法,所有类型都实现了空接口。

类型断言用于提取接口的基础值,语法:i.(T)

package main

import(
"fmt"
)

func assert(i interface{}){
    s:= i.(int)
    fmt.Println(s)
}

// 程序打印的是int值, 但是如果我们给s 变量赋值的是string类型,程序就会panic。
func main(){
  var s interface{} = 55
  assert(s)
}


// 可以这样写 ======================================================= 
package main

import (  
    "fmt"
)

func assert(i interface{}) {  
    v, ok := i.(int)
    fmt.Println(v, ok)
}
func main() {  
    // 如果 i 的值是int类型, 那么v就是i 对应的值, 
    // ok就是true。否则ok为false,程序并不会panic。
    var s interface{} = 56
    assert(s)
    var i interface{} = "Steven Paul"
    assert(i)
}

类型判断

类型判断的语法类似于类型断言。在类型断言的语法i.(type)中,类型type应该由类型转换的关键字type替换。

// 基本类型判断
package main

import (  
    "fmt"
)

func findType(i interface{}) {  
    switch i.(type) {
    case string:
        fmt.Printf("String: %s\n", i.(string))
    case int:
        fmt.Printf("Int: %d\n", i.(int))
    default:
        fmt.Printf("Unknown type\n")
    }
}
func main() {  
    findType("Naveen")
    findType(77)
    findType(89.98)
}




/* 
=================================================================
 还可以将类型与接口进行比较。如果我们有一个类型并且
 该类型实现了一个接口,那么可以将它与它实现的接口进行比较。
*/

package main

import "fmt"

type Describer interface {  
    Describe()
}
type Person struct {  
    name string
    age  int
}

func (p Person) Describe() {  
    fmt.Printf("%s is %d years old", p.name, p.age)
}

func findType(i interface{}) {  
    switch v := i.(type) {
    case Describer:
        v.Describe()
    default:
        fmt.Printf("unknown type\n")
    }
}

func main() {  
    findType("Naveen")
    p := Person{
        name: "Naveen R",
        age:  25,
    }
    findType(p)
}

// 输出
unknown type  
Naveen R is 25 years old // 验证成功 调用 Describe()

接口的继承

接口既然可以继承自然可以组合

package main
 
import "fmt"
 
 // 定义一个接口  声明SayHi方法
type Humaner interface {
    SayHi()
}
 
 // 定义一个接口  继承Humaner接口 存在 SayHi、Sing方法
type Personer interface {
    Humaner
    Sing(lrc string)
}
 
 // 定义一个结构体
type Student struct {
    name string
    id int
}


// 实现接口的sayhi
func (s *Student)SayHi()  {
    fmt.Printf("%s sayhi\n", s.name)
}
 
 // 实现接 Sing
func (p *Student)Sing(lrc string)  {
    fmt.Printf("student %s sing %s\n", p.name, lrc)
}
 
func main() {  
    //定义一个接口的类型的变量
    var i Personer
    s := &Student{"mike", 1}
    i = s
    i.SayHi()
    i.Sing("loving you ")
}

// 执行结果
// mike sayhi
// student mike sing loving you
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值