文章目录

  • 1. 接口与依赖
  • 2. 自定义类型

1. 接口与依赖

在上一节中我们讨论Go语言的面向对象特性的时候也说了,Go语言并不支持继承,能够进行对象的封装(包括数据成员和成员函数的封装),那么这里简单说一下Go语言接口之间的依赖关系。

我们知道 C++中两个接口之间的依赖 可以通过公有/私有继承方式来实现,且有对应的标识关键字

class Programmar{public:virtual std::string WriteHelloWorld()=0; // 纯虚函数标识实现只能在子类进行
};class CxxProgrammar : public Programmar{ //标识公有继承
public:std::string WriteHelloWorld();
};std::string CxxProgrammar::WriteHelloWorld(){std::cout << "Hello World!" << std::endl;return "Hello World!";
}

在Go语言中的 接口之间的依赖关系则相比于以上语言有一些差异,先看一个声明的案例

type Programmer interface {WriteHelloWorld() string
}type GoProgrammer struct{ // 不需要显式声明接口
}func (p *GoProgrammer) WriteHelloWorld() string{ // 具体方法的实现,并绑定在GoProgrammer 的指针上return "fmt.Println(\"Hello World!\")"
}

以上Go语言的案例测试代码如下:

package interface_testimport ("testing"
)type Programmer interface {WriteHelloWorld() string
}type GoProgrammer struct{ // 不需要显示指定继承实现
}func (p *GoProgrammer) WriteHelloWorld() string{ // 只需要方法签名一样,即可实例化父类的成员,不需要显式声明return "fmt.Println(\"Hello World!\")"
}func TestInterface(t *testing.T) {var p Programmer // 创建一个基类(C++的描述,Go语言中叫做interface)p = new(GoProgrammer) // 用派生类初始化该对象t.Log(p.WriteHelloWorld())
}

最终如上测试代码的输出:

=== RUN   TestInterfaceinterface_test.go:25: fmt.Println("Hello World!")
--- PASS: TestInterface (0.00s)

综上总结,Go语言的接口和其他语言的主要差异如下:

  • 接口为非侵入性,实现不依赖于接口的定义
  • 接口的定义可以包含在接口的使用者包内

同时Go 语言也提供了接口变量:

其中 Coder 表示是一个接口,GoProgrammar表示其实现。

2. 自定义类型

  • 自定义一个函数类型: type IntCov func(n int) int
  • 自定义一个普通类型:type MyInt int

自定义类型,尤其是函数类型能够一定程度降低代码的复杂度,让代码更易读。

如下,未添加自定义函数类型

// 计时函数 -- 计算一个函数的执行耗时
func calcTimeSpent(inner func(op int) int) func(op int) int{return func(n int) int{start := time.Now() // 开始计时ret := inner(n) // 执行函数fmt.Println("time spent :", time.Since(start).Seconds()) // 统计计时return ret}
}

可以看到函数定义部分很难区分函数的逻辑,而我们增加了自定义函数类型之后:

type IntCov func(op int) int // 自定义函数类型,简化函数逻辑
func calcTimeSpent(inner IntCov) IntCov{return func(n int) int{start := time.Now() // 开始计时ret := inner(n) // 执行函数fmt.Println("time spent :", time.Since(start).Seconds()) // 统计计时return ret}
}

可以看到定义的函数开头部分复杂度立即降低。

完成的 统计函数耗时测试代码如下:

package interface_testimport ("testing""time""fmt"
)type IntCov func(op int) int // 自定义函数类型,简化函数逻辑
func calcTimeSpent(inner IntCov) IntCov{return func(n int) int{start := time.Now() // 开始计时ret := inner(n) // 执行函数fmt.Println("time spent :", time.Since(start).Seconds()) // 统计计时return ret}
}func slowTest(op int) int {time.Sleep(time.Second * 1) // sleep 1秒return op
}func TestSpentTime(t *testing.T) {sp := calcTimeSpent(slowTest) // 传入耗时函数t.Log(sp(10))
}

输出如下:

=== RUN   TestSpentTime
time spent : 1.000234077interface_test.go:47: 10
--- PASS: TestSpentTime (1.00s)

Go 分布式学习利器(10)-- Go语言的接口相关推荐

  1. Go 分布式学习利器(14)-- Go语言的错误处理

    1. Go 的错误机制 Go 语言的错误机制中与其他语言的主要差异如下: 没有异常机制 error 类型实现了 error接口 type error interface {Error() string ...

  2. Go 分布式学习利器(13)-- Go语言的多态

    文章目录 1. 基本的多态实现 2. 空接口与断言 3. Go接口的最佳实践 1. 基本的多态实现 我们知道C++中实现多态是通过虚函数表 和 继承来 实现的. 类似如下代码: class Progr ...

  3. Go 分布式学习利器(11)-- Go语言通过单链表 实现队列

    一个小实验,将之前学习的Go相关的语法做个总结. 包括: Go语言接口特性 Go语言封装特性 Go语言 变量,指针,函数 语法 GO语言 条件和循环语句 的语法 GO语言的测试程序 通过链表实现一个队 ...

  4. Go 分布式学习利器(12)-- Go语言的扩展和复用

    Go语言无法天然支持继承,但是又想要实现面向对象的特性. 即父类对象 使用子类对象初始化,那么该父类对象调用的函数就是子类实现的函数 ,从而满足LSP(子类交换原则). 案例一: Go语言 支持扩展父 ...

  5. Go 分布式学习利器(9)-- Go语言 结构体的行为定义和实现

    文章目录 1. Go语言的结构体 -- 数据成员的封装 2. Go (函数成员)行为的定义和实现 1. Go语言的结构体 – 数据成员的封装 Go语言官方给的描述是 既是面向对象语言,也不算面向对象语 ...

  6. Go: 分布式学习利器(2)-- Go中的变量,常量 以及与其他语言变量之间的差异

    文章目录 1. Go 语言编写测试代码 2. Go 的变量 3. Go 常量定义 1. Go 语言编写测试代码 源码文件以 _test结尾: xxx_test.go 测试方法名需以Test开头: fu ...

  7. Go 分布式学习利器(16) -- go中可复用的package构建

    通过本文,你将了解go 语言中如何将自己的package构建到项目中 以及如何将远程(github)的package构建到项目中. 1. 构建本地的package package 是可复用模块的基本单 ...

  8. Go 分布式学习利器(20)-- Go并发编程之多路选择和超时控制,channel的关闭和广播

    Select 多路选择 基本使用语法如下: select {case ret := <-retCh1: //阻塞事件,等待channel1的消息t.Logf("result %s \n ...

  9. Go 分布式学习利器(17)-- Go并发编程之协程机制:Grountine 原理及使用

    文章目录 1. Thread VS Groutine 2. Groutine 调度原理 3. Groutine 示例代码 关于Go的底层实现还需要后续持续研究,文中如有一些原理描述有误,欢迎指证. 1 ...

最新文章

  1. 3000多种细菌大迁徙,就发生在你买菜接过钞票的一瞬间
  2. H3C交换机配置本地和远程登录用户名和密码
  3. 使用verilog设计实现QR分解
  4. mysql创建管理密码_mysql 创建用户与授权、修改密码
  5. 判断js中数据类型 的最短代码
  6. 1._请写出5种以上的android中界面常用布局方式,跳槽季“充电宝”Android面试题(一)...
  7. Win10系统开机任务栏一直转圈怎么解决
  8. Python赋值语句浅析
  9. 谭晓生大闹中国计算机中心,360高管谭晓生不满中国计算机大会拖堂和临时加议程,现场摔话筒发飙...
  10. python多态实例_Python多态实例详解
  11. 【原文件】辞海(第六版彩图本) pdf
  12. x86 x64 IA64的关系和区别
  13. 熵增定律:企业和个人发展的终极规律
  14. CentOS7安装Chrome浏览器
  15. 计算机维修培训教材,计算机芯片级维修--芯片级维修培训教材.doc
  16. [PR] 关于Adobe Premiere Pro CS6 中文乱码的问题(怎么选中文字体?)
  17. 全面比较Aptos和Sui:Aptos已上线 来看看Sui
  18. firefly-rk3288j开发板 eDP实验之NV101WXM-N51显示屏驱动
  19. 借助智能手机应用程序和可穿戴设备在夏季塑造身材
  20. java linkedblockingqueue_Java LinkedBlockingQueue take()用法及代码示例

热门文章

  1. JS简单实现自定义右键菜单
  2. ubuntu下安装 python 常用软件
  3. HDU——1106排序(istringstream的使用、STLvector练习)
  4. jquery 设置css样式
  5. LTE QCI分类 QoS
  6. 数据结构编程实战汇总
  7. 一些可能没用过的调试窗口
  8. 试用最新版本的live writer发一篇日志看看
  9. python制作图形化界面_python图形化界面设计(wxpython)一布局管理
  10. 中文 查询_查询商标,商标注册通过分析的几个小技巧