博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go圣经-学习笔记之接口
阅读量:7051 次
发布时间:2019-06-28

本文共 2358 字,大约阅读时间需要 7 分钟。

hot3.png

接口概述

接口类型是对其他类型行为的抽象和概括,类似于C++中的多态,在运行时绑定。通过这种抽象的形式,可以让我们的方法更加灵活和更具有适应能力。

下面这粗体段话,我把我能理解的说一下:

  • 隐式实现,是指只要满足接口的定义,就能当做接口使用,不需要显示的说我要继承并实现这些接口。
  • 接口类型尽量小一点,通过组合接口行为实现复杂的对象行为集;这个后面,我会举一个例子

很多面向对象的语言都有相似的接口概念,但Go语言中接口类型的独特之处在于它是满足隐式实现的。也就是说,我们没有必要对于给定的具体类型定义所有满足的接口类型;简单地拥有一些必需的方法就足够了。这种设计可以让你创建一个新的接口类型满足已经存在的具体类型却不会去改变这些类型的定义;当我们使用的类型来自于不受我们控制的包时这种设计尤其有用。

接口类型

接口类型描述了一系列方法集合,io.Writer接口类型是用得最广泛的接口之一。我们可以看看这些接口类型:

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

我们可以看到一个行为一个接口,Go语言标准库中有很多这样的写法,主要考虑点:各个细粒度接口类型可以根据开发者的需要灵活的组合,形成强大的数据对象。例如:

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

通过这个,我来说一个很实用的小trick。问题描述:判断一个数据对象是否具有某个指定的方法?

func writeString(w io.Writer, s string) (n int, err error) {    type Writer interface{        WriteString(string) (int, error)    }    if sw, ok:= w.(Writer); ok {        return sw.WriteString(s)    }     return w.Write(s)}

正因为Go语言的接口是隐式实现的,所以这带来很非常大的方便。

实现接口的条件

一个类型如果拥有一个接口所需要的所有方法,则这个类型就实现了这个接口。接口指定的规则:

var w io.Writerw = os.Stdoutw = new(bytes.Buffer)var rwc ReadWriteCloserw = rwc // ... 接口对象可以赋值给接口对象,编译时不会报错,如果接口对象内存值为nil,则会在运行时panic。

这里说一个:临时变量不能寻址: IntSet{}.String() ,编译报错。var set IntSet; set.String(), 编译成功。

后者编译通过,是编译器会按照类型声明进行数据对象的隐式改变。但是下面这种编译器会报错:

var s IntSetvar _ fmt.Stringer()  = &s // compile okvar _ fmt.Stringer() = s // compile error

接口类型封装和隐藏数据对象的方法和值。即使具体类型有其他的方法也只能通过接口类型暴露出来的方法能够被调用到:

os.Stdout.Write([]byte("hello,world")var w io.Writerw = os.Stdout  // os.Stdout有Writer、Reader和Close接口w.Close() // complie error

如果一个接口类型的方法集是空的,那么这个接口的数据对象能够接收任何数据类型,且通过断言来校验你想要的类型数据对象。

接口很多初学者要犯的错

我在Github上看到过很多项目有过这样类似的校验:

func main() {    var a *int    var b interface{}    b = a    if b == nil {        fmt.Println("b is nil")    } else {        fmt.Println("b is non-nil")    }}

请问上面的输出是什么?, Github上很多开发者会回答:b is nil

接口数据对象接口值是由类型和类型值两部分构成的,上面这个例子,b是有类型的int类型的指针。只是接口值是nil。如果你要校验原始的数据对象是否为nil,有两种做法:

  • 第一种,通过反射reflect校验
  • 第二种,通过类型值校验
value := reflect.ValueOf(b)if value.IsNil() {    fmt.Println("b is actually nil value")}

第二种:

var NilPtr = (*int)(nil)if b == NilPtr {    fmt.Println("b is actually nil value")}

转载于:https://my.oschina.net/u/3287304/blog/1557369

你可能感兴趣的文章
关于百度地图API的地图坐标转换问题
查看>>
【操作系统】设备管理(五)
查看>>
ArcObject开发时,axtoolbarcontrol中一些添加的按钮是灰色的问题
查看>>
[LeetCode] Guess Number Higher or Lower 猜数字大小
查看>>
netbeans 快捷键
查看>>
C#实现GDI+基本图的缩放、拖拽、移动
查看>>
github-ssh
查看>>
FiddlerScript学习一:改动Request或Response
查看>>
linux下dd命令详解【转】
查看>>
JS及JQuery对Html内容编码,Html转义
查看>>
在java中如何在非servlet的普通类中获取request、response、session
查看>>
Linux Rsync
查看>>
Redis实现消息队列
查看>>
2k8 32bit下载
查看>>
密码需要带特殊字符
查看>>
个人收集的java精品网站
查看>>
卫生间排风设计规范
查看>>
eclipse.ini
查看>>
sql查询表结构,过程,视图,主键,外键,约束
查看>>
范式图形辨析
查看>>