2016-04-22 107 views
4

我試圖在兩個存儲器之間建立一箇中間層,它從存儲器A中獲取,將其轉換爲相應類型的存儲器B,然後存儲它。由於我需要轉換的約有50-100種類型,我希望使用map[string]func,並根據storageA.Type確定需要調用哪個轉換函數。接口類型返回(另一個)接口類型結構的函數

每個這些轉換功能將在存儲B.每個這些存儲器B結構的實現公共接口,這樣它們是可能的調用函數與返回不同的結構,所有的反射不同的類型。

歸結我的問題是,我不能投func(StorageAType) StorageBType1func(StorageAType) StorageBType即使StorageBtype1實現接口StorageBType

我已經創建了這個相當長的playground,因爲我意識到用單詞描述問題非常棘手。註釋掉第38-41行和第60-63行將使它運行,但它是我想要使用的那些行。對不起,它的大小,但我不明白一個不太詳細但清晰的例子。

請注意,我不得不重新創建我的計算器帳戶,所以我不認爲我有代表評論答案。

*編輯:

非常典型。只是在問我意識到如何解決它之後。通過返回轉換器功能中的接口類型而不是確切類型在此playground中進行更改。

回答

2

具有不同結果類型的函數類型是不同的類型,如果其中一個結果類型實現另一個類型,則無關緊要。 Spec: Function types:

函數類型表示集合與相同的參數和結果類型所有功能。

StorageBtype1StorageBType是不同類型的,所以它們具有的功能類型作爲其結果類型也不同,並且這些函數類型中的一個的值不能被用作用於其它的值。

簡單地改變結果類型的所有轉換器功能StorageBType

func TypeA3ToTypeB1(i StorageAType) StorageBType { 
    return StorageBType1{i.Type} 
} 

func TypeA5ToTypeB2(i StorageAType) StorageBType { 
    return StorageBType2{i.Type, i.Name} 
} 

由於所有的返回值實現StorageBType,這是一個有效的變化和需要的轉換器功能的實現沒有變化。

當然,現在調用這些函數將返回類型StorageBType的值。如果這對你來說足夠/足夠,你就沒有什麼可做的了。

萬一你需要返回的值存儲在接口值的具體類型,你可以使用type assertion

例如:

a := StorageAType{Type:3} 
b := TypeA3ToTypeB1(a) // b is of type StorageBType 
if b1, ok := b.(StorageBType1); ok { 
    // b1 is of type StorageBType1, you may use it like so: 
    fmt.Println("b1.Type:", b1.Type) 
} else { 
    // b is not of type StorageBType1, or it is nil 
} 

輸出:

b1.Type: 3 

如果你想測試很多具體的類型,你可以使用一個type switch

switch i := b.(type) { 
    case nil: 
     fmt.Println("nil") 
    case StorageBType1: 
     // Here i is of type StorageBType1, you may refer to its fields: 
     fmt.Println("StorageBType1", i.Type) 
    case StorageBType2: 
     // Here i is of type StorageBType2, you may refer to its fields: 
     fmt.Println("StorageBType2", i.Type, i.Name) 
    default: 
     fmt.Println("Unhandled type!") 
}