duck typing 问题

来源:1-2 duck typing的概念

lieh1203

2022-08-08 14:33:42

问题描述:

老师你好,之前老师讲的深度讲解Go语言课程我也上过,学了好几个月了,就是这块duck type不太能理解,网上也查了很多资料,还是有点模棱两可的。


1、go语言接口由使用者定义,而传统的是由接口的实现者定义的,这块能再解释一下好处吗?

2、传统的接口实现,例如由team的leader定义好interface,然后再定义一个函数,参数是这个定义好的接口类型,最后team的不同成员去实现接口,使用的时候就把instance传入到该函数不也是实现解耦了吗?那对比go语言的duck type,好处到底在哪里?


您能否通过代码片段和使用场景讲解一下吗?在实际项目开发中怎么去灵活运用duck type,我也反复琢磨老师的代码,总感觉没抓到核心思想。


比如说下面这段代码,BigDuck和SmallDuck是两个不同的实现类,如果使用了duck type,我能想到的好处就是:如果Duck接口名称换了一个名,只要把downloader方法的参数类型换一下就行,而两个实现类不用去改代码,那还有其他什么情况下因为使用了duck typing而解耦了?

不好意思,问题提的有点乱,希望老师能解答一下,谢谢


相关代码:

type Duck interface {
   Get(url string) string
}

type SmallDuck  struct {

}

func (SmallDuck ) Get(url string) string {
   return url
}

type BigDuck  struct {

}

func (BigDuck ) Get(url string) string {
   return url
}

func downloader(p Duck)  {
   print(p.Get("https://www.baidu.com/"))
}

func main() {
   var p Duck
   p = SmallDuck{}
   //p = BigDuck{}
   downloader(p)
}



写回答

2回答

ccmouse

2022-08-09

我们看个本课程项目的具体例子:

https://git.imooc.com/class-108/coolcar/src/master/server/auth/auth/auth.go

这里我们定义了

type OpenIDResolver interface {

Resolve(code string) (string, error)

}

在Go语言中,接口由使用者定义,所以我们用了这个接口的能力:

openID, err := s.OpenIDResolver.Resolve(req.Code)

这个接口的实现在:https://git.imooc.com/class-108/coolcar/src/master/server/auth/wechat/wechat.go

在这个实现的地方,我们看不到OpenIDResolver的出现,它只是“碰巧”实现了一个Resolve方法。


首先"Duck typing"的坏处是实现者也不知道实现了什么接口。而具体的参数列表,函数名称等却仍然需要使用者和实现者去商讨。

但这样做的好处,

一:使得接口变小。Java的接口通常会有非常多的方法,但Go的接口鼓励方法的数量越少越好,接口是使用者定义的,所以使用者可以非常精确的只定义自己需要使用的方法。更小的接口带来了更低的耦合度。

二:从代码的依赖来说,wechat/wechat.go不需要依赖接口的定义就能实现接口。使得代码中减少import,进而减少诸如循环依赖,增加编译速度等。


1
hieh1203
回复
hcmouse
hp>好的,明白了

h022-08-20
共3条回复

lieh1203

提问者

2022-08-08

上面的代码贴的有问题,重新上传一下

package main



type Duck interface {

Get(url string) string

}


type SmallDuck  struct {


}


func (SmallDuck ) Get(url string) string {

return url

}


type BigDuck  struct {

}

// python js

//duck typing



func (BigDuck ) Get(url string) string {

return url

}


func downloader(p Duck)  {

print(p.Get("https://www.baidu.com/"))

}


func main() {

var p Duck

p = SmallDuck{}

//p = BigDuck{}

downloader(p)

}


0

0 学习 · 1399 问题

查看课程