2015-10-14 26 views
1

我有地圖這種 type Store map[string]string從地圖填充一個結構與反思

從這個圖,我想填充結構。目標是,對於結構的每個字段,找到與字段名匹配的鍵,取值,並根據結構字段的類型將值轉換爲適當的結構字段類型並進行設置。

基本上地圖將包含整數,布爾值,字符串和持續時間爲字符串所以convestion應該是簡單的strconv.atoi()time.parseDuration() ...

而且,我想用結構標記指定的名稱鍵,因爲struct字段可能是camelCase,而地圖中的鍵將是這樣的「example_key」

任何想法如何做到這一點。我已閱讀了關於golang的反思,但對我來說仍然不透明。我只需要一個解釋來解決這個問題,然後我認爲我可以通過我自己來處理這個實現。

感謝

+0

這應該是一種適用於一般情況的方法嗎?如果不是這樣,約定就是在包中定義一個構造函數,然後在那裏進行賦值並返回一個新實例。它會像'func NewStoreObject(store map [string] string)StoreObject,error'。如果你正在尋找一個通用的解決方案,你會問很多。但我想我也可以解釋一下。它只是反映結構上的類型,根據字段名稱對映射進行索引,切換結構字段類型,每種情況下都有代碼進行轉換和分配。 – evanmcdonnal

+0

@evanmcdonnal您好!這不是針對一般用例,而是具體的。我現在正好在結構中使用了很多類型,所以只會對這些類型進行調整,但是我仍然需要測試reflect.Type我猜。該地圖不會作爲參數傳遞,它來自其他地方,但您建議的原型是我的想法。 –

+0

嗯,這不符合任何範例。如果您使用反射,我希望您可以使用它來確定在運行時在哪些字段上設置了哪些值。如果你編寫的代碼在編譯時聲明'thisType.Name = storeMap [「name」]''那麼你可以使用我描述的構造器類型範例,因爲每種類型都會有一個特殊情況,就像它們全部一樣有他們自己的構造函數方法,在地圖中並返回實例。如果你想像'ConvertoObject(store Store)interface {}''這樣的單一方法,那麼使用反射是合理的。 – evanmcdonnal

回答

3

爲了避免意見,我只是要作一個答案解釋這兩種方法我會選擇從一些擴展討論。一般來說,我會避免反射方法。有些情況下需要它,但大多數情況下,更詳細的字面簡單代碼會更好,即使它只有幾行,並且方法之間有一些重疊。

因此,從簡單的例子開始。假設你有3種類型,GroceryStore,ComputerStoreCornerStore。在每種類型被定義的任何包中,定義一些類似構造函數的方法是相當常見的(它們在技術上不是構造函數,只是實例化一個類型並返回它但具有相同目的的包範圍方法)。所以一個例子是;

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不能被識別?那麼其他所有可能的錯誤怎麼辦?是普遍的地方?)。

+0

非常感謝您的明確答覆。我理解了這個方法,並且在這個解釋中我的頭腦更加簡潔。 –

+1

RE:構建一個通用的方法 - 使用https://github.com/mitchellh/mapstructure之類的東西可能會更好,而不是滾動自己的東西。反射包可能易碎(由於其本質)。 – elithrar

+0

@elithrar這看起來正是我所需要的。我會研究這個以增加接受的答案。謝謝! –