接口在golang中非常重要,作为一个go语言小白,在学习完基础知识后尝试通过阅读源码来提升对go语言基础知识的掌握。最近在尝试看一个开源软件(github.com/kelseyhightower/confd 版本0.19.2)的源码时注意到golang中接口的实现有些不理解,查了一些资料才知道这是非常自然的事情。一般情况下示例代码中接口的不同实现类项名都是不一样的,但源码中类型名却是一样的,具体情况如下:
package backends定义了存储类型的接口:
type StoreClient interface {
GetValues(keys []string) (map[string]string, error)
WatchPrefix(prefix string, keys []string, waitIndex uint64, stopChan chan bool) (uint64, error)
}
在不同的后端存储中实现了这个接口,如nacos实现如下:
package nacos
type Client struct {
configClient config_client.IConfigClient
namingClient naming_client.INamingClient
group string
namespace string
accessKey string
secretKey string
channel chan int
count int
}
func (client *Client) GetValues(keys []string) (map[string]string, error) {
vars := make(map[string]string)
......
}
func (client *Client) WatchPrefix(prefix string, keys []string, waitIndex uint64, stopChan chan bool) (uint64, error) {
// return something > 0 to trigger a key retrieval from the store
......
}
存储类型为redis中实现如下:
package redis
type Client struct {
client redis.Conn
machines []string
password string
separator string
psc redis.PubSubConn
pscChan chan watchResponse
}
func (c *Client) GetValues(keys []string) (map[string]string, error) {
// Ensure we have a connected redis client
rClient, err := c.connectedClient()
.....
}
func (c *Client) WatchPrefix(prefix string, keys []string, waitIndex uint64, stopChan chan bool) (uint64, error) {
if waitIndex == 0 {
return 1, nil
}
......
}
在Go语言中,如果不同的包中出现了同名的类型或接口,可以通过在类型或接口名称前面添加包名来进行区分。
调用实例如下:
func (t *TemplateResource) setVars() error {
var err error
log.Debug("Retrieving keys from store")
log.Debug("Key prefix set to " + t.Prefix)
result, err := t.storeClient.GetValues(util.AppendPrefix(t.Prefix, t.Keys))
if err != nil {
return err
}
log.Debug("Got the following map from store: %v", result)
t.store.Purge()
for k, v := range result {
t.store.Set(path.Join("/", strings.TrimPrefix(k, t.Prefix)), v)
}
return nil
}
上述代码中通过storeClient的类型对接口中不同的存储类型进行区分。