2017-05-24 144 views
0

我想申請依賴注入我的代碼,所以我創建它的每個部分作爲服務。類型斷言恐慌

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 

回答

3

當你從一個函數返回一個BaseInterface,參考的類型實際上BaseInterface,而不是SetupService是。確實SetupService確實滿足BaseInterface,但是在投射時該類型信息會丟失。

你可以做的是這樣的:

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

但有一件事要注意的是,你不使用指針,所以每個方法調用複製對象和狀態突變不會保留。您可能要替換這些:

func (s SetupService) ... 

有了這些:

func (s *SetupService) ... 

更新:爲什麼不避免返回此處設置的結果呢?

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

Go沒有繼承的概念 - 不知道你是什麼意思或我自己編輯答案。 – Adrian

+0

謝謝。它解決了我的問題,但由於額外的一項功能/每項服務,我感到很難過。 – PumpkinSeed

+0

@阿德里安:我們在這裏分開毛髮,但我會重新措辭,以便它在學術上是正確的。 – robbrit