描述
之前一直的做法都是结构体继承interface,duckType嘛。偶尔发现把interface组合到Struct的
type service interface {
name() string
SetName(name string) error
}
type Ducky struct {
service
}
//func (duck *Ducky) name() string {
// return "duck"
//}
var _ service = &Ducky{}
func TestCombineInterface(t *testing.T) {
defer func() {
err := recover()
if err != nil {
t.Log(err)
}
}()
duck := Ducky{}
name := duck.name()
t.Log(name)
t.Log("End")
}
从 var_ service =&Ducky{} 可以看到 Ducky 实现了service接口的方法,然而 并没有实现,会报空指针异常。
runtime error: invalid memory address or nil pointer dereference
同理如果把duck实例传入下面的方法也是没问题的,duck确实是service类型,只是name方法没有实现而已。
func FindName(s service) string {
fmt.Println("FindName")
return s.name()
}
但是,这有什么用了,感觉挖了个坑。接口完整性检查 也没法确定方法是不是真的实现了。
对比之下,用继承的方法,做完整性检查可以强制用户实现接口的所有方法!
type Jacky struct {
}
func (j *Jacky) name() string {
return "jacky"
}
func (j *Jacky) SetName(name string) error {
j.SetName(name)
return nil
}
var _ service = &Jacky{}
先关的,name()方法是私有的,包外就不能实现Service接口
type Gogo struct {
nickName string
}
func (g *Gogo) SetName(name string) error {
g.nickName = name
return nil
}
func (g *Gogo) name() string {
return g.nickName
}
另外,如果Struct实现接口的时候,receiver是指针。把它的实例传给以对应接口为入参的方法时。需要获取地址。
例如下面的SetName方法
package ky
import "fmt"
type Service interface {
name() string
SetName(name string) error
}
type Ducky struct {
Service
}
type Jacky struct {
}
func (j *Jacky) name() string {
return "jacky"
}
func (j *Jacky) SetName(name string) error {
j.SetName(name)
return nil
}
func (duck *Ducky) name() string {
return "duck"
}
func SetName(s Service, name string) error {
fmt.Println("FindName")
return s.SetName(name)
}
func checkName() {
duck := Jacky{}
err := SetName(&duck, "Jacky")
if err != nil {
fmt.Println(err)
}
}
到现在,其实也不确定Struct组合接口的具体场景
适合的使用场景
待续...