深入理解Golang接口(一)

 go教练   2019-07-15 13:47   89 人阅读  0 条评论

interface 介绍

如果说goroutine和channel是Go并发的两大基石,那么接口是Go语言编程中数据类型的关键。在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口Go语言中所有数据结构的核心

Go不是一种典型的OO语言,它在语法上不支持类和继承的概念。

没有继承是否就无法拥有多态行为了呢?答案是否定的,Go语言引入了一种新类型—Interface,它在效果上实现了类似于C++的“多态”概念,虽然与C++的多态在语法上并非完全对等,但至少在最终实现的效果上,它有多态的影子。

虽然Go语言没有类的概念,但它支持的数据类型可以定义对应的method(s)。本质上说,所谓的method(s)其实就是函数,只不过与普通函数相比,这类函数是作用在某个数据类型上的,所以在函数签名中,会有个receiver(接收器)来表明当前定义的函数会作用在该receiver上。

Go语言支持的除Interface类型外的任何其它数据类型都可以定义其method(而并非只有struct才支持method),只不过实际项目中,method(s)多定义在struct上而已。 从这一点来看,我们可以把Go中的struct看作是不支持继承行为的轻量级的“类”。

从语法上看,Interface定义了一个或一组method(s),这些method(s)只有函数签名,没有具体的实现代码(有没有联想起C++中的虚函数?)。若某个数据类型实现了Interface中定义的那些被称为"methods"的函数,则称这些数据类型实现(implement)了interface。这是我们常用的OO方式,如下是一个简单的示例

 微信截图_20190715094624.png

Why Interface

为什么要用接口呢?在Gopher China 上的分享中,有大神给出了下面的理由:

writing generic algorithm (泛型编程)

hiding implementation detail (隐藏具体实现)

providing interception points

下面大体再介绍下这三个理由

writing generic algorithm (泛型编程)

严格来说,在 Golang 中并不支持泛型编程。在 C++ 等高级语言中使用泛型编程非常的简单,所以泛型编程一直是 Golang 诟病最多的地方。但是使用 interface 我们可以实现泛型编程。

 微信截图_20190715094655.png

hiding implementation detail (隐藏具体实现)

隐藏具体实现,这个很好理解。比如我设计一个函数给你返回一个 interface,那么你只能通过 interface 里面的方法来做一些操作,但是内部的具体实现是完全不知道的。

例如我们常用的context包,就是这样的,context 最先由 google 提供,现在已经纳入了标准库,而且在原有 context 的基础上增加了:cancelCtx,timerCtx,valueCtx。

刚好前面我们有专门说过context,现在再来回顾一下

 微信截图_20190715094800.png

表明上 WithCancel 函数返回的还是一个 Context interface,但是这个 interface 的具体实现是 cancelCtx struct。

// newCancelCtx returns an initialized cancelCtx.
 func newCancelCtx(parent Context) cancelCtx {
 return cancelCtx{
 Context: parent,
 done: make(chan struct{}),
 }
 }
 
 // A cancelCtx can be canceled. When canceled, it also cancels any children
 // that implement canceler.
 type cancelCtx struct {
 Context //注意一下这个地方
 
 done chan struct{} // closed by the first cancel call.
 mu sync.Mutex
 children map[canceler]struct{} // set to nil by the first cancel call
 err error // set to non-nil by the first cancel call
 }
 
 func (c *cancelCtx) Done() <-chan struct{} {
 return c.done
 }
 
 func (c *cancelCtx) Err() error {
 c.mu.Lock()
 defer c.mu.Unlock()
 return c.err
 }
 
 func (c *cancelCtx) String() string {
 return fmt.Sprintf("%v.WithCancel", c.Context)
 }

尽管内部实现上下面三个函数返回的具体 struct (都实现了 Context interface)不同,但是对于使用者来说是完全无感知的。

 微信截图_20190715094811.png

以上就是今天给大家介绍的深入理解Golang接口),如果你还想了解更多关于go语言的知识技巧,可以继续关注我们http://www.fastgolang.com

本文地址:http://fastgolang.com/98.html
版权声明:本文为原创文章,版权归 go教练 所有,欢迎分享本文,转载请保留出处!

 发表评论


表情

还没有留言,还不快点抢沙发?