爲了避免意見,我只是要作一個答案解釋這兩種方法我會選擇從一些擴展討論。一般來說,我會避免反射方法。有些情況下需要它,但大多數情況下,更詳細的字面簡單代碼會更好,即使它只有幾行,並且方法之間有一些重疊。
因此,從簡單的例子開始。假設你有3種類型,GroceryStore
,ComputerStore
和CornerStore
。在每種類型被定義的任何包中,定義一些類似構造函數的方法是相當常見的(它們在技術上不是構造函數,只是實例化一個類型並返回它但具有相同目的的包範圍方法)。所以一個例子是;
func NewComputerStore(store Store) *ComputerStore {
return &ComputerStore{
Name: store["Name"],
Location: store["Location"],
//ect
}
}
當然上面的例子是完全不安全的。實際上,您需要使用v, ok := myMape["key"]
語法,然後指定if ok
,如果不是,則可以執行任何操作(可能是分配默認值,日誌錯誤和拋出錯誤的某種組合)。
現在,如果你想要一個通用的方法...它通常看起來更像這樣(注意這是未經測試的,比實際示例更僞代碼);
func (s *Store) ConvertToObject(obj interface{}) error {
val := reflect.ValueOf(obj)
for int i := 0; i < val.NumField(); i++ {
switch v := val.Field(i).(type) [
case int64:
val.Field(i).SetInt(strconv.Atoi(s[val.Field(i).Name]))
}
}
}
所以上面的代碼的基本思想是這樣的。你從商店地圖開始。來電者知道該地圖應該是什麼類型。他們稱這種方法傳遞了這種類型的新實例。在這個方法中,我們並不在乎這個類型是什麼,我們關心它的類型是什麼。因此,我迭代傳入的對象上的所有字段。每個字段都通過類型切換(因爲我需要一個字符串來進行X轉換,以便每個類型存在於此方法應該使用的結構中,或者至少一個體面的基本情況),在每種類型的情況下,您可以使用字段名稱進行分配,以查找其在Store
地圖中的值並將字符串轉換爲X.
希望這是有道理的。如果它沒有明確說明方法,我可以跟進。記住上面的代碼並不是爲了運行。另外,我忽略了所有您需要的錯誤處理lot以使一個通用函數能夠工作(如果轉換失敗,該怎麼辦?如果type不能被識別?那麼其他所有可能的錯誤怎麼辦?是普遍的地方?)。
這應該是一種適用於一般情況的方法嗎?如果不是這樣,約定就是在包中定義一個構造函數,然後在那裏進行賦值並返回一個新實例。它會像'func NewStoreObject(store map [string] string)StoreObject,error'。如果你正在尋找一個通用的解決方案,你會問很多。但我想我也可以解釋一下。它只是反映結構上的類型,根據字段名稱對映射進行索引,切換結構字段類型,每種情況下都有代碼進行轉換和分配。 – evanmcdonnal
@evanmcdonnal您好!這不是針對一般用例,而是具體的。我現在正好在結構中使用了很多類型,所以只會對這些類型進行調整,但是我仍然需要測試reflect.Type我猜。該地圖不會作爲參數傳遞,它來自其他地方,但您建議的原型是我的想法。 –
嗯,這不符合任何範例。如果您使用反射,我希望您可以使用它來確定在運行時在哪些字段上設置了哪些值。如果你編寫的代碼在編譯時聲明'thisType.Name = storeMap [「name」]''那麼你可以使用我描述的構造器類型範例,因爲每種類型都會有一個特殊情況,就像它們全部一樣有他們自己的構造函數方法,在地圖中並返回實例。如果你想像'ConvertoObject(store Store)interface {}''這樣的單一方法,那麼使用反射是合理的。 – evanmcdonnal