2013-01-25 110 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")) 
    } 
} 

,这不是一个真正的完整的解决方案,但是......在它的问路的问题是不可能的去做。