golang学习-------------认识golang的接口(interface)

golang从设计之初本不是一个面向对象的语言,但是为了更高效的开发,又提供了一些面向对象的能力,golang的面象对象主要就是通过interface来实现的,今天我们就来聊一聊golang的这个interface。

首先呢先聊点形式化的东西,golang的interface的设计哲学呢是靠近ducking type的,什么是ducking type呢?简单的来说,就是由使用者来定义我要用的这个东西到底是什么,这么说可能有点抽象,我们来举个例子说明一下:

非ducking type模式下,我们可能实现了一个类,然后告诉别人,我的这个类完成了什么功能,你可以调用哪些接口来实现这个功能。

而在ducking type下呢,我设计的是一个基本类,比如这个类是士兵,然后给你一个接口(类似回调之类的),让你来定义这个士兵,你给他装上机枪他就是一个机枪兵,你给他装上大炮他就是炮兵。

然而golang的interface又不是完全的ducking type,因为golang没有实现动态绑定的功能。说了这么多形式化的东西,我们来看看interface到底是个什么:

我们开始说到golang的interface是用于面向对象的,面向对象的3个基本要素继承,封装,多态。继承,封装由golang提供的struct搞定了,而interface提供的就是多态的能力,多态的能力简单来说就是一对多,多对一的能力,一对多的能力由golang的type提供了(比如 type Mytype1 int...type Mytype2 int,那么int对应了Mytype1和Mytype2),那么多对一呢?靠的就是interface。下面我们从代码来进行分析:

interface在我看来有一点点泛型+回调的味道(这是本人从应用上的一点理解,在原理上他们是没有很大的关联的),为什么这么说呢?我们来看看下面的代码:

 

package main

import (
	"fmt"	
)

type Book struct {
	Content string
}

type Sentense struct {
	Content string
}

func (b Book) PrintContent() {
	fmt.Println(b.Content)
}

func (s Sentense) PrintContent() {
	fmt.Println(s.Content)
}

type TestInterface interface {
	PrintContent()
}

func testPrintBook(ts TestInterface) {
	ts.PrintContent()
}

func testPrintSentense(ts TestInterface) {
	ts.PrintContent()
}


func main() {
	book := Book{"this is book"}
	sentense := Sentense{"this is sentense"}
	testPrintContent(book)
	testPrintContent(sentense)	
}

可以看到的是,interface实现了多对一的功能,Book和Sentense都可以通过接口来进行调用,go的官方标准的说法就是实现了interface中的函数,就相当与实现了这个interface,这就是我为什么说它有一点泛型的味道,这看起来是不是和c++的template<class T>有那么一点点像,当然这肯定和泛型有很大的区别,具体在这里就不展开了。

那么为什么又说他有那么一点点回调的味道呢?我们来扩展一下上面的代码的功能,然后拆分成几个模块,来一点点工程化的感觉,我们来简单描述下我们期望实现的功能:

我们现在希望做一个print函数,它允许使用者自己定义如何print自己相关结构的内容,比如遇到Book就print它内容的一个字,遇到Sentense就把content全print出来。

那么怎么设计呢?我们的print功能应该是一个独立的模块,它应该对外开放一个接口让使用者自己实现它需要print的东西对吧(回忆下上面讲的ducking type,是不是面向使用者的哲学就体现出来了),来看下具体代码:

首先我们在testInterface.go文件中来实现这个简单的print的功能的基本框架:

package testInterface

type PrintMethod interface {
	OwnPrintMenthod()
}

func MyPrintMethod(pm PrintMethod) {
	pm.OwnPrintMenthod()
}

OK,我们现在就可以使用MyPrintMethod来定制我们的特殊需求了,来看看我们的main.go

package main

import (
	"fmt"
	"testInterface"
)

type Book struct {
	Content string
}

func (b Book) OwnPrintMenthod() {
	fmt.Println(b.Content[:1])
}

type Sentense struct {
	Content string
}

func (s Sentense) OwnPrintMenthod() {
	fmt.Println(s.Content)
}

func main() {
	book := Book{"this is book"}
	sentense := Sentense{"this is sentense"}
	testInterface.MyPrintMethod(book)
	testInterface.MyPrintMethod(sentense)

}

这里充分体现了使用者定义的哲学,Book和Sentense分别定义了自己的Print模式,我们设计的Print模块负责基本功能的实现,看到这里如果学c/c++的同学应该会联想到回调吧,因为c/c++实现这种功能最简单的就是回调函数了,在stl中也广泛的体现了这种设计哲学。

本人对于golang的学习也还不够深入,如果有什么错误的理解欢迎指正

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值