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 会很好,但它似乎需要通过硬编码字符串的字段名称,或者结构中字段的索引(可能会更改)。

4

2 回答 2

6

不在你所说的上下文中。它不是作为参数传入的,因此您需要一些其他方式来指定要发送的结构的哪些字段。这里的心理差距是你试图把这个集合函数当作一个属性来对待,而实际上它不是。如在其他语言中所见,属性之间的主要区别在于属性绑定到特定字段,而您的SetField1方法绑定到整个结构。该方法还不如设置两个字段。

一般来说,如果你在做字段反射的东西,并且你想用字段做花哨的动态东西,你想使用结构标签。例如,像这样:

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

您可以像这样访问这些标签:

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"))
    }
}

这并不是一个真正的完整解决方案,但是......以它的方式提出的问题是不可能的。

于 2013-01-25T04:30:52.567 回答
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方法,将字段作为字符串接受,并将值作为 a 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)

}

尽管我认为这不适用于未导出的字段。

于 2013-01-25T15:00:38.887 回答