2017-05-24 9 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関数を呼び出します。そして、なぜ私はこのパニックを得た:あなたは関数からBaseInterfaceを返すとき

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ないSetupServiceです。 SetupServiceBaseInterfaceを満たしていますが、キャストするとそのタイプ情報は失われます。しかし注意すべき

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

ありがとうございます。それは私の問題を解決しましたが、私は余分な1つの機能/各サービスのために悲しいです。 – PumpkinSeed

+0

@Adrian:私たちはここで髪を分割していますが、私はそれがpedantically正しいように言い換えるでしょう。 – robbrit