在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)
}
哈哈哈
使用:
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)
}