Go工厂方法返回类型接口,而不是实现接口的struct

时间:2016-01-22 19:14:13

标签: go interface factory-method

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

以下是一些示例代码,用于说明我使用的模式。

// 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

当我尝试访问我的结构中未在界面中定义的字段时,出现错误:

f.Name undefined (type Foo has no field or method Name)

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

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

1 个答案:

答案 0 :(得分:2)

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

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

f.(RealFoo).Name

或者,如果它不是RealFoo

,以避免恐慌
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
}

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

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