接口定义

应该定义在接口所使用的包中,而非接口实现的包中。

以io包中的io.Reader/io.Wirter为例,接口定义在io包中,而他的实现bytes.Buffer、os.File等都是在不同包中。

接口实现应该返回具体类型

应该返回对应的结构体指针,这样实现类如果扩展新的方法就可以直接添加,无需改动接口定义部分,更加灵活。

//为了方便演示,本实例代码未遵循「接口需要在使用包中声明」规范
package demo

import "fmt"

type Demo interface {
    show() error
}

type MyDemo struct {
}

//这里的返回值应该是 `MyDemo` 或 `*MyDemo` 而非 `Demo`
func NewMyDemo() *MyDemo {
    return &MyDemo{}
}

func (md *MyDemo) show() error {
    fmt.Println("show")
    return nil
}

接口应该什么时候定义

在当前模块有依赖外部服务的时候,这时候就会定义一个接口,来对外部的依赖资源进行抽象解耦,屏蔽接口的实现。相反,依赖的提供方在不知道使用方需求的时候,定义接口也就没什么意义。