Go 工厂方法返回类型接口(interface),而不是实现接口(interface)的结构

标签 go interface factory-method

我正在尝试创建一个工厂方法,该方法返回一个实现某个接口(interface)的结构的构造函数。

下面是一些示例代码,说明了我正在使用的模式。

// Generic Interface
type Foo interface {
    Bar() string
}

type FooConstructor func(name string) Foo

// A struct that implements Foo
type RealFoo struct {
    Name string
}

func (f *RealFoo) Bar() string {
    return f.Name
}

func NewRealFoo(name string) Foo {
    return &RealFoo{Name: name}
}

// Factory method to return some FooConstructor
func FooFactory() FooConstructor {
    // based on some logic, return some Foo constructor
    return NewRealFoo
}

func main() {
    ff := FooFactory()
    f := ff("baz")
    fmt.Println(f.Bar())
    fmt.Println(f.Name)
}

http://play.golang.org/p/0RzXlIGAs8

当我尝试访问接口(interface)中未定义的结构上的字段时,出现错误:

f.Name undefined(类型 Foo 没有字段或方法名称)

我认为问题在于我的构造函数 func NewRealFoo(name string) Foo 将接口(interface)作为返回类型,而不是 *RealFoo。但是为了将它用作工厂方法的 FooConstructor 类型,返回类型必须是 Foo 接口(interface)。

如何修复我的代码以便我可以访问字段 f.Name

最佳答案

您实际上返回的是 RealFoo 对象,但作为 Foo 的实现。

要获取 RealFoo 结构的字段,请使用类型断言:

f.(RealFoo).Name

或者,如果它不是 RealFoo,为了避免 panic :

if realFoo, ok := f.(RealFoo); ok {
    _ := realFoo.Name
}

或切换所有或部分可能的 Foo

类型
switch rf := f.(type) {
case realFoo:
    _ := rf.Name // rf is a realFoo
case unrealFoo:
    _ := rf.ImaginaryName // rf is an unrealFoo
case surrealFoo:
    _ := rf.SurrealName // rf is a surrealFoo
default: 
    // rf is none of the above types
}

如果您愿意修改您的工厂构造函数,您也可以从 NewRealFoo 返回一个 RealFoo,而不是 Foo。在需要 Foo 的任何地方使用它仍然有效,因为它实现了该接口(interface)。这就是您在 NewRealFoo 中所做的,当在返回 Foo 的函数中返回 RealFoo 时。

func NewRealFoo(name string) RealFoo {
    return &RealFoo{Name: name}
}

关于Go 工厂方法返回类型接口(interface),而不是实现接口(interface)的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34954212/

相关文章:

typescript 接口(interface)变量克隆

docker - 如何借助docker compose正确设置golang应用的第三方库?

json - json.Decode不会解码数字

function - 在函数参数中传递接口(interface)指针

c# - 如何在C#接口(interface)中实现泛型?

c# - 实现通用工厂方法

factory-pattern - 抽象工厂和工厂设计模式有什么区别?

objective-c - 工厂方法和构造函数之间的区别

io - 读取的字节数和无符号数

sql - 执行查询 sql 时出错 - Golang