当前位置: 首页 > 面试题库 >

Go函数类型,该函数类型返回与接口一起使用的结构

杨豪
2023-03-14
问题内容

我的包中有一个结构,上面有耗时的方法,通过工厂函数进行构造也很耗时。因此,在依赖于该其他结构的包中,我希望能够在创建后使用伪造的工厂函数和伪造的结构对其进行测试。由于结构是通过工厂函数构造的,因此我想伪造工厂函数,并在测试期间将替代工厂函数传递给我的结构。

昂贵的包装的一个例子是:

package expensive

import "fmt"

type myStruct struct{}

func (m *myStruct) DoSomething() {
    fmt.Println("In Do something")
}

func (m *myStruct) DoSomethingElse() {
    fmt.Println("In do something else")
}

// CreateInstance is expensive to call
func CreateInstance() *myStruct {
    return &myStruct{}
}

我的主包装使用以下代码:

package main

import "play/expensive"

func main() {
    thing := structToConstruct{expensive.CreateInstance}
    thing.performAction()
}

type myInterface interface {
    DoSomething()
}

type structToConstruct struct {
    factoryFunction func() myInterface
}

func (s *structToConstruct) performAction() {
    instance := s.factoryFunction()
    instance.DoSomething()
}

但是,此代码抱怨以下错误:

。\ main.go:6:不能在字段值中使用昂贵的CreateInstance(func()*
expensive.myStruct类型)作为func()myInterface类型

但是, expensive.myStruct 确实* 实现了myInterface接口,所以我不明白为什么Go抱怨此设置的类型安全。

自从@jmaloney指导之后,我意识到我可以像这样在我的主要方法中包装函数:

    wrapper := func() myInterface {
        return expensive.CreateInstance()
    }
    thing := structToConstruct{wrapper}

然后可以工作,但是我仍然不太明白为什么当函数期望返回该接口的实例时,尤其是在此修复程序不需要类型声明/转换的情况下,为什么不能使用实现接口的结构,如它只是在调用底层工厂函数。

编辑:从那以后我就遇到过这个提案,以将其添加到语言中。该提案被拒绝:

https://github.com/golang/go/issues/12754


问题答案:

getInstance 需要返回 myInterface

package main

import "fmt"

func main() {
    var function func() myInterface

    function = getInstance

    newSomething := function()

    newSomething.doSomething()
}

type myInterface interface {
    doSomething()
}

type myStruct struct{}

func (m *myStruct) doSomething() {
    fmt.Println("doing something")
}

func getInstance() myInterface {
    return &myStruct{}
}

操场上的例子

但是,* expensive.myStruct确实实现了myInterface接口,所以我不明白为什么Go抱怨此设置的类型安全。

在那种情况下,您不是在处理Go的接口,而是在处理结构的类型签名。

当您首次使用factoryFunction func() *myFunctionfactoryFunction 声明结构时,现在始终需要匹配声明的签名。



 类似资料:
  • 问题内容: 我想了解为什么下面的代码片段无法编译。将函数接受为可能具有任何返回类型的函数参数的Go方法是什么? 播放:https://play.golang.org/p/CqbuEZGy12 我的解决方案基于Volker的答案: 播放:https://play.golang.org/p/waOGBZZwN7 问题答案: 你绊倒了围棋新人一个非常普遍的误解:空接口并 不能 意味着“任何类型”。确实不

  • 我想使返回数据类型的的函数与传入的参数的数据类型相同。例如,我会这样调用函数: 因为我将一个传递给,所以它返回了一个

  • 主要内容:结构体实现接口,函数体实现接口,HTTP包中的例子函数和其他类型一样都属于“一等公民”,其他类型能够实现接口,函数也可以,本节将对结构体与函数实现接口的过程进行对比。 首先给出本节完整的代码: 有如下一个接口: 这个接口需要实现 Call() 方法,调用时会传入一个 interface{} 类型的变量,这种类型的变量表示任意类型的值。 接下来,使用结构体进行接口实现。 结构体实现接口 结构体实现 Invoker 接口的代码如下: 代码说明如下:

  • 问题内容: 我有一个模块分开的应用程序。有几个实体和CSV模块。CSV模块仅支持struct(Entity),但我想使CSV模块可与任何类型的实体一起使用。现在,它的工作方式如下:Csv模块从通道接收数据并将其严格转换为struct。我如何实现动态返回类型,因此它可以与任何类型的Entity一起使用,而不仅限于 问题答案: 快速/肮脏的解决方案: 返回接口{},但是您最终欺骗了编译器,而类型检查的

  • 我需要编写一个程序,它接受一个线性链表的实例,并删除列表中除最后两个项目以外的所有项目。我使用类在C++中完成了这一操作,因此我将有3个文件:main.cpp、list.h和list.cpp。不能有循环:我可以使用多个函数,但遍历部分必须是递归的。 我考虑了一下,得出的结论是:我必须有一个可以从main调用的公共函数,它不接受参数,名为void lastTwo()。我将有另一个私有函数node*l

  • 从Kotlin调用Java代码时,存在SAM转换,因此Java代码如下所示: 可以如下所示: 现在,我正在处理一个Kotlin项目,我想将功能接口定义为事件侦听器: 在SomeClass中,我有一个设置监听器的函数: 当我创建这个类的实例并尝试调用setter函数时,我是这样做的: 我知道静态编程语言有函数类型,因此不支持来自各种站点的SAM转换,例如这个站点。 我读过一些关于函数类型的书,但我以