Go 将数据和函数与接口和结构相结合的组合

Go 将数据和函数与接口和结构相结合的组合,go,composition,Go,Composition,我想知道这是否是Go中完成的事情,或者我是否认为这一切都错了:编写TypeX接口和TypeX结构,这样我的接口方法也可以访问特定数据: 我的电脑中的C程序员希望这样做: type PluginHandler interface { onLoad() pm *PluginManager } func (ph PluginHandler) onLoad() { pm.DoSomething() } 在那里,我有一个用函数定义的接口,还有一些我想传递给这些函数的数据,但这是一

我想知道这是否是Go中完成的事情,或者我是否认为这一切都错了:编写
TypeX接口
TypeX结构
,这样我的接口方法也可以访问特定数据:

我的电脑中的C程序员希望这样做:

type PluginHandler interface {
    onLoad()
    pm *PluginManager
}
func (ph PluginHandler) onLoad() {
    pm.DoSomething()
}
在那里,我有一个用函数定义的接口,还有一些我想传递给这些函数的数据,但这是一个语法错误


那么,这是通过其他方法可以实现的,还是我只是在思考问题时出错了?

您错误地定义了
onLoad
。不能直接在接口类型上定义函数

一旦有了接口,就需要另一种类型来实现接口中指定的方法。例如,如果另一个类型实现了
onLoad
方法,它们会自动(隐式)实现接口
PluginHandler

您需要做的另一件事是更改接口函数类型以接受所需的数据:

type PluginHandler interface {
    onLoad(*PluginManager)
}

struct SomeType {
    // ...
}

func (s SomeType) onLoad(pm *PluginManager) { // SomeType now implements
    pm.DoSomething()                          // PluginHandler interface.
}
这样,就可以插入
PluginHandler
所需的
PluginManager

此外,您还可以在需要时将
SomeType
用作
PluginHandler
类型

func someFuntion(ph PluginHandler) {
    // ...
    ph.onLoad(pm)
    // ...
}
可以使用类型为
SomeType
的输入参数调用:

s := SomeType{}
someFunction(s)

TL;博士没有直接翻译

长答覆:

Go接口是唯一的方法

Go结构只是数据(有可能是接收器方法)

您可以在结构中引用甚至嵌入接口:

type Frobnicator interface {
    Frobnicate() error
}

type Widget struct {
    Frobnicator
    WidgetName string
}
但这不是你真正要说的

我相信,对你的困境最好的回答是:退后一步。你关注的是树木,你需要看看森林。GO采用与C不同的方法,或者经典的OO语言,如C++和java。
看看要解决的一般问题,并在围棋中找到解决方案。这可能是一个痛苦的过程(我可以从经验中说),但这确实是学习新思维方式的唯一途径。

为了记录在案,您可以通过引入另一种(间接)类型向现有类型添加额外的方法,如下所示:

如果您需要使用更通用的解决方案,那么适配器和策略模式的组合可以做到:

type PluginHandlerAdapter struct{ _onLoad func() }

func (x *PluginHandlerAdapter) onLoad() {
    x._onLoad()
}
使用方式类似(忽略公共/私人访问):


非常感谢。这太完美了。我现在已经为我的应用程序安装了一个插件系统:)你能指出一些参考资料或方便的书来阅读OO哲学如何适合golang吗?。我们同意,OO哲学不附属于任何语言,因为它应被视为研究和定义系统中的组件及其关系的精神工具,所有这些都有利于实现正确的抽象。正如你提到的,golang提倡以自己独特的方式思考。。但与OO世界并没有完全不同。例如:接口的概念与java中的概念完全相同(在版本8之前)。。。但是多态性仅限于工作接口(在java中,也可以使用类来实现)。而且,结构没有层次结构。。他们确实有结构嵌入以便于代码重用,但这不是层次结构。。。。无论如何我开始重新考虑一些事情…我不确定你想要什么样的推荐信。Go故意明确地不是一种OO语言。它确实具有OO语言中的一些共同特征,因此可以通过一些相同的方法完成一些相同的任务。但这并不意味着它是一种OO语言,正如你所说的,golang的一部分理念是建立在OO原则之上的,在golang中使用接口与java非常不同。首先,不需要隐式声明一个抽象实现了一个接口,与java相反(您需要键入“implements someInterfaceIdentifier”)。其次,在java中,后缀“able”是推荐用于接口的术语,在golang中,推荐的后缀是“er | or”.第一种是perphahs以被动的方式描述对象,第二种是以主动的方式描述对象(Readable vs Sourcer,两者都是源代码),我有更多的半生不熟的想法…我想更深入地了解它…我可能需要有人谈谈这一点,并进行“基于oo的治疗”。可能会看到一些简单场景的设计,支持使用正确的golang机制重用代码(我指的是语言提供的构建块)。(例如,请参见以下问题:,当您有时间时…)
type PluginHandlerAdapter struct{ _onLoad func() }

func (x *PluginHandlerAdapter) onLoad() {
    x._onLoad()
}
type PluginManager struct {
    PluginHandlerAdapter
}

func NewPluginManager() *PluginManager {
    res := new(PluginManager)
    res._onLoad = res.DoSomething
    return res
}