博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go面向对象-接口
阅读量:2110 次
发布时间:2019-04-29

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

目录


一、Go 接口

1、接口的作用

接口是用来定义对象间交互的协议。

2、Duck type 式接口实现

a、什么是 Duck type

Duck type 就是鸭子类型,什么叫鸭子类型,也就是脚上有璞,身上有羽毛,嘴扁扁的, 虽然我们也不知道它是什么鸟,但是看起来像鸭子,我们就叫它鸭子。

b、接口定义

type Programmer interface {	WriteHelloWorld() string}

c、接口实现

//定义接口的数据结构type GoProgrammer struct {	Language string}//方法名和返回值都必须和接口定义的保持一致,//同时把这个方法绑定到 GoProgrammer 这个结构的指针上func (goProgrammer *GoProgrammer) WriteHelloWorld() string {	return goProgrammer.Language + " print Hello World"}

d、接口定义和实现示例

package _interfaceimport "testing"//定义接口type Programmer interface {	WriteHelloWorld() string}//定义接口的数据结构type GoProgrammer struct {	Language string}//实例的方法名和返回值都必须和接口定义的保持一致,//同时把这个方法绑定到 GoProgrammer 这个结构的指针上func (goProgrammer *GoProgrammer) WriteHelloWorld() string {	return goProgrammer.Language + " print Hello World"}//调用这个接口的实现func TestClient(t *testing.T) {	goProgrammer := &GoProgrammer{Language: "Go"}	res := goProgrammer.WriteHelloWorld()	t.Log(res)	//Go print Hello World}

结论:GoProgrammer 这个结构实现了 Programmer 这个接口 , 但是 Go 语言没有将显示的使用 implements 来进行依赖绑定, 而是使用了 duck type 的方式,只要方法名,参数和返回值是一样的 我们就认为这个实例就是 Programmer 接口的实现。

e、与其它主要编程语言的差异

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

 

二、空接口与断言

1、空接口可以表示任何类型

通过断言来将空接口转换为指定类型,而不是使用强制类型转换

//空接口转换为其它任何类型的格式//val 为转换后的结果值,当 ok==true 时,表示转换成功val, ok := empty_interface.(type)

2、调试效果

package empty_interfaceimport (	"fmt"	"testing")//空接口类型转换func ConvertEmptyInterface(p interface{})  {	if val, ok := p.(int); ok {		fmt.Printf("Empty interface convert to integer : %v\n", val)	} else if val, ok := p.(string); ok {		fmt.Printf("Empty interface convert to string : %v\n", val)	} else if val, ok := p.([2]int); ok {		fmt.Printf("Empty interface convert to array : %v\n", val)	} else if val, ok := p.([]int); ok {		fmt.Printf("Empty interface convert to slice : %v\n", val)	} else if val, ok := p.(map[int]int); ok {		fmt.Printf("Empty interface convert to map : %v\n", val)	} else {		fmt.Print("Unknow")	}}//空接口可以转换为任何类型func TestEmptyInterfaceAssertion(t *testing.T) {	number := 10	ConvertEmptyInterface(number)	//Empty interface convert to integer : 10	str := "Go"	ConvertEmptyInterface(str)	//Empty interface convert to string : Go	map1 := make(map[int]int, 10)	ConvertEmptyInterface(map1)	//Empty interface convert to map : map[]	arr := [2]int{1, 2}	ConvertEmptyInterface(arr)	//Empty interface convert to array : [1 2]	slice1 := make([]int, 3, 5)	ConvertEmptyInterface(slice1)	//Empty interface convert to slice : [0 0 0]}

3、用更简洁的 switch 来实现

package empty_interfaceimport (	"fmt"	"testing")//空接口类型转换func ConvertEmptyInterface(p interface{})  {	// p.(type)这种写法只能用于 switch 中	switch val:= p.(type) {	case int:		fmt.Printf("Empty interface convert to integer : %v\n", val)	case string:		fmt.Printf("Empty interface convert to string : %v\n", val)	case [2]int:		fmt.Printf("Empty interface convert to array : %v\n", val)	case []int:		fmt.Printf("Empty interface convert to slice : %v\n", val)	case map[int]int:		fmt.Printf("Empty interface convert to map : %v\n", val)	default:		fmt.Print("Unknow")	}}//空接口可以转换为任何类型func TestEmptyInterfaceAssertion(t *testing.T) {	number := 10	ConvertEmptyInterface(number)	//Empty interface convert to integer : 10	str := "Go"	ConvertEmptyInterface(str)	//Empty interface convert to string : Go	arr := [2]int{1, 2}	ConvertEmptyInterface(arr)	//Empty interface convert to array : [1 2]	slice1 := make([]int, 3, 5)	ConvertEmptyInterface(slice1)	//Empty interface convert to slice : [0 0 0]	map1 := make(map[int]int, 10)	ConvertEmptyInterface(map1)	//Empty interface convert to map : map[]}

为何写这种两段式的switch语句会报错呢 (use of .(type) outside type switch)?

对于这个情况,后面的 val 有什么用呢?前面 val 已经被赋值并且可以在下面使用了。 val 的值是

类型,你可以通过 %T 来输出。

//空接口类型转换func ConvertEmptyInterface(p interface{})  {    switch val := p.(type); val {        //code    }}

 

三、Go接口最佳实践

1、倾向于使用小的接口定义,很多接口只包含一个方法

更小的接口,让接口的负担更轻,接口的复用性更高,在Go里面有很多 Single method (即只有一个方法的接口),例如像下面这样:

type Reader interface {	Read (p []byte) (num int)}type Writer interface {	Write (p []byte) (num int)}

2、较大的接口定义,可以由多个小接口定义组合而成

type ReaderWriter interface {	Reader	Writer}

3、只依赖于必要功能的最小接口

//例如我这个方法只需要用到了 Reader,就只依赖 Reader 接口,//没必要依赖 ReaderWriter 接口func GetAllReaders(reader Reader) error {	//code	return nil}

当我们定义了较小的接口后,为了发挥小接口的优势,我们使用的方法一定要尽量依赖它最小的接口,这样接口中的方法才能被更多的地方去复用。

:这篇博文是我学习中的总结,如有转载请注明出处:

上一篇

下一篇

你可能感兴趣的文章
Leetcode C++《热题 Hot 100-23》3.无重复字符的最长子串
查看>>
Leetcode C++《热题 Hot 100-24》5.最长回文子串
查看>>
Leetcode C++《热题 Hot 100-26》15.三数之和
查看>>
Leetcode C++《热题 Hot 100-27》17.电话号码的字母组合
查看>>
Leetcode C++《热题 Hot 100-28》19.删除链表的倒数第N个节点
查看>>
Leetcode C++《热题 Hot 100-29》22.括号生成
查看>>
Leetcode C++《热题 Hot 100-40》64.最小路径和
查看>>
Leetcode C++《热题 Hot 100-41》75.颜色分类
查看>>
Leetcode C++《热题 Hot 100-42》78.子集
查看>>
Leetcode C++《热题 Hot 100-43》94.二叉树的中序遍历
查看>>
Leetcode C++ 《第175场周赛-1 》5332.检查整数及其两倍数是否存在
查看>>
Leetcode C++ 《第175场周赛-2 》5333.制造字母异位词的最小步骤数
查看>>
Leetcode C++ 《第175场周赛-3》1348. 推文计数
查看>>
Leetcode C++《热题 Hot 100-44》102.二叉树的层次遍历
查看>>
Leetcode C++《热题 Hot 100-45》338.比特位计数
查看>>
读书摘要系列之《kubernetes权威指南·第四版》第一章:kubernetes入门
查看>>
Leetcode C++《热题 Hot 100-46》739.每日温度
查看>>
Leetcode C++《热题 Hot 100-47》236.二叉树的最近公共祖先
查看>>
Leetcode C++《热题 Hot 100-48》406.根据身高重建队列
查看>>
《kubernetes权威指南·第四版》第二章:kubernetes安装配置指南
查看>>