Go中的接口层次结构

I have a program where multiple types of modules are used, but all the different types of modules share certain methods. I'm trying to build a generic factory that can be reused for the different types of modules, but I'm missing something like interface inheritance or however that would be called in Go.

This is an example that I tried to simplify as good as possible:

There is a generic factory which uses a generic Module interface:

package main

var (
  modules []Module
)

type Module interface {
  RegisterFlagSet()
  GetName() (string)
}

type Factory struct {
  instances []Module
}

func RegisterModules(modules []Module) {
  modules = modules
}

func (f *Factory) registerFlagSets() {
  for _,inst := range f.instances {
    inst.RegisterFlagSet()
  }
}

func (f *Factory) GetInstance(seek string)(Module) {
  for _,inst := range f.instances {
    if (inst.GetName() == seek) {
      return inst
    }
  }
  panic("cannot find module")
}

Then there's a more specific implementation for the module type Timer. I'm trying to reuse as much of the factory as possible:

package main

import (
  "time"
)

var (
  timer_modules = []Timer{
    // list all the timer modules here
  }
)

type Timer interface {
  Module
  GetTicker() (*time.Ticker)
}

type TimerFactory struct {
  Factory
}

func NewTimerFactory() TimerFactory {
  tfact := TimerFactory{}
  RegisterModules(timer_modules)
  return tfact
}

When I try to build that I get this error:

timer_factory.go:25: cannot use timer_modules (type []Timer) as type []Module in argument to RegisterModules

I don't understand why a variable of type []Timer cannot be used as type []Module because all the methods of the interface Module are also in the interface Timer, so they should be compatible or not? Is there a way to make them compatible?

Change your declaration of Timer

type Timer interface {
  Module
  GetTicker()(*time.Ticker)
}

https://golang.org/doc/faq#convert_slice_of_interface gives explanations. One of the workarounds is to implement a new register function:

func RegisterModule(m Module) {
  modules = append(modules, m)
}

and invoke the function in a range at the cost of only two more lines:

func NewTimerFactory() TimerFactory {
  tfact := TimerFactory{}
  for _, t := range timer_modules {
    RegisterModule(t)
  }
  return tfact
}