为了账号安全,请及时绑定邮箱和手机立即绑定

Go 最佳实践:具有模糊接收器的函数与方法?

Go 最佳实践:具有模糊接收器的函数与方法?

Go
芜湖不芜 2021-11-08 14:34:46
在 Go 中何时使用方法与函数的最佳实践是什么?具体来说,我有 2 个 structs: probeManagerand probeWorker,我正在编写一个run需要访问两个结构成员的函数。这可以解释为告诉管理器运行工作器,或者调用工作器上的 run 并传递管理器以进行访问,或者我可以创建一个将两者都作为参数的运行函数:func (m *ProbeManager) run(w *ProbeWorker) { ... }func (w *ProbeWorker) run(m *ProbeManager) { ... }func run(m *ProbeManager, w *ProbeWorker) { ... }由于所有 3 种方法在语义上都是有效的,因此一种方法比另一种方法有什么优势,或者这只是归结为个人喜好?
查看完整描述

2 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

使用方法允许您定义接口。假设你有:


func (m *ProbeManager) Run(w *ProbeWorker) {} 

您可以创建一个接口:


type Manager interface {

    Run(w *ProbeWorker)

}

现在任何需要的东西都*ProbeManager可以Manager代替。这Run与其实现的细节脱钩。这很有用的原因有很多:


它使代码更容易推理并且更容易安全地更改,因为它隐藏了不必要的细节(信息隐藏)

它使代码更易于测试,因为您可以模拟接口并单独测试一小段代码:


type mockManager struct {

    run func(w *ProbeWorker)

}


func (m mockManager) Run(w *ProbeWorker) {

    m.run(w)

}


func Test(t *testing.T) {

    wasCalled := false

    m := mockManager{

        run: func(w *ProbeWorker) {

            wasCalled = true

        },

    }

    // pass m to something that takes a Manager

}

接口还使您能够实现依赖注入。有很多方法,但一个非常简单的方法是提供一个Default实现:


var DefaultManager Manager = &ProbeManager{}

或者基于字符串的注册表:


var managerLookup = map[string]Manager{}


func RegisterManager(nm string, m Manager) {

    managerLookup[nm] = m

}


func GetManager(nm string) Manager {

    return managerLookup[nm]

}

这非常强大,因为它允许您修改现有包的行为而无需更改其代码。(例如,假设您有一个文件下载器并且您实现了http支持。其他人可以提供ftp支持,并且解析 URL 所需的代码不需要通过使用此注册表方法进行更改)


接口允许您实现类似的方法来解决您会在其他编程语言中发现的问题。它们为您提供了一种通用的多态性(请参阅sort包),您可以通过实现调用相同接口的接口来实现面向方面的编程或猴子修补(考虑gzip.Reader调用底层File. 的任何东西,io.Reader也可以采用 a gzip.Reader,允许您无需更改其余代码即可替换行为)


我可以继续...


查看完整回答
反对 回复 2021-11-08
?
萧十郎

TA贡献1815条经验 获得超12个赞

它们实际上都是等价的。接收者像其他所有参数一样被传递到方法中。由于无论什么(调用方法)都需要手头的两种类型,因此定义它并不重要。就个人而言,基于此,我将使用您的三个选项中的最后一个。这对我来说更有意义,因为在其他情况下,您将方法与这两种类型之一相关联,而实际上它同时需要这两种类型。不过,这只是您希望如何组织代码的问题。在性能或应用程序行为方面,两者之间没有任何好处,它们都是一样的。

编辑:最后一点。这些都不会被导出,所以它是一个“私有”或者更确切地说是一种用作包内部助手的方法。没有接收类型的更多理由。


查看完整回答
反对 回复 2021-11-08
  • 2 回答
  • 0 关注
  • 143 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信