和许多面向对象的编程语言一样,Golang
也存在interface
接口这样的概念。interface
相当于是一个中间层,下游只需要关心interface
实现了什么行为,利用这些行为做些业务级别事情,而上游则负责实现interface
,把这些行为具象化。本文就来通过一个简单的缓存cache
模块的实现,来示范一下Golang
的interface
该怎么用。
首先,从业务service
角度而言,一个cache模块可能需要以下几种方法:
- 获取缓存中的某个值
- 缓存数据,加缓存时效
- 删除缓存内容
那么这些个方法,就可以用一类叫Cache
的interface
来表示:
1 | type Cache interface { |
其中,Get
方法返回一个interface{}
的value
,以及是否存在的bool
标识;Set
跟SetExpire
表示无时限跟有时限的缓存行为;Delete
表示删除缓存内容。整块Cache
的接口定义也非常明显。
这样写有什么好处?如果你是下游业务服务的话,你只需要这样写就可以了。这里给一个同package
下的测试用例代码:
1 | func TestCache(t *testing.T) { |
可以看到,我们指定的缓存对象curCache
标识为一个Cache
,是个接口定义,这样标识起来的话,下面的代码就可以正常使用Get
、Set
之类的方法了。而更重要的是,下面的代码,不会因为Cache
的具体实现变化而有所变化。举个例子,你有10个开源的缓存库,想定时切换Current() Cache
背后的缓存对象实现,就算你再怎么换,只要用到缓存的代码标注缓存对象为Cache
这个interface
,并且interface
的定义没有变化,那么使用缓存的代码就不需要动。这样,就彻底实现了缓存提供方和使用方的解耦,开发效率也会噌噌噌的上去。
既然提到了提供方Provider
的概念,那在缓存的实现上,就可以走依赖注入控制反转的模式。假设某个Web服务有个本地缓存模块,在实现上,就可以考虑提供多个Cache
接口的实现,同时在配置里指定默认的一种。这里,就以go-cache为例,做一个实现案例。
1 | import ( |
当我们定义一个GoCache
的struct
,实现了Cache
接口定义的所有行为,那么GoCache
的实例,在Golang
里,就能够被标识为一个Cache
接口实例。NewGoCache
方法,不仅是提供了一个GoCache
的实例,而在业务层面,更是提供了一个Cache
实例。因此,我们可以简单用一个map
来管理所有的Cache
的构造器,从而标识不同的缓存实现:
1 | func provideGoCache() Cache { |
显而易见,通过这样的一个代码组织,不论是go-cache
,抑或是其它的Cache
实现,都可以集中管理并灵活取用。这,便是interface
在Golang
编程中给我们带来的便利了。