2013-01-25 151 views
2

我有代表在數據庫對象的結構,像這樣:獲取已知結構域的名稱

type Object struct { 
    Id string 
    Field1 string 
    Field2 int 
} 

,我想有一個更新數據庫中的特定領域的功能每當字段被修改,這些方針的東西:

func (self *Object) SetField1(value string) { 
    self.Field1 = value 
    database.Update(self.Id, "Field1", self.Field1) // pseudocode 
} 

有沒有辦法來代替"Field1"硬編碼字符串,我的代碼是在結構領域的排序和命名的未來變化性?

我對反射包進行了探討,能夠獲得表示我正在使用的字段的StructField會很好,但它似乎需要通過硬編碼的字段名稱字符串或結構中的字段索引(可能會更改)。

+0

如果你不知道你的字段的名稱,你將如何在數據庫中更新它? – Daniel

+0

那麼'Object'是'Foo'? –

+0

@系統 - 是的,修正了錯字。 – Chris

回答

3

您可以通過添加一個方法是這樣的驗證字符串:

func (self *Object) verify(field string) string { 
    if _, ok := reflect.TypeOf(*self).FieldByName(field); ok { 
     return field 
    } 
    panic("Invalid field name") 
} 

,然後使字符串到數據庫更新時使用它

func (self *Object) SetField1(value string) { 
    self.Field1 = value 
    database.Update(self.Id, self.verify("Field1"), self.Field1) // pseudocode 
} 

但我認爲如果你願意使用反射,那麼你最好使用一個通用的setField方法將字段接受爲字符串,並將值作爲interface{},檢查字段和值,設置值並更新數據庫。

這樣一切都是使用字符串完成的,所以它可能工作或恐慌,並且您不需要記住使用.verify()方法。

財產以後這樣的:

func (self *Object) SetField(field string, value interface{}) { 
    // verify field and value using reflection 
    // set the value using reflection 
    database.Update(self.Id, field, self.Field1) 

} 

雖然我不認爲這會在未導出下地幹活。

6

不在您談論的上下文中。它沒有作爲參數傳遞,所以你需要一些其他方式來指定哪個要發送的結構域。這裏的心理缺陷是你試圖把它設置的功能當它不是它的屬性;如其他語言所示,屬性之間的主要區別是屬性綁定到特定的字段,而您的SetField1方法綁定到整個結構。該方法不妨設置兩個字段。

一般情況下,如果你正在做場反射的東西,並且你想用字段做一些花哨的動態東西,你想使用結構標籤。例如,像這樣:

type Object struct { 
    Id string  `db:"id"` 
    Field1 string `db:"field1"` 
    Field2 int `db:"field2"` 
} 

您可以訪問這些標籤,如-A-這樣的:

package main 

import (
    "reflect" 
    "fmt" 
) 

func main() { 
    var x struct { 
     MyField int `core:"required"` 
    } 
    t := reflect.TypeOf(x) 

    for i := 0; i < t.NumField(); i++ { 
     field := t.Field(i) 
     fmt.Println(field.Name, ":", field.Tag.Get("core")) 
    } 
} 

,這不是一個真正的完整的解決方案,但是......在它的問路的問題是不可能的去做。