描述

之前一直的做法都是结构体继承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组合接口的具体场景

适合的使用场景

待续...