Go学习--interface(接口)

一、概念

接口是双方约定的一种合作协议。接口实现者不需要关心接口会被怎样使用,调用者也不需要关心接口的实现细节。接口是一种类型,也是一种抽象结构,不会暴露所含数据的格式、类型及结构。

通过以下的代码感受下Golang接口的用法

package main
import (
    "fmt"
)

// 定义一个数据写入器
type DataWriter interface {
    WriteData(data interface{}) error
}

// 定义文件结构,用于实现DataWriter
type file struct {
}

// 实现DataWriter接口的WriteData方法
func (d *file) WriteData(data interface{}) error {
    // 模拟写入数据
    fmt.Println("WriteData:", data)
    return nil
}
func main() {
    // 实例化file
    f := new(file)
    
    // 声明一个DataWriter的接口
    var writer DataWriter
    
    // 将接口赋值f,也就是*file类型
    writer = f
    
    // 使用DataWriter接口进行数据写入
    writer.WriteData("data")
}

二、实现接口的添加

1.接口的方法与实现接口的类型方法格式一致

2.接口中所有方法均要被实现

这个就是区别于Java一个很大的特点,如果没有全部实现,编译时会报错


三、类型和接口的关系

1.一个类型可以实现多个接口

接口内的方法完全独立,互相不知道对方的存在,也不知道自己使用的接口是谁实现的。

2.多个类型可以实现相同的接口

一个接口的方法,不一定需要由一个类型完全实现,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现。也就是说,使用者并不关心某个接口的方法是通过一个类型完全实现的,还是通过多个结构嵌入到一个结构体中拼凑起来共同实现的。

// 一个服务需要满足能够开启和写日志的功能
type Service interface {
    Start()  // 开启服务
    Log(string)  // 日志输出
}

// 日志器
type Logger struct {
}

// 实现Service的Log()方法
func (g *Logger) Log(l string) {
}

// 游戏服务
type GameService struct {
    Logger  // 嵌入日志器
}

// 实现Service的Start()方法
func (g *GameService) Start() {
}

var s Service = new(GameService)
s.Start()
s.Log(“hello”)

四、接口的嵌套组合

1.系统包中

type Writer interface {
    Write(p []byte) (n int, err error)
}

type Closer interface {
    Close() error
}

type WriteCloser interface {
    Writer
    Closer
}

2.代码中

package main

import (
    "io"
)

// 声明一个设备结构
type device struct {
}

// 实现io.Writer的Write()方法
func (d *device) Write(p []byte) (n int, err error) {
    return 0, nil
}

// 实现io.Closer的Close()方法
func (d *device) Close() error {
    return nil
}

func main() {
    // 声明写入关闭器, 并赋予device的实例
    var wc io.WriteCloser = new(device)

    // 写入数据
    wc.Write(nil)

    // 关闭设备
    wc.Close()

    // 声明写入器, 并赋予device的新实例
    var writeOnly io.Writer = new(device)

    // 写入数据
    writeOnly.Write(nil)

}

五、接口和其他类型之间的转换

Go 语言中使用接口断言(type assertions)将接口转换成另外一个接口,也可以将接口转换为另外的类型。接口的转换在开发中非常常见,使用也非常频繁。

1.类型断言的格式

t,ok := i.(T)

2.将接口转换为其他接口

var obj interface = new(bird)
f, isFlyer := obj.(Flyer)

3.将接口转换为其他类型

p1 := new(pig)
var a Walker = p1
p2 := a.(*pig)
fmt.Printf("p1=%p p2=%p", p1, p2)

五、空接口类型

空接口类型可以保存其他值,但是拿出来的时候,要进行类型的断言(类似Java的类型强制转换)


六、空接口的值比较

1.类型不同的空接口间的比较结果不相同

// a保存整型
var a interface{} = 100

// b保存字符串
var b interface{} = "hi"

// 两个空接口不相等
fmt.Println(a == b)

2.不能比较空接口中的动态值

// c保存包含10的整型切片
var c interface{} = []int{10}

// d保存包含20的整型切片
var d interface{} = []int{20}

// 这里会发生崩溃
fmt.Println(c == d)

七、类型分支判断基本类型

switch 接口变量.(type) {
   case 类型1:
       // 变量是类型1时的处理
   case 类型2:
       // 变量是类型2时的处理
   …
   default:
       // 变量不是所有case中列举的类型时的处理
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值