golang的interface(第二篇) - 接口的作用

2017/08/04

golang的interface(第一篇) - 接口的定义与实现里面,我稍微讲了一下我理解的什么是接口,怎么定义接口,怎么实现接口,本文将会讲一讲接口的作用。

接口作为参数代表什么

如果一个函数的参数类型是一个接口,代表:在使用这个函数的时候,可以传进来一个实现了这个接口的类型。

比如一个接口的参数类型是「跑」(runType),不管他是跑到哪里,跑多久,是要一个对象可以跑,那这个对象就可以使用这个函数。

接口作为参数可以做什么

将对象一般行为抽象出来,作为接口,例如:

io.Writer

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

代表了所有可以写入字节的抽象,比如:文件,缓冲,http,hasher。

只要一个类型实现了io.Writer接口,那他就可以去写。(具体怎么写在这个接口实现的方法里详细定义了。)

我觉得自己对这个还不理解,感觉自己说了很多废话。

现在有一个方法,输入一些字节和一个对象,就会调用这个对象的写方法,叫做Print

所以,屏幕可以定义自己的展现字符的方式,日志可以定义自己存储日志的格式,http server可以定义网络返回的数据的格式,等等等等,只要这个独特的对象定义了自己的写方法,那么他就可以药药药切克闹。。

sort包示例说明

在golang内置的sort包里面,定义了一个Interface

type Interface interface {
	Len() int
	Less(i, j int) bool
	Swap(i, j int)
}

好奇怪,竟然名字就是叫做Interface

然后还定义了一个函数,接受作为参数,并将其排序

func Sort(data Interface)

所以,对于任何数据类型,你定义的乱七八糟的东西。你想要对他排序?

没问题,只要你去为这个数据类型实现Interface的接口

字符串数组 sort示例

type personName []string

func (pn personName) Len() int {
	return len(pn)
}

func (pn personName) Less(i, j int) bool {
	return pn[i] < pn[j]
}

func (pn personName) Swap(i, j int) {
	pn[i], pn[j] = pn[j], pn[i]
}

上面先定义了一个字符串数组personName,然后实现了sort包里面的Interface接口,所以可以用sort.Sort对他进行排序了

func main() {
	pn :=personName{"chen","zhao","qian","sun","li"}
	sort.Sort(pn)

	fmt.Println(pn)
}

自定义struct sort示例

type Person struct {
	Name string
	Age  int
}

type Human []Person

func (h Human) Len() int {
	return len(h)
}

func (h Human) Less(i, j int) bool {
	p1 := h[i]
	p2 := h[j]
	if p1.Age < p2.Age {
		return true
	} else if p1.Age == p2.Age {
		return p1.Name <= p2.Name
	}
	return false
}

func (h Human) Swap(i, j int) {
	h[i], h[j] = h[j], h[i]
}

嗯,上面定义了一个人类的对象,然后他们排序的时候先比较年龄,再比较名字。

func main() {
	h := Human{
		Person{Name: "chen", Age: 24},
		Person{Name: "zhao", Age: 24},
		Person{Name: "qian", Age: 26},
	}
	sort.Sort(h)

	fmt.Println(h)
}
[{chen 24} {zhao 24} {qian 26}]

怎么实现逆向排序

sort 逆向排序

这个函数支持输入一并返回一个``接口,但是返回的那个的接口的方法被修改了

func Reverse(data Interface) Interface {
	return &reverse{data}
}
type reverse struct {
	Interface
}

在sort里面,定义了这样一个未导出的接口reverse,他使用了一个 重要的概念:组合 ,他本身并没有声明任何方法,但是呢,他内嵌了一个Interface接口,所以他就自动声明了Interface接口的所有方法!!

所以,如果你在你的代码里面对一个数据类型实现了Interface接口,那么实际上,你也隐式地实现了未导出的接口reverse接口。

更为神奇的是:他在你实现了这些接口之后,改变了你所定义的意义。

看一看sort里的实现:

func (r reverse) Less(i, j int) bool {
	return r.Interface.Less(j, i)
}

哈哈哈😁,Less反过来了

使用:

func main() {
	h := Human{
		Person{Name: "chen", Age: 24},
		Person{Name: "zhao", Age: 24},
		Person{Name: "qian", Age: 26},
	}
	//sort.Sort(h)
	sort.Sort(sort.Reverse(h))
	fmt.Println(h)
}