类型断言恐慌

时间:2017-05-24 18:55:20

标签: go type-assertion

我想在我的代码上应用依赖注入,所以我将它的每一部分都创建为服务。

type BaseService struct {
    Config config.Container
    SQL    *gorm.DB
    Mongo  *mgo.Session
    Logger logger.Logger
}

type BaseInterface interface {
    Set(c config.Container, sq *gorm.DB, m *mgo.Session, l logger.Logger) BaseInterface
}

func (s BaseService) Set(c config.Container, sq *gorm.DB, m *mgo.Session, l logger.Logger) BaseInterface {
    s.Config = c
    s.SQL = sq
    s.Mongo = m
    s.Logger = l
    return s
}

func NewSetupService(c config.Container, s *gorm.DB, m *mgo.Session, l logger.Logger) SetupService {
    return SetupService{}.Set(c, s, m, l).(SetupService)
}
...
...

有BaseService,每个服务都将其扩展为以下内容:

type SetupService struct {
    BaseService
}

type SetupInterface interface {
    Do()
}

func (s SetupService) Do() {
    mongo := s.Mongo.Clone()
    defer mongo.Close()
    mongoDB := mongo.DB(s.Config.Database.Mongo.DB)
...
...

但是当我调用NewSetupService函数时,我得到了一个恐慌,这对我来说并不清楚。基本上我创建了一个SetupService {}并调用了这个结构的Set函数,对不对?那为什么我会感到恐慌:

panic: interface conversion: api.BaseInterface is api.BaseService, not api.SetupService [recovered]
    panic: interface conversion: api.BaseInterface is api.BaseService, not api.SetupService

1 个答案:

答案 0 :(得分:3)

从函数返回BaseInterface时,引用的类型实际为BaseInterface而不是SetupService。确实,SetupService确实满足BaseInterface,但是在您投射时类型信息会丢失。

你能做的是:

func (s SetupService) Set() SetupService {
  s.BaseService.Set()
  return s
}

有一点需要注意的是,您没有使用指针,因此每个方法调用都会复制对象,并且不会保留状态突变。您可能想要替换这些:

func (s SetupService) ...

有了这些:

func (s *SetupService) ...

更新:为什么不避免返回Set here的结果?

s := SetupService{}
s.Set(...)
return s